{"model_name":"gpt-5.4-nano-high","codes":{"1":{"ahc001":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\n\nstruct Company {\n    int x, y;\n    ll r;\n};\n\nstruct Rect {\n    int a, b, c, d; // [a,c) x [b,d)\n};\n\nstruct Candidate {\n    int k;       // cut position (x=k for vertical, y=k for horizontal)\n    ll cost;     // squared cost on matching side areas\n};\n\nstatic double evalScore(const vector<Company>& comp, const vector<Rect>& rects) {\n    int n = (int)comp.size();\n    long double total = 0;\n    for (int i = 0; i < n; i++) {\n        ll s = 1LL * (rects[i].c - rects[i].a) * (rects[i].d - rects[i].b);\n        ll ri = comp[i].r;\n        ll mn = min(ri, s), mx = max(ri, s);\n        long double t = (long double)mn / (long double)mx;\n        long double p = 1.0L - (1.0L - t) * (1.0L - t); // = 2t - t^2\n        total += p;\n    }\n    return (double)total;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int n;\n    cin >> n;\n    vector<Company> comp(n);\n    for (int i = 0; i < n; i++) {\n        cin >> comp[i].x >> comp[i].y >> comp[i].r;\n    }\n\n    const int N = 10000;\n    vector<Rect> bestRects(n);\n    double bestScore = -1e100;\n\n    // RNG base\n    uint64_t baseSeed = chrono::steady_clock::now().time_since_epoch().count();\n    int ITER = 35; // heuristic; adjust if needed\n\n    for (int it = 0; it < ITER; it++) {\n        uint64_t seed = baseSeed ^ (uint64_t)(it * 0x9e3779b97f4a7c15ULL);\n        std::mt19937_64 rng(seed);\n\n        vector<Rect> rects(n, Rect{0,0,1,1});\n\n        function<vector<Candidate>(const vector<int>& ids, int lx, int rx, int ly, int ry, bool vertical)> getCandidates =\n            [&](const vector<int>& ids, int lx, int rx, int ly, int ry, bool vertical) -> vector<Candidate> {\n                vector<Candidate> cand;\n                int m = (int)ids.size();\n                if (m <= 1) return cand;\n                ll totalR = 0;\n                for (int id : ids) totalR += comp[id].r;\n\n                if (vertical) {\n                    if (rx - lx <= 1) return cand;\n                    vector<int> v = ids;\n                    sort(v.begin(), v.end(), [&](int a, int b){ return comp[a].x < comp[b].x; });\n\n                    // prefix sums over sorted by x\n                    vector<ll> pref(m + 1, 0);\n                    for (int i = 0; i < m; i++) pref[i+1] = pref[i] + comp[v[i]].r;\n\n                    int i = 0;\n                    while (i < m) {\n                        int xval = comp[v[i]].x;\n                        int j = i;\n                        while (j < m && comp[v[j]].x == xval) j++;\n\n                        // boundary k=xval => left: x<k => indices [0,i), right: [j,m)\n                        if (i > 0) {\n                            int k = xval;\n                            if (k > lx && k < rx) {\n                                ll leftSum = pref[i];\n                                ll leftW = 1LL * (k - lx);\n                                ll height = 1LL * (ry - ly);\n                                ll areaL = leftW * height;\n                                ll diff = areaL - leftSum;\n                                ll cost = diff * diff;\n                                cand.push_back({k, cost});\n                            }\n                        }\n                        i = j;\n                    }\n                } else {\n                    if (ry - ly <= 1) return cand;\n                    vector<int> v = ids;\n                    sort(v.begin(), v.end(), [&](int a, int b){ return comp[a].y < comp[b].y; });\n\n                    // prefix sums over sorted by y\n                    vector<ll> pref(m + 1, 0);\n                    for (int i = 0; i < m; i++) pref[i+1] = pref[i] + comp[v[i]].r;\n\n                    int i = 0;\n                    while (i < m) {\n                        int yval = comp[v[i]].y;\n                        int j = i;\n                        while (j < m && comp[v[j]].y == yval) j++;\n\n                        // boundary k=yval => bottom: y<k => [0,i), top: [j,m)\n                        if (i > 0) {\n                            int k = yval;\n                            if (k > ly && k < ry) {\n                                ll bottomSum = pref[i];\n                                ll bottomH = 1LL * (k - ly);\n                                ll width = 1LL * (rx - lx);\n                                ll areaB = bottomH * width;\n                                ll diff = areaB - bottomSum;\n                                ll cost = diff * diff;\n                                cand.push_back({k, cost});\n                            }\n                        }\n                        i = j;\n                    }\n                }\n\n                sort(cand.begin(), cand.end(), [&](const Candidate& A, const Candidate& B){\n                    if (A.cost != B.cost) return A.cost < B.cost;\n                    return A.k < B.k;\n                });\n                return cand;\n            };\n\n        function<void(int,int,int,int, const vector<int>&, int)> build =\n            [&](int lx, int rx, int ly, int ry, const vector<int>& ids, int depth) {\n                if ((int)ids.size() == 1) {\n                    int id = ids[0];\n                    rects[id] = Rect{lx, ly, rx, ry};\n                    return;\n                }\n\n                auto candV = getCandidates(ids, lx, rx, ly, ry, true);\n                auto candH = getCandidates(ids, lx, rx, ly, ry, false);\n\n                bool useV;\n                if (candV.empty()) useV = false;\n                else if (candH.empty()) useV = true;\n                else {\n                    ll bestV = candV.front().cost;\n                    ll bestH = candH.front().cost;\n                    // randomized choice weighted by inverse best cost\n                    long double wV = 1.0L / (1.0L + (long double)bestV);\n                    long double wH = 1.0L / (1.0L + (long double)bestH);\n                    long double x = (long double) (rng() % 1000000) / 1000000.0L;\n                    useV = (x < wV / (wV + wH));\n                }\n\n                int k;\n                if (useV) {\n                    // pick among top candidates with soft randomness\n                    int topK = min<int>(5, candV.size());\n                    vector<Candidate> cand2(candV.begin(), candV.begin() + topK);\n                    vector<long double> ws(topK);\n                    for (int i = 0; i < topK; i++) ws[i] = 1.0L / (1.0L + (long double)cand2[i].cost);\n                    long double sum = 0;\n                    for (auto w: ws) sum += w;\n                    long double r01 = (long double)(rng() % 1000000) / 1000000.0L;\n                    long double acc = 0;\n                    int pick = topK - 1;\n                    for (int i = 0; i < topK; i++) {\n                        acc += ws[i] / sum;\n                        if (r01 <= acc) { pick = i; break; }\n                    }\n                    k = cand2[pick].k;\n\n                    vector<int> left, right;\n                    left.reserve(ids.size());\n                    right.reserve(ids.size());\n                    for (int id : ids) {\n                        if (comp[id].x < k) left.push_back(id);\n                        else right.push_back(id);\n                    }\n                    // Safety: both sides must be non-empty and bounds must keep positive sizes\n                    if (left.empty() || right.empty() || left.size()+right.size()!=(size_t)ids.size()) {\n                        // fallback: split by median x\n                        vector<int> v = ids;\n                        sort(v.begin(), v.end(), [&](int a, int b){ return comp[a].x < comp[b].x; });\n                        int mid = (int)v.size()/2;\n                        k = comp[v[mid]].x;\n                        left.clear(); right.clear();\n                        for (int id : ids) (comp[id].x < k ? left : right).push_back(id);\n                    }\n\n                    build(lx, k, ly, ry, left, depth+1);\n                    build(k, rx, ly, ry, right, depth+1);\n                } else {\n                    int topK = min<int>(5, candH.size());\n                    vector<Candidate> cand2(candH.begin(), candH.begin() + topK);\n                    vector<long double> ws(topK);\n                    for (int i = 0; i < topK; i++) ws[i] = 1.0L / (1.0L + (long double)cand2[i].cost);\n                    long double sum = 0;\n                    for (auto w: ws) sum += w;\n                    long double r01 = (long double)(rng() % 1000000) / 1000000.0L;\n                    long double acc = 0;\n                    int pick = topK - 1;\n                    for (int i = 0; i < topK; i++) {\n                        acc += ws[i] / sum;\n                        if (r01 <= acc) { pick = i; break; }\n                    }\n                    k = cand2[pick].k;\n\n                    vector<int> bottom, top;\n                    bottom.reserve(ids.size());\n                    top.reserve(ids.size());\n                    for (int id : ids) {\n                        if (comp[id].y < k) bottom.push_back(id);\n                        else top.push_back(id);\n                    }\n                    if (bottom.empty() || top.empty() || bottom.size()+top.size()!=(size_t)ids.size()) {\n                        vector<int> v = ids;\n                        sort(v.begin(), v.end(), [&](int a, int b){ return comp[a].y < comp[b].y; });\n                        int mid = (int)v.size()/2;\n                        k = comp[v[mid]].y;\n                        bottom.clear(); top.clear();\n                        for (int id : ids) (comp[id].y < k ? bottom : top).push_back(id);\n                    }\n\n                    build(lx, rx, ly, k, bottom, depth+1);\n                    build(lx, rx, k, ry, top, depth+1);\n                }\n            };\n\n        vector<int> ids(n);\n        iota(ids.begin(), ids.end(), 0);\n        build(0, N, 0, N, ids, 0);\n\n        double sc = evalScore(comp, rects);\n        if (sc > bestScore) {\n            bestScore = sc;\n            bestRects = rects;\n        }\n    }\n\n    for (int i = 0; i < n; i++) {\n        cout << bestRects[i].a << ' ' << bestRects[i].b << ' '\n             << bestRects[i].c << ' ' << bestRects[i].d << '\\n';\n    }\n    return 0;\n}","ahc002":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const int H = 50, W = 50;\nstatic const int N = H * W;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int si, sj;\n    cin >> si >> sj;\n    vector<int> tile(N);\n    for (int i = 0; i < H; i++) {\n        for (int j = 0; j < W; j++) {\n            cin >> tile[i * W + j];\n        }\n    }\n    vector<int> p(N);\n    for (int i = 0; i < H; i++) {\n        for (int j = 0; j < W; j++) {\n            cin >> p[i * W + j];\n        }\n    }\n\n    int M = 0;\n    for (int x : tile) M = max(M, x + 1);\n\n    int start = si * W + sj;\n\n    // Neighbors (4-neighborhood) on squares\n    vector<array<int, 4>> neigh(N);\n    vector<int> deg(N, 0);\n    for (int i = 0; i < H; i++) {\n        for (int j = 0; j < W; j++) {\n            int id = i * W + j;\n            array<int,4> arr;\n            arr.fill(-1);\n            int d = 0;\n            auto add = [&](int ni, int nj) {\n                if (0 <= ni && ni < H && 0 <= nj && nj < W) arr[d++] = ni * W + nj;\n            };\n            add(i-1, j);\n            add(i+1, j);\n            add(i, j-1);\n            add(i, j+1);\n            neigh[id] = arr;\n            deg[id] = d;\n        }\n    }\n\n    // Precompute for each square: how many distinct tile-ids appear among its neighbor squares (excluding same tile).\n    vector<int> cntAdjDistinct(N, 0);\n    for (int id = 0; id < N; id++) {\n        int ti = tile[id];\n        int seen[4]; int sc = 0;\n        for (int k = 0; k < 4; k++) {\n            int nb = neigh[id][k];\n            if (nb < 0) continue;\n            int tb = tile[nb];\n            if (tb == ti) continue;\n            bool ok = true;\n            for (int q = 0; q < sc; q++) if (seen[q] == tb) ok = false;\n            if (ok) seen[sc++] = tb;\n        }\n        cntAdjDistinct[id] = sc;\n    }\n\n    auto coordOf = [&](int id) -> pair<int,int> {\n        return {id / W, id % W};\n    };\n\n    auto dirBetween = [&](int a, int b) -> char {\n        int ai = a / W, aj = a % W;\n        int bi = b / W, bj = b % W;\n        if (bi == ai - 1 && bj == aj) return 'U';\n        if (bi == ai + 1 && bj == aj) return 'D';\n        if (bi == ai && bj == aj - 1) return 'L';\n        if (bi == ai && bj == aj + 1) return 'R';\n        // Should not happen if b is a 4-neighbor of a\n        return '?';\n    };\n\n    // One random stochastic greedy walk.\n    auto runWalk = [&](mt19937_64 &rng, bool storePath) {\n        vector<char> used(M, 0);\n        vector<int> curPath;\n        curPath.reserve(M);\n\n        used[tile[start]] = 1;\n        int cur = start;\n        long long score = p[cur];\n        curPath.push_back(cur);\n\n        const double beta = 0.85;   // lookahead weight\n        const double gamma = 0.35;  // distinct-neighbor bias\n        while (true) {\n            vector<pair<int,double>> cand; // (next, value)\n            cand.reserve(4);\n            for (int k = 0; k < 4; k++) {\n                int nb = neigh[cur][k];\n                if (nb < 0) continue;\n                int tnb = tile[nb];\n                if (used[tnb]) continue;\n                int futureMax = 0;\n                // one-step lookahead from nb\n                for (int kk = 0; kk < 4; kk++) {\n                    int nn = neigh[nb][kk];\n                    if (nn < 0) continue;\n                    int tnn = tile[nn];\n                    if (used[tnn]) continue;\n                    futureMax = max(futureMax, p[nn]);\n                }\n                double val = (double)p[nb] + beta * (double)futureMax + gamma * (double)cntAdjDistinct[nb];\n                // small noise to diversify\n                val += (double)(uniform_int_distribution<int>(0, 999)(rng)) * 1e-6; // up to ~0.001\n                cand.push_back({nb, val});\n            }\n            if (cand.empty()) break;\n\n            sort(cand.begin(), cand.end(), [&](auto &x, auto &y){ return x.second > y.second; });\n            int K = min<int>(3, (int)cand.size());\n\n            if (K == 1) {\n                int nxt = cand[0].first;\n                used[tile[nxt]] = 1;\n                cur = nxt;\n                score += p[cur];\n                curPath.push_back(cur);\n            } else {\n                double base = cand[K-1].second;\n                vector<double> w(K);\n                double sumw = 0;\n                for (int i = 0; i < K; i++) {\n                    w[i] = (cand[i].second - base) + 1.0; // positive\n                    sumw += w[i];\n                }\n                double r = uniform_real_distribution<double>(0.0, sumw)(rng);\n                int pick = 0;\n                while (pick < K && r >= w[pick]) {\n                    r -= w[pick];\n                    pick++;\n                }\n                if (pick >= K) pick = K - 1;\n                int nxt = cand[pick].first;\n                used[tile[nxt]] = 1;\n                cur = nxt;\n                score += p[cur];\n                curPath.push_back(cur);\n            }\n        }\n\n        if (storePath) {\n            return pair<long long, vector<int>>(score, curPath);\n        } else {\n            return pair<long long, vector<int>>(score, {});\n        }\n    };\n\n    // Time control\n    auto t0 = chrono::steady_clock::now();\n    double TIME_LIMIT = 1.88; // seconds\n\n    mt19937_64 rng((uint64_t)chrono::steady_clock::now().time_since_epoch().count());\n\n    long long bestScore = -1;\n    vector<int> bestPath;\n\n    // Multi-start stochastic greedy\n    while (true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - t0).count();\n        if (elapsed > TIME_LIMIT) break;\n\n        bool store = false;\n        // only store path if it might improve, to reduce copying\n        // We'll quickly estimate by running without storing? (but then path missing)\n        // Simpler: always store; with small sizes it\u2019s okay. Keep it conditional:\n        // run twice? too much. We'll store every time.\n        auto [sc, path] = runWalk(rng, true);\n        if (sc > bestScore) {\n            bestScore = sc;\n            bestPath = std::move(path);\n        }\n    }\n\n    // Tail extension from best prefix (a few tries)\n    // Use remaining time.\n    auto now = chrono::steady_clock::now();\n    double elapsed = chrono::duration<double>(now - t0).count();\n    int tries = 0;\n    while (elapsed < TIME_LIMIT && tries < 60) {\n        tries++;\n\n        int L = (int)bestPath.size();\n        if (L <= 1) break;\n\n        uniform_int_distribution<int> distCut(0, max(0, L - 1));\n        // Prefer cutting near the end\n        int cut = max(0, L - 1 - (int)uniform_int_distribution<int>(0, min(120, L - 1))(rng));\n        if (cut < 0) cut = 0;\n\n        vector<char> used(M, 0);\n        long long score = 0;\n        for (int i = 0; i <= cut; i++) {\n            int sq = bestPath[i];\n            used[tile[sq]] = 1;\n            score += p[sq];\n        }\n        int cur = bestPath[cut];\n\n        vector<int> newPart;\n        newPart.reserve(M - cut);\n\n        // run extension with current used/cur\n        const double beta = 0.85, gamma = 0.35;\n        vector<int> curPath2;\n        curPath2.reserve(M);\n        curPath2.push_back(cur); // starting at cur\n\n        long long sc2 = score;\n\n        while (true) {\n            vector<pair<int,double>> cand;\n            for (int k = 0; k < 4; k++) {\n                int nb = neigh[cur][k];\n                if (nb < 0) continue;\n                if (used[tile[nb]]) continue;\n                int futureMax = 0;\n                for (int kk = 0; kk < 4; kk++) {\n                    int nn = neigh[nb][kk];\n                    if (nn < 0) continue;\n                    if (used[tile[nn]]) continue;\n                    futureMax = max(futureMax, p[nn]);\n                }\n                double val = (double)p[nb] + beta * (double)futureMax + gamma * (double)cntAdjDistinct[nb];\n                val += (double)(uniform_int_distribution<int>(0, 999)(rng)) * 1e-6;\n                cand.push_back({nb, val});\n            }\n            if (cand.empty()) break;\n\n            sort(cand.begin(), cand.end(), [&](auto &x, auto &y){ return x.second > y.second; });\n            int K = min<int>(3, (int)cand.size());\n            int nxt;\n            if (K == 1) nxt = cand[0].first;\n            else {\n                double base = cand[K-1].second;\n                vector<double> w(K);\n                double sumw = 0;\n                for (int i = 0; i < K; i++) {\n                    w[i] = (cand[i].second - base) + 1.0;\n                    sumw += w[i];\n                }\n                double r = uniform_real_distribution<double>(0.0, sumw)(rng);\n                int pick = 0;\n                while (pick < K && r >= w[pick]) {\n                    r -= w[pick];\n                    pick++;\n                }\n                if (pick >= K) pick = K - 1;\n                nxt = cand[pick].first;\n            }\n\n            used[tile[nxt]] = 1;\n            cur = nxt;\n            sc2 += p[cur];\n            curPath2.push_back(cur);\n        }\n\n        if (sc2 > bestScore) {\n            vector<int> merged;\n            merged.reserve(L - (cut + 1) + (int)curPath2.size());\n            for (int i = 0; i <= cut; i++) merged.push_back(bestPath[i]);\n            // append curPath2 excluding the first element (it equals bestPath[cut])\n            for (int i = 1; i < (int)curPath2.size(); i++) merged.push_back(curPath2[i]);\n            bestScore = sc2;\n            bestPath = std::move(merged);\n        }\n\n        now = chrono::steady_clock::now();\n        elapsed = chrono::duration<double>(now - t0).count();\n    }\n\n    // Output directions string\n    string ans;\n    if (!bestPath.empty()) {\n        ans.reserve(max(0, (int)bestPath.size() - 1));\n        for (int i = 1; i < (int)bestPath.size(); i++) {\n            ans.push_back(dirBetween(bestPath[i-1], bestPath[i]));\n        }\n    }\n    cout << ans << \"\\n\";\n    return 0;\n}","ahc003":"#include <bits/stdc++.h>\nusing namespace std;\n\n// Grid size\nstatic constexpr int H = 30;\nstatic constexpr int W = 30;\nstatic constexpr int N = H * W;\n\n// Edge indexing\n// Horizontal edges: between (i,j) and (i,j+1), i in [0,29], j in [0,28]\nstatic constexpr int HOR = H * (W - 1); // 30*29 = 870\n// Vertical edges: between (i,j) and (i+1,j), i in [0,28], j in [0,29]\nstatic constexpr int VER = (H - 1) * W; // 29*30 = 870\nstatic constexpr int ECOUNT = HOR + VER;\n\nstatic inline int idx_node(int i, int j) { return i * W + j; }\nstatic inline pair<int,int> coord_node(int v) { return {v / W, v % W}; }\n\nstatic inline int idx_horizontal_edge(int i, int j /*0..28*/) {\n    // between (i,j) and (i,j+1)\n    return i * (W - 1) + j;\n}\nstatic inline int idx_vertical_edge(int i, int j /*0..29*/) {\n    // between (i,j) and (i+1,j)\n    return HOR + i * W + j;\n}\n\nstruct PathResult {\n    string moves;\n    vector<int> usedEdges;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // Build adjacency\n    vector<vector<pair<int,int>>> adj(N); // (to, edgeIdx)\n\n    for (int i = 0; i < H; i++) {\n        for (int j = 0; j < W; j++) {\n            int u = idx_node(i, j);\n            // Right\n            if (j + 1 < W) {\n                int v = idx_node(i, j + 1);\n                int e = idx_horizontal_edge(i, j);\n                adj[u].push_back({v, e});\n                adj[v].push_back({u, e});\n            }\n            // Down\n            if (i + 1 < H) {\n                int v = idx_node(i + 1, j);\n                int e = idx_vertical_edge(i, j);\n                adj[u].push_back({v, e});\n                adj[v].push_back({u, e});\n            }\n        }\n    }\n\n    // Weight estimates\n    vector<double> w_hat(ECOUNT, 5000.0);\n\n    // RNG for exploration and tie-breaking\n    std::mt19937_64 rng(712367821ULL);\n    auto rand01 = [&]() -> double {\n        return (rng() >> 11) * (1.0 / 9007199254740992.0);\n    };\n\n    const double LO = 1.0;\n    const double HI = 15000.0;\n\n    auto build_path_from_parents = [&](int s, int t,\n                                        const vector<int>& parent,\n                                        const vector<int>& parentEdge) -> PathResult {\n        PathResult res;\n        if (s == t) return res;\n\n        vector<char> revMoves;\n        vector<int> revEdges;\n\n        int cur = t;\n        while (cur != s) {\n            int p = parent[cur];\n            int e = parentEdge[cur];\n            revEdges.push_back(e);\n\n            auto [pi, pj] = coord_node(p);\n            auto [ci, cj] = coord_node(cur);\n\n            char mv;\n            if (ci == pi - 1 && cj == pj) mv = 'U';\n            else if (ci == pi + 1 && cj == pj) mv = 'D';\n            else if (ci == pi && cj == pj - 1) mv = 'L';\n            else if (ci == pi && cj == pj + 1) mv = 'R';\n            else {\n                // Should never happen if parents define a valid grid step\n                mv = '?';\n            }\n\n            revMoves.push_back(mv);\n            cur = p;\n        }\n\n        reverse(revMoves.begin(), revMoves.end());\n        reverse(revEdges.begin(), revEdges.end());\n\n        res.moves.assign(revMoves.begin(), revMoves.end());\n        res.usedEdges = std::move(revEdges);\n        return res;\n    };\n\n    auto dijkstra_path = [&](int s, int t) -> PathResult {\n        // Dijkstra on w_hat\n        vector<long double> dist(N, numeric_limits<long double>::infinity());\n        vector<int> parent(N, -1);\n        vector<int> parentEdge(N, -1);\n        vector<long long> choiceKey(N, (1LL<<62));\n\n        struct State {\n            long double d;\n            int v;\n            long long key;\n            bool operator>(State const& other) const {\n                if (d != other.d) return d > other.d;\n                return key > other.key;\n            }\n        };\n\n        priority_queue<State, vector<State>, greater<State>> pq;\n        dist[s] = 0;\n        parent[s] = s;\n\n        pq.push({0.0L, s, 0});\n\n        const long double EPS = 1e-12;\n\n        while (!pq.empty()) {\n            auto st = pq.top(); pq.pop();\n            int u = st.v;\n            if (st.d != dist[u]) continue;\n            if (u == t) break;\n\n            for (auto [to, e] : adj[u]) {\n                long double nd = dist[u] + (long double)w_hat[e];\n                long long nkey = (long long)u * (long long)(ECOUNT + 7) + (long long)e;\n\n                if (nd + EPS < dist[to]) {\n                    dist[to] = nd;\n                    parent[to] = u;\n                    parentEdge[to] = e;\n                    choiceKey[to] = nkey;\n                    pq.push({nd, to, nkey});\n                } else if (fabsl(nd - dist[to]) <= EPS) {\n                    if (nkey < choiceKey[to]) {\n                        parent[to] = u;\n                        parentEdge[to] = e;\n                        choiceKey[to] = nkey;\n                        pq.push({nd, to, nkey});\n                    }\n                }\n            }\n        }\n\n        return build_path_from_parents(s, t, parent, parentEdge);\n    };\n\n    auto random_monotone_path = [&](int s, int t) -> PathResult {\n        auto [si, sj] = coord_node(s);\n        auto [ti, tj] = coord_node(t);\n\n        int i = si, j = sj;\n        PathResult res;\n        while (i != ti || j != tj) {\n            bool canV = (i != ti);\n            bool canH = (j != tj);\n\n            bool doV;\n            if (canV && canH) {\n                doV = (rand01() < 0.5);\n            } else {\n                doV = canV;\n            }\n\n            if (doV) {\n                if (ti > i) {\n                    // move down\n                    int e = idx_vertical_edge(i, j);\n                    res.usedEdges.push_back(e);\n                    res.moves.push_back('D');\n                    i++;\n                } else {\n                    // move up\n                    int e = idx_vertical_edge(i - 1, j);\n                    res.usedEdges.push_back(e);\n                    res.moves.push_back('U');\n                    i--;\n                }\n            } else {\n                if (tj > j) {\n                    // move right\n                    int e = idx_horizontal_edge(i, j);\n                    res.usedEdges.push_back(e);\n                    res.moves.push_back('R');\n                    j++;\n                } else {\n                    // move left\n                    int e = idx_horizontal_edge(i, j - 1);\n                    res.usedEdges.push_back(e);\n                    res.moves.push_back('L');\n                    j--;\n                }\n            }\n        }\n        return res;\n    };\n\n    for (int k = 0; k < 1000; k++) {\n        int si, sj, ti, tj;\n        if (!(cin >> si >> sj >> ti >> tj)) break;\n        int s = idx_node(si, sj);\n        int t = idx_node(ti, tj);\n\n        // Exploration probability schedule\n        double pExpl;\n        if (k < 120) pExpl = 0.18;\n        else if (k < 400) pExpl = 0.08;\n        else pExpl = 0.03;\n\n        PathResult pr;\n        if (rand01() < pExpl) pr = random_monotone_path(s, t);\n        else pr = dijkstra_path(s, t);\n\n        // Safety: if something went wrong, fallback to monotone\n        if ((int)pr.moves.size() == 0 || (int)pr.usedEdges.size() != (int)pr.moves.size()) {\n            pr = random_monotone_path(s, t);\n        }\n\n        cout << pr.moves << '\\n' << flush;\n\n        long long y_int;\n        if (!(cin >> y_int)) break;\n        long double y = (long double)y_int;\n\n        int m = (int)pr.usedEdges.size();\n        if (m == 0) continue;\n\n        long double pred = 0.0L;\n        for (int e : pr.usedEdges) pred += (long double)w_hat[e];\n\n        long double err = y - pred;\n\n        // Learning rate decay\n        long double eta = 0.30L / sqrt((long double)(k + 1));\n        eta = max((long double)0.005, eta);\n\n        long double delta = eta * err / (long double)m;\n\n        for (int e : pr.usedEdges) {\n            long double nw = (long double)w_hat[e] + delta;\n            if (nw < LO) nw = LO;\n            if (nw > HI) nw = HI;\n            w_hat[e] = (double)nw;\n        }\n    }\n\n    return 0;\n}","ahc004":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 20;\nstatic constexpr int ALPHA = 8; // A..H\n\n// SplitMix64 hash for unordered_map speed\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 uint64_t keyOfString(const vector<uint8_t>& v) {\n    int len = (int)v.size();\n    uint64_t enc = 0;\n    for (uint8_t x : v) enc = (enc << 3) | (uint64_t)x; // base 8 packing\n    return (uint64_t(len) << 48) | enc; // len distinguishes different lengths\n}\n\nstruct Solver {\n    int M;\n    vector<string> S;\n    vector<vector<uint8_t>> scodes; // codes of each string\n    vector<int> slen;              // length of each string\n    vector<uint64_t> skey;         // key of each string (len<<48 | enc)\n\n    // For objective:\n    int K; // number of distinct keys\n    vector<int> mult;           // multiplicity for each key id\n    vector<int> occ;            // occurrence count in the current grid\n    long long curC = 0;        // sum of mult[id] where occ[id]>0\n\n    // Map from key to id\n    unordered_map<uint64_t, int, decltype(&splitmix64)> idByKey;\n\n    // Which lengths appear in input?\n    vector<int> neededLens; // subset of [2..12]\n    bool needLen[13]{};\n\n    // Masks for sliding window encoding\n    uint64_t maskLower[13]{};\n\n    // Grid state\n    array<array<uint8_t, N>, N> g{};\n    array<array<uint8_t, N>, N> bestG{};\n\n    int bestC = -1;\n\n    // For greedy assembly initialization:\n    // prefixCand[lenOverlap][encPrefix] = list of string indices having that prefix\n    // suffixCand[lenOverlap][encSuffix] = list of string indices having that suffix\n    vector<unordered_map<uint64_t, vector<int>, decltype(&splitmix64)>> prefixCand, suffixCand;\n\n    mt19937_64 rng;\n\n    Solver() : rng(chrono::steady_clock::now().time_since_epoch().count()) {\n        idByKey = unordered_map<uint64_t, int, decltype(&splitmix64)>(1024, splitmix64);\n    }\n\n    uint8_t charToCode(char c) { return (uint8_t)(c - 'A'); }\n\n    uint64_t encFromSeq(const vector<uint8_t>& v, int l, int r) {\n        // encode v[l..r) as base-8 concatenation; no length in key\n        uint64_t enc = 0;\n        for (int i = l; i < r; i++) enc = (enc << 3) | v[i];\n        return enc;\n    }\n\n    void buildObjectiveStructures() {\n        // Build distinct keys and multiplicities\n        idByKey.clear();\n        mult.clear();\n        needLen[0] = false;\n        for (int k = 0; k <= 12; k++) needLen[k] = false;\n\n        K = 0;\n        for (int i = 0; i < M; i++) {\n            uint64_t key = skey[i];\n            auto it = idByKey.find(key);\n            if (it == idByKey.end()) {\n                int id = K++;\n                idByKey.emplace(key, id);\n                mult.push_back(1);\n            } else {\n                mult[it->second]++;\n            }\n            int len = slen[i];\n            needLen[len] = true;\n        }\n\n        neededLens.clear();\n        for (int k = 2; k <= 12; k++) if (needLen[k]) neededLens.push_back(k);\n\n        // Precompute masks for sliding in updateLine\n        for (int k = 2; k <= 12; k++) {\n            int bits = 3 * (k - 1);\n            maskLower[k] = (bits >= 64) ? ~0ULL : ((1ULL << bits) - 1ULL);\n        }\n    }\n\n    void buildOverlapMaps() {\n        // Build prefix/suffix candidates for greedy assembly.\n        // overlap length is at least 2\n        prefixCand.assign(13, unordered_map<uint64_t, vector<int>, decltype(&splitmix64)>(0, splitmix64));\n        suffixCand.assign(13, unordered_map<uint64_t, vector<int>, decltype(&splitmix64)>(0, splitmix64));\n\n        for (int i = 0; i < M; i++) {\n            int L = slen[i];\n            // ov in [2, L-1]\n            for (int ov = 2; ov <= L - 1; ov++) {\n                uint64_t pref = encFromSeq(scodes[i], 0, ov);\n                uint64_t suf = encFromSeq(scodes[i], L - ov, L);\n                prefixCand[ov][pref].push_back(i);\n                suffixCand[ov][suf].push_back(i);\n            }\n        }\n        // Optionally reserve would be done, but not required (small total).\n    }\n\n    inline void updateLine(bool isRow, int idx, int delta) {\n        // delta is +1 or -1: add or remove all occurrences contributed by this line.\n        // Recompute ext[0..2N-1] each time (N fixed and small).\n        uint8_t ext[2 * N];\n        for (int t = 0; t < 2 * N; t++) {\n            if (isRow) ext[t] = g[idx][t % N];\n            else ext[t] = g[t % N][idx];\n        }\n\n        for (int k : neededLens) {\n            // Build enc for start=0 window length k\n            uint64_t enc = 0;\n            for (int t = 0; t < k; t++) enc = (enc << 3) | (uint64_t)ext[t];\n\n            for (int start = 0; start < N; start++) {\n                uint64_t key = (uint64_t(k) << 48) | enc;\n                auto it = idByKey.find(key);\n                if (it != idByKey.end()) {\n                    int id = it->second;\n                    int before = occ[id];\n                    if (delta == +1) {\n                        occ[id] = before + 1;\n                        if (before == 0) curC += mult[id];\n                    } else {\n                        occ[id] = before - 1;\n                        if (before == 1) curC -= mult[id];\n                    }\n                }\n                if (start == N - 1) break;\n                // Slide: drop first code, append ext[start+k]\n                enc = ((enc & maskLower[k]) << 3) | (uint64_t)ext[start + k];\n            }\n        }\n    }\n\n    void computeInitialCounts() {\n        occ.assign(K, 0);\n        curC = 0;\n        // Add all row contributions\n        for (int i = 0; i < N; i++) updateLine(true, i, +1);\n        // Add all column contributions\n        for (int j = 0; j < N; j++) updateLine(false, j, +1);\n\n        bestC = (int)curC;\n        bestG = g;\n    }\n\n    inline void setCell(int i, int j, uint8_t nv) {\n        if (g[i][j] == nv) return;\n        // Remove current contributions\n        updateLine(true, i, -1);\n        updateLine(false, j, -1);\n        // Set cell\n        g[i][j] = nv;\n        // Add new contributions\n        updateLine(true, i, +1);\n        updateLine(false, j, +1);\n    }\n\n    void randomFillRow(array<uint8_t, N>& row) {\n        for (int j = 0; j < N; j++) row[j] = (uint8_t)(rng() % ALPHA);\n    }\n\n    // Greedy construction of a decent initial grid (rows-first).\n    void buildInitialGridGreedy() {\n        // Initialize covered sets for horizontal matches using built rows only.\n        vector<unordered_set<uint64_t, decltype(&splitmix64)>> coveredKeys(13);\n        for (int k = 2; k <= 12; k++) {\n            if (needLen[k]) coveredKeys[k] = unordered_set<uint64_t, decltype(&splitmix64)>(0, splitmix64);\n        }\n        vector<char> coveredInput(M, 0);\n\n        auto addRowToCovered = [&](int rowIdx, const array<uint8_t, N>& row) {\n            // For each needed length k, insert all cyclic substrings keys into coveredKeys[k]\n            for (int k : neededLens) {\n                uint64_t enc = 0;\n                // build first window start=0\n                for (int t = 0; t < k; t++) enc = (enc << 3) | row[t];\n                for (int start = 0; start < N; start++) {\n                    uint64_t key = (uint64_t(k) << 48) | enc;\n                    coveredKeys[k].insert(key);\n                    if (start == N - 1) break;\n                    enc = ((enc & maskLower[k]) << 3) | (uint64_t)row[(start + k) % N];\n                }\n            }\n        };\n\n        auto updateCoveredInputFromRowSets = [&]() {\n            for (int i = 0; i < M; i++) {\n                if (coveredInput[i]) continue;\n                int k = slen[i];\n                uint64_t key = skey[i];\n                if (coveredKeys[k].find(key) != coveredKeys[k].end()) coveredInput[i] = 1;\n            }\n        };\n\n        // For choosing seeds\n        int minOverlap = 2;\n\n        for (int i = 0; i < N; i++) {\n            vector<int> bestIdx;\n            int bestL = -1;\n            for (int idx = 0; idx < M; idx++) {\n                if (coveredInput[idx]) continue;\n                if (slen[idx] > bestL) {\n                    bestL = slen[idx];\n                    bestIdx.clear();\n                    bestIdx.push_back(idx);\n                } else if (slen[idx] == bestL) {\n                    bestIdx.push_back(idx);\n                }\n            }\n\n            array<uint8_t, N> row;\n            if (bestL < 0) {\n                randomFillRow(row);\n                for (int j = 0; j < N; j++) g[i][j] = row[j];\n                addRowToCovered(i, row);\n                updateCoveredInputFromRowSets();\n                continue;\n            }\n\n            int seed = bestIdx[rng() % bestIdx.size()];\n            vector<uint8_t> seq = scodes[seed];\n\n            // Expand seq until length N (or stuck)\n            while ((int)seq.size() < N) {\n                int curLen = (int)seq.size();\n\n                int bestRightLen = curLen;\n                int bestRightIdx = -1, bestRightOv = -1;\n\n                int maxOv = min(curLen - 1, 11); // since max string length <=12, ov<=11\n                for (int ov = minOverlap; ov <= maxOv; ov++) {\n                    // We'll iterate ov descending for stronger matches\n                }\n                for (int ov = maxOv; ov >= minOverlap; ov--) {\n                    // suffix of seq length ov\n                    uint64_t sufEnc = 0;\n                    for (int t = curLen - ov; t < curLen; t++) sufEnc = (sufEnc << 3) | seq[t];\n\n                    auto it = prefixCand[ov].find(sufEnc);\n                    if (it == prefixCand[ov].end()) continue;\n\n                    for (int candIdx : it->second) {\n                        if (slen[candIdx] <= ov) continue;\n                        int newLen = curLen + slen[candIdx] - ov;\n                        if (newLen <= N && newLen > bestRightLen) {\n                            bestRightLen = newLen;\n                            bestRightIdx = candIdx;\n                            bestRightOv = ov;\n                        }\n                    }\n                }\n\n                int bestLeftLen = curLen;\n                int bestLeftIdx = -1, bestLeftOv = -1;\n\n                for (int ov = maxOv; ov >= minOverlap; ov--) {\n                    uint64_t prefEnc = 0;\n                    for (int t = 0; t < ov; t++) prefEnc = (prefEnc << 3) | seq[t];\n\n                    auto it = suffixCand[ov].find(prefEnc);\n                    if (it == suffixCand[ov].end()) continue;\n\n                    for (int candIdx : it->second) {\n                        if (slen[candIdx] <= ov) continue;\n                        int newLen = curLen + slen[candIdx] - ov;\n                        if (newLen <= N && newLen > bestLeftLen) {\n                            bestLeftLen = newLen;\n                            bestLeftIdx = candIdx;\n                            bestLeftOv = ov;\n                        }\n                    }\n                }\n\n                int finalLen = max(bestRightLen, bestLeftLen);\n                if (finalLen == curLen) break;\n\n                bool takeRight;\n                if (bestRightLen > bestLeftLen) takeRight = true;\n                else if (bestLeftLen > bestRightLen) takeRight = false;\n                else takeRight = (rng() & 1);\n\n                if (takeRight) {\n                    // append candidate after overlap\n                    auto& cv = scodes[bestRightIdx];\n                    int ov = bestRightOv;\n                    for (int t = ov; t < (int)cv.size() && (int)seq.size() < N; t++) {\n                        seq.push_back(cv[t]);\n                    }\n                } else {\n                    auto& cv = scodes[bestLeftIdx];\n                    int ov = bestLeftOv;\n                    vector<uint8_t> nseq;\n                    nseq.reserve(N);\n                    for (int t = 0; t < (int)cv.size() - ov && (int)nseq.size() < N; t++) nseq.push_back(cv[t]);\n                    for (uint8_t x : seq) {\n                        if ((int)nseq.size() >= N) break;\n                        nseq.push_back(x);\n                    }\n                    seq.swap(nseq);\n                }\n            }\n\n            // Fill the rest randomly\n            while ((int)seq.size() < N) seq.push_back((uint8_t)(rng() % ALPHA));\n\n            for (int j = 0; j < N; j++) {\n                row[j] = seq[j];\n                g[i][j] = row[j];\n            }\n            addRowToCovered(i, row);\n            updateCoveredInputFromRowSets();\n        }\n    }\n\n    void solveOneRun(int steps, long double Tstart, long double Tmin) {\n        // Simulated annealing on single-cell changes\n        long double T = Tstart;\n        long double alpha = pow((double)(Tmin / Tstart), 1.0 / (double)steps);\n\n        for (int it = 0; it < steps; it++) {\n            int i = (int)(rng() % N);\n            int j = (int)(rng() % N);\n            uint8_t old = g[i][j];\n            uint8_t nv = old;\n            while (nv == old) nv = (uint8_t)(rng() % ALPHA);\n\n            long long oldC = curC;\n            setCell(i, j, nv);\n            long long newC = curC;\n\n            bool accept = false;\n            if (newC >= oldC) {\n                accept = true;\n            } else {\n                long double prob = expl((long double)(newC - oldC) / T);\n                long double r = (long double)(rng() % 1000000) / 1000000.0L;\n                if (r < prob) accept = true;\n            }\n\n            if (accept) {\n                if (newC > bestC) {\n                    bestC = (int)newC;\n                    bestG = g;\n                }\n            } else {\n                // revert\n                setCell(i, j, old);\n            }\n\n            T *= alpha;\n        }\n    }\n\n    void run() {\n        ios::sync_with_stdio(false);\n        cin.tie(nullptr);\n\n        int Nread;\n        cin >> Nread >> M;\n        // N is fixed to 20 in the statement, but read anyway\n        for (int i = 0; i < M; i++) {\n            cin >> S.emplace_back();\n        }\n\n        scodes.assign(M, {});\n        slen.assign(M, 0);\n        skey.assign(M, 0);\n\n        for (int i = 0; i < M; i++) {\n            const string& s = S[i];\n            slen[i] = (int)s.size();\n            vector<uint8_t> v(s.size());\n            for (int t = 0; t < (int)s.size(); t++) v[t] = charToCode(s[t]);\n            scodes[i] = v;\n            skey[i] = keyOfString(v);\n        }\n\n        buildObjectiveStructures();\n        buildOverlapMaps();\n\n        // Build greedy initial grid\n        buildInitialGridGreedy();\n        // We'll run multiple restarts from perturbed versions of this greedy grid.\n        array<array<uint8_t, N>, N> baseG = g;\n\n        bestC = -1;\n        bool haveBest = false;\n\n        int restarts = 2;\n        int stepsPer = 100000; // keep moderate for time\n        long double Tstart = 4.0L, Tmin = 0.12L;\n\n        for (int r = 0; r < restarts; r++) {\n            g = baseG;\n            // Perturb for restarts\n            int perturb = (r == 0 ? 0 : 40 + 20 * r);\n            for (int t = 0; t < perturb; t++) {\n                int i = (int)(rng() % N);\n                int j = (int)(rng() % N);\n                uint8_t nv = (uint8_t)(rng() % ALPHA);\n                if (nv == g[i][j]) nv = (nv + 1) % ALPHA;\n                g[i][j] = nv;\n            }\n\n            computeInitialCounts();\n            if (!haveBest || bestC > (int)curC) {\n                // bestC and bestG already set in computeInitialCounts\n            }\n            if (curC > bestC) {\n                bestC = (int)curC;\n                bestG = g;\n            }\n\n            // Merge with global best\n            if (!haveBest || bestC > bestC) {\n                // not used\n            }\n\n            // Ensure global best initialized from this run\n            if (!haveBest) {\n                haveBest = true;\n                bestC = (int)curC;\n                bestG = g;\n            } else {\n                if ((int)curC > bestC) {\n                    bestC = (int)curC;\n                    bestG = g;\n                }\n            }\n\n            solveOneRun(stepsPer, Tstart, Tmin);\n        }\n\n        // Output best grid\n        for (int i = 0; i < N; i++) {\n            string row;\n            row.reserve(N);\n            for (int j = 0; j < N; j++) row.push_back(char('A' + bestG[i][j]));\n            cout << row << \"\\n\";\n        }\n    }\n};\n\nint main() {\n    Solver s;\n    s.run();\n    return 0;\n}","ahc005":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct DSU {\n    int n;\n    vector<int> p, r;\n    DSU(int n=0): n(n), p(n), r(n,0) { iota(p.begin(), p.end(), 0); }\n    int find(int x){ return p[x]==x? x : p[x]=find(p[x]); }\n    bool unite(int a,int b){\n        a=find(a); b=find(b);\n        if(a==b) return false;\n        if(r[a]<r[b]) swap(a,b);\n        p[b]=a;\n        if(r[a]==r[b]) r[a]++;\n        return true;\n    }\n};\n\nstruct Edge {\n    int u, v;\n    int cost;\n    bool operator<(Edge const& other) const { return cost < other.cost; }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, si, sj;\n    cin >> N >> si >> sj;\n    vector<string> g(N);\n    for(int i=0;i<N;i++) cin >> g[i];\n\n    vector<vector<int>> idx(N, vector<int>(N, -1));\n    vector<pair<int,int>> cells;\n    vector<int> wts;\n\n    auto inside = [&](int r,int c){ return 0<=r && r<N && 0<=c && c<N; };\n\n    // BFS to get connected component containing (si,sj)\n    queue<pair<int,int>> q;\n    vector<vector<char>> vis(N, vector<char>(N, 0));\n    q.push({si,sj});\n    vis[si][sj] = 1;\n\n    int sr = si, sc = sj;\n    if(g[sr][sc] == '#') return 0; // guaranteed not\n\n    int drs[4] = {-1, 1, 0, 0};\n    int dcs[4] = {0, 0, -1, 1};\n\n    while(!q.empty()){\n        auto [r,c] = q.front(); q.pop();\n        int id = (int)cells.size();\n        cells.push_back({r,c});\n        wts.push_back(g[r][c]-'0');\n        idx[r][c] = id;\n\n        for(int k=0;k<4;k++){\n            int nr=r+drs[k], nc=c+dcs[k];\n            if(!inside(nr,nc)) continue;\n            if(vis[nr][nc]) continue;\n            if(g[nr][nc] == '#') continue;\n            vis[nr][nc]=1;\n            q.push({nr,nc});\n        }\n    }\n\n    int m = (int)cells.size();\n    int sidx = idx[si][sj];\n    if(m == 1){\n        cout << \"\\n\";\n        return 0;\n    }\n\n    // Build edge list for the component graph\n    vector<Edge> edges;\n    edges.reserve(m*2);\n\n    for(int u=0; u<m; u++){\n        auto [r,c] = cells[u];\n        // Right and Down to avoid duplicates\n        const int rr[2] = {0, 1};\n        const int cc[2] = {1, 0};\n        for(int t=0;t<2;t++){\n            int nr = r + rr[t], nc = c + cc[t];\n            if(!inside(nr,nc)) continue;\n            int v = idx[nr][nc];\n            if(v == -1) continue;\n            int cost = wts[u] + wts[v];\n            edges.push_back({u, v, cost});\n        }\n    }\n\n    // Kruskal MST\n    sort(edges.begin(), edges.end());\n    DSU dsu(m);\n    vector<pair<int,int>> treeEdges;\n    treeEdges.reserve(m-1);\n\n    for(auto &e: edges){\n        if(dsu.unite(e.u, e.v)){\n            treeEdges.push_back({e.u, e.v});\n            if((int)treeEdges.size() == m-1) break;\n        }\n    }\n\n    // Build MST adjacency\n    vector<vector<int>> tree(m);\n    for(auto [u,v]: treeEdges){\n        tree[u].push_back(v);\n        tree[v].push_back(u);\n    }\n\n    auto dirChar = [&](int from, int to)->char{\n        int fr = cells[from].first, fc = cells[from].second;\n        int tr = cells[to].first, tc = cells[to].second;\n        if(tr == fr - 1 && tc == fc) return 'U';\n        if(tr == fr + 1 && tc == fc) return 'D';\n        if(tr == fr && tc == fc - 1) return 'L';\n        // otherwise tr == fr && tc == fc + 1\n        return 'R';\n    };\n\n    // Generate doubled-tree DFS tour (iterative) producing a closed walk\n    string route;\n    route.reserve(2*(m-1));\n\n    struct Frame { int u, p, it; };\n    vector<Frame> st;\n    st.push_back({sidx, -1, 0});\n\n    while(!st.empty()){\n        auto &top = st.back();\n        int u = top.u;\n\n        if(top.it < (int)tree[u].size()){\n            int v = tree[u][top.it++];\n            if(v == top.p) continue;\n            route.push_back(dirChar(u, v));   // go down\n            st.push_back({v, u, 0});\n        }else{\n            // finished u, pop and return to parent if exists\n            Frame finished = st.back();\n            st.pop_back();\n            if(!st.empty()){\n                int parent = st.back().u;\n                route.push_back(dirChar(finished.u, parent)); // return up\n            }\n        }\n    }\n\n    // route starts and ends at start, and all moves are between adjacent road cells\n    cout << route << \"\\n\";\n    return 0;\n}","future-contest-2022-qual":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct ReadyComp {\n    // Larger critical first; then smaller s2 first; then smaller id first.\n    const vector<int>* crit;\n    const vector<long long>* s2;\n    bool operator()(int a, int b) const {\n        if ((*crit)[a] != (*crit)[b]) return (*crit)[a] > (*crit)[b];\n        if ((*s2)[a] != (*s2)[b]) return (*s2)[a] < (*s2)[b];\n        return a < b;\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, K, R;\n    cin >> N >> M >> K >> R;\n\n    vector<long long> s2(N, 0);\n    vector<double> p(N, 0.0);\n    for (int i = 0; i < N; i++) {\n        long long sum = 0;\n        for (int k = 0; k < K; k++) {\n            long long x;\n            cin >> x;\n            sum += x * x;\n        }\n        s2[i] = sum;\n        p[i] = sqrt((double)sum);\n    }\n\n    vector<vector<int>> out(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        out[u].push_back(v);\n        indeg[v]++;\n    }\n\n    // Criticality: longest path length from i (in nodes).\n    vector<int> crit(N, 1);\n    for (int i = N - 1; i >= 0; i--) {\n        int best = 1;\n        for (int v : out[i]) best = max(best, 1 + crit[v]);\n        crit[i] = best;\n    }\n\n    // Ready set\n    ReadyComp comp{&crit, &s2};\n    set<int, ReadyComp> ready(comp);\n    for (int i = 0; i < N; i++) if (indeg[i] == 0) ready.insert(i);\n\n    vector<int> state(N, 0); // 0=unstarted, 1=in progress, 2=done\n\n    vector<int> curTask(M, -1);\n    vector<int> startDay(M, -1);\n\n    const double INF = 1e100;\n    vector<double> LB(M, -INF), UB(M, INF);\n    vector<double> param(M, 40.0); // initial guess\n\n    auto recomputeParam = [&](int j) {\n        double lb = LB[j], ub = UB[j];\n        double x;\n        if (lb <= -INF/2 && ub >= INF/2) x = 40.0;\n        else if (lb <= -INF/2) x = ub - 5.0;\n        else if (ub >= INF/2) x = lb + 5.0;\n        else x = 0.5 * (lb + ub);\n\n        x = min(100.0, max(5.0, x));\n        param[j] = x;\n    };\n\n    auto estimateScore = [&](int j, int task) -> double {\n        // Estimated time increases with (p[task] - param[j])_+\n        double diff = p[task] - param[j];\n        double time_est = 1.0;\n        if (diff > 0) time_est += diff; // linear monotone proxy\n        // Prefer critical tasks\n        const double alpha = 0.01;\n        double denom = 1.0 + alpha * (double)crit[task];\n        return time_est / denom;\n    };\n\n    mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());\n\n    int day = 1;\n    while (day <= 2000) {\n        vector<pair<int,int>> assign; // (member, task)\n        int idleCount = 0;\n        for (int j = 0; j < M; j++) if (curTask[j] == -1) idleCount++;\n\n        // Greedy: strongest members first\n        vector<int> idleMembers;\n        idleMembers.reserve(idleCount);\n        for (int j = 0; j < M; j++) if (curTask[j] == -1) idleMembers.push_back(j);\n        sort(idleMembers.begin(), idleMembers.end(), [&](int a, int b){\n            if (param[a] != param[b]) return param[a] > param[b];\n            return a < b;\n        });\n\n        const int LCAND = 60;\n\n        for (int j : idleMembers) {\n            if (ready.empty()) break;\n\n            // Scan first LCAND tasks in static ready priority, choose best for this member.\n            double bestScore = 1e100;\n            int bestTask = -1;\n            auto bestIt = ready.end();\n\n            int cnt = 0;\n            for (auto it = ready.begin(); it != ready.end() && cnt < LCAND; ++it, ++cnt) {\n                int t = *it;\n                double sc = estimateScore(j, t);\n\n                // Tiny random tie-breaker\n                sc += uniform_real_distribution<double>(0.0, 1e-7)(rng);\n\n                if (sc < bestScore) {\n                    bestScore = sc;\n                    bestTask = t;\n                    bestIt = it;\n                } else if (fabs(sc - bestScore) <= 1e-12) {\n                    // tie: higher critical, then smaller difficulty\n                    if (bestTask != -1) {\n                        if (crit[t] > crit[bestTask]) {\n                            bestScore = sc;\n                            bestTask = t;\n                            bestIt = it;\n                        } else if (crit[t] == crit[bestTask] && s2[t] < s2[bestTask]) {\n                            bestScore = sc;\n                            bestTask = t;\n                            bestIt = it;\n                        }\n                    }\n                }\n            }\n\n            if (bestTask == -1) break;\n            // assign\n            ready.erase(bestIt);\n            state[bestTask] = 1;\n            curTask[j] = bestTask;\n            startDay[j] = day;\n            assign.emplace_back(j + 1, bestTask + 1);\n        }\n\n        // Output\n        cout << assign.size();\n        for (auto [a, b] : assign) cout << ' ' << a << ' ' << b;\n        cout << '\\n' << flush;\n\n        // Read completion info\n        int n;\n        if (!(cin >> n)) return 0;\n        if (n == -1) return 0;\n\n        for (int i = 0; i < n; i++) {\n            int f;\n            cin >> f;\n            int j = f - 1;\n            int task = curTask[j];\n            if (task < 0) continue; // should not happen\n\n            curTask[j] = -1;\n            state[task] = 2;\n            int dur = day - startDay[j] + 1;\n\n            // Update bounds from duration signal\n            if (dur == 1) {\n                LB[j] = max(LB[j], p[task]);\n            } else if (dur >= 4) {\n                UB[j] = min(UB[j], p[task]);\n            }\n            recomputeParam(j);\n\n            // Update indegrees\n            for (int v : out[task]) {\n                indeg[v]--;\n                if (indeg[v] == 0 && state[v] == 0) ready.insert(v);\n            }\n        }\n\n        day++;\n    }\n\n    return 0;\n}","ahc006":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic inline int manhattan(int x1, int y1, int x2, int y2) {\n    return abs(x1 - x2) + abs(y1 - y2);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    const int NORD = 1000;\n    const int W = 1000; // matrix stride\n    const int XOFF = 400, YOFF = 400;\n    const int M = 50;\n\n    vector<int> px(NORD), py(NORD), dx(NORD), dy(NORD);\n    for (int i = 0; i < NORD; i++) {\n        int a, b, c, d;\n        cin >> a >> b >> c >> d;\n        px[i] = a; py[i] = b;\n        dx[i] = c; dy[i] = d;\n    }\n\n    // Precompute distances needed\n    vector<int> internal(NORD), startDist(NORD), endDist(NORD);\n    // trans[i][j] = dist(drop_i, pick_j)\n    vector<int> trans(NORD * W);\n    // pickDist[i][j] = dist(pick_i, pick_j)\n    vector<int> pickDist(NORD * W);\n    // dropDist[i][j] = dist(drop_i, drop_j)\n    vector<int> dropDist(NORD * W);\n\n    for (int i = 0; i < NORD; i++) {\n        internal[i] = manhattan(px[i], py[i], dx[i], dy[i]);\n        startDist[i] = manhattan(XOFF, YOFF, px[i], py[i]);\n        endDist[i] = manhattan(dx[i], dy[i], XOFF, YOFF);\n    }\n\n    for (int i = 0; i < NORD; i++) {\n        int dix = dx[i], diy = dy[i];\n        for (int j = 0; j < NORD; j++) {\n            trans[i * W + j] = manhattan(dix, diy, px[j], py[j]);\n            pickDist[i * W + j] = manhattan(px[i], py[i], px[j], py[j]);\n            dropDist[i * W + j] = manhattan(dix, diy, dx[j], dy[j]);\n        }\n    }\n\n    auto getTrans = [&](int i, int j) -> int { return trans[i * W + j]; };\n    auto getPickDist = [&](int i, int j) -> int { return pickDist[i * W + j]; };\n    auto getDropDist = [&](int i, int j) -> int { return dropDist[i * W + j]; };\n\n    vector<long long> weight(NORD);\n    for (int i = 0; i < NORD; i++) {\n        weight[i] = (long long)internal[i] + startDist[i] + endDist[i];\n    }\n\n    auto computeMacroTotal = [&](const vector<int>& orderSeq, long long internalSum) -> long long {\n        long long cost = startDist[orderSeq[0]];\n        cost += endDist[orderSeq.back()];\n        for (int i = 0; i + 1 < (int)orderSeq.size(); i++) {\n            cost += getTrans(orderSeq[i], orderSeq[i + 1]); // drop_i -> pick_next\n        }\n        return internalSum + cost;\n    };\n\n    auto buildMacroRoute = [&](const vector<int>& orderSeq) -> vector<pair<int,int>> {\n        vector<pair<int,int>> route;\n        route.reserve(2 * M + 2);\n        route.push_back({XOFF, YOFF});\n        for (int ord : orderSeq) {\n            route.push_back({px[ord], py[ord]});\n            route.push_back({dx[ord], dy[ord]});\n        }\n        route.push_back({XOFF, YOFF});\n        return route;\n    };\n\n    auto nearestNeighborMacroForward = [&](const vector<int>& subset, long long internalSum) -> pair<long long, vector<int>> {\n        vector<char> used(NORD, 0);\n        vector<int> orderSeq;\n        orderSeq.reserve(M);\n\n        int first = subset[0];\n        for (int v : subset) if (startDist[v] < startDist[first]) first = v;\n        orderSeq.push_back(first);\n        used[first] = 1;\n\n        while ((int)orderSeq.size() < M) {\n            int cur = orderSeq.back();\n            int best = -1;\n            int bestCost = INT_MAX;\n            for (int cand : subset) if (!used[cand]) {\n                int cst = getTrans(cur, cand); // drop_cur -> pick_cand\n                if (cst < bestCost) {\n                    bestCost = cst;\n                    best = cand;\n                }\n            }\n            used[best] = 1;\n            orderSeq.push_back(best);\n        }\n\n        long long t = computeMacroTotal(orderSeq, internalSum);\n        return {t, orderSeq};\n    };\n\n    auto nearestNeighborMacroBackward = [&](const vector<int>& subset, long long internalSum) -> pair<long long, vector<int>> {\n        vector<char> used(NORD, 0);\n        vector<int> orderSeq(M);\n\n        int last = subset[0];\n        for (int v : subset) if (endDist[v] < endDist[last]) last = v;\n        orderSeq[M - 1] = last;\n        used[last] = 1;\n\n        for (int pos = M - 2; pos >= 0; pos--) {\n            int cur = orderSeq[pos + 1]; // in forward order: prev -> cur\n            int best = -1;\n            int bestCost = INT_MAX;\n            for (int cand : subset) if (!used[cand]) {\n                int cst = getTrans(cand, cur); // drop_cand -> pick_cur\n                if (cst < bestCost) {\n                    bestCost = cst;\n                    best = cand;\n                }\n            }\n            used[best] = 1;\n            orderSeq[pos] = best;\n        }\n\n        long long t = computeMacroTotal(orderSeq, internalSum);\n        return {t, orderSeq};\n    };\n\n    auto optimizeMacroForSubset = [&](const vector<int>& subset) -> pair<long long, vector<pair<int,int>>> {\n        long long internalSum = 0;\n        for (int v : subset) internalSum += internal[v];\n\n        auto fwd = nearestNeighborMacroForward(subset, internalSum);\n        auto bwd = nearestNeighborMacroBackward(subset, internalSum);\n\n        vector<int> bestSeq = (fwd.first <= bwd.first) ? fwd.second : bwd.second;\n        long long bestT = min(fwd.first, bwd.first);\n\n        // Local search: swap best-improvement sweeps\n        const int SWAP_SWEEPS = 2;\n        for (int sweep = 0; sweep < SWAP_SWEEPS; sweep++) {\n            bool improved = false;\n            long long curT = bestT;\n            int bi = -1, bj = -1;\n\n            for (int i = 0; i < M; i++) {\n                for (int j = i + 1; j < M; j++) {\n                    swap(bestSeq[i], bestSeq[j]);\n                    long long t = computeMacroTotal(bestSeq, internalSum);\n                    if (t < curT) {\n                        curT = t;\n                        bi = i; bj = j;\n                        improved = true;\n                    }\n                    swap(bestSeq[i], bestSeq[j]);\n                }\n            }\n            if (!improved) break;\n            swap(bestSeq[bi], bestSeq[bj]);\n            bestT = curT;\n        }\n\n        // Local search: insertion (best-improvement) one sweep\n        {\n            long long curT = bestT;\n            int bestI = -1, bestJ = -1;\n            for (int i = 0; i < M; i++) {\n                for (int j = 0; j < M; j++) if (j != i) {\n                    vector<int> tmp = bestSeq;\n                    int val = tmp[i];\n                    tmp.erase(tmp.begin() + i);\n                    tmp.insert(tmp.begin() + j, val);\n                    long long t = computeMacroTotal(tmp, internalSum);\n                    if (t < curT) {\n                        curT = t;\n                        bestI = i; bestJ = j;\n                    }\n                }\n            }\n            if (bestI != -1) {\n                int val = bestSeq[bestI];\n                bestSeq.erase(bestSeq.begin() + bestI);\n                bestSeq.insert(bestSeq.begin() + bestJ, val);\n                bestT = curT;\n            }\n        }\n\n        return {bestT, buildMacroRoute(bestSeq)};\n    };\n\n    auto computeTwoStageTotal = [&](const vector<int>& pickupOrder, const vector<int>& destOrder) -> long long {\n        long long cost = startDist[pickupOrder[0]];\n        for (int i = 0; i + 1 < M; i++) {\n            cost += getPickDist(pickupOrder[i], pickupOrder[i + 1]);\n        }\n        // pickup_last -> drop_first\n        cost += getTrans(destOrder[0], pickupOrder.back()); // dist(pick_last, drop_first)\n        for (int i = 0; i + 1 < M; i++) {\n            cost += getDropDist(destOrder[i], destOrder[i + 1]);\n        }\n        cost += endDist[destOrder.back()];\n        return cost;\n    };\n\n    auto buildTwoStageRouteGreedy = [&](const vector<int>& subset) -> pair<long long, vector<pair<int,int>>> {\n        // Greedy pickup order by nearest neighbor on pickDist\n        vector<char> used(NORD, 0);\n        vector<int> pickupOrder;\n        pickupOrder.reserve(M);\n\n        int first = subset[0];\n        for (int v : subset) if (startDist[v] < startDist[first]) first = v;\n        pickupOrder.push_back(first);\n        used[first] = 1;\n\n        while ((int)pickupOrder.size() < M) {\n            int cur = pickupOrder.back();\n            int best = -1, bestC = INT_MAX;\n            for (int cand : subset) if (!used[cand]) {\n                int cst = getPickDist(cur, cand);\n                if (cst < bestC) { bestC = cst; best = cand; }\n            }\n            used[best] = 1;\n            pickupOrder.push_back(best);\n        }\n\n        // Greedy destination order by nearest neighbor on dropDist, starting from last pickup\n        vector<char> used2(NORD, 0);\n        vector<int> destOrder;\n        destOrder.reserve(M);\n\n        int lastPick = pickupOrder.back();\n        int firstDest = -1, bestC = INT_MAX;\n        for (int v : subset) if (!used2[v]) {\n            int cst = getTrans(v, lastPick); // dist(drop_v, pick_last) == dist(pick_last, drop_v)\n            if (cst < bestC) { bestC = cst; firstDest = v; }\n        }\n        destOrder.push_back(firstDest);\n        used2[firstDest] = 1;\n\n        while ((int)destOrder.size() < M) {\n            int cur = destOrder.back();\n            int best = -1, bestD = INT_MAX;\n            for (int cand : subset) if (!used2[cand]) {\n                int cst = getDropDist(cur, cand);\n                if (cst < bestD) { bestD = cst; best = cand; }\n            }\n            used2[best] = 1;\n            destOrder.push_back(best);\n        }\n\n        long long total = computeTwoStageTotal(pickupOrder, destOrder);\n\n        vector<pair<int,int>> route;\n        route.reserve(2 * M + 2);\n        route.push_back({XOFF, YOFF});\n        for (int ord : pickupOrder) route.push_back({px[ord], py[ord]});\n        for (int ord : destOrder) route.push_back({dx[ord], dy[ord]});\n        route.push_back({XOFF, YOFF});\n        return {total, route};\n    };\n\n    // Candidate subset pools\n    vector<int> ids(NORD);\n    iota(ids.begin(), ids.end(), 0);\n    sort(ids.begin(), ids.end(), [&](int i, int j){ return weight[i] < weight[j]; });\n\n    vector<int> pool;\n    int TOP = 350;\n    for (int i = 0; i < TOP; i++) pool.push_back(ids[i]);\n\n    // Add randomness from the remainder\n    mt19937 rng((uint32_t)chrono::steady_clock::now().time_since_epoch().count());\n    uniform_int_distribution<int> uniAll(0, NORD - 1);\n    while ((int)pool.size() < 500) {\n        int v = uniAll(rng);\n        if (find(pool.begin(), pool.end(), v) == pool.end()) pool.push_back(v);\n    }\n\n    sort(pool.begin(), pool.end());\n    pool.erase(unique(pool.begin(), pool.end()), pool.end());\n\n    auto sampleSubsetWeightedNoReplace = [&](int k) -> vector<int> {\n        // Exponential race sampling without replacement:\n        // key = -log(u) / rate, choose smallest k keys.\n        // We want smaller weight more likely => rate = 1/(weight+1).\n        vector<pair<long double,int>> keys;\n        keys.reserve(pool.size());\n        uniform_real_distribution<long double> ur(1e-12L, 1.0L);\n        for (int v : pool) {\n            long double u = ur(rng);\n            long double rate = 1.0L / ( (long double)weight[v] + 1.0L );\n            long double key = -log(u) / rate;\n            keys.push_back({key, v});\n        }\n        nth_element(keys.begin(), keys.begin() + k, keys.end(),\n                    [](auto &p1, auto &p2){ return p1.first < p2.first; });\n        vector<int> subset;\n        subset.reserve(k);\n        for (int i = 0; i < k; i++) subset.push_back(keys[i].second);\n        return subset;\n    };\n\n    // Global best\n    long long bestT = (1LL<<62);\n    vector<int> bestSubset;\n    vector<pair<int,int>> bestRoute;\n\n    auto trySubset = [&](const vector<int>& subset) {\n        if ((int)subset.size() != M) return;\n\n        auto macro = optimizeMacroForSubset(subset);\n        if (macro.first < bestT) {\n            bestT = macro.first;\n            bestSubset = subset;\n            bestRoute = move(macro.second);\n        }\n\n        auto twoStage = buildTwoStageRouteGreedy(subset);\n        if (twoStage.first < bestT) {\n            bestT = twoStage.first;\n            bestSubset = subset;\n            bestRoute = move(twoStage.second);\n        }\n    };\n\n    // Try a few deterministic subsets first\n    auto pickTopKBy = [&](auto getter) -> vector<int> {\n        vector<int> v = ids;\n        sort(v.begin(), v.end(), [&](int i, int j){ return getter(i) < getter(j); });\n        v.resize(M);\n        return v;\n    };\n\n    trySubset(pickTopKBy([&](int i){ return (long long)internal[i]; }));\n    trySubset(pickTopKBy([&](int i){ return (long long)startDist[i]; }));\n    trySubset(pickTopKBy([&](int i){ return (long long)endDist[i]; }));\n    trySubset(pickTopKBy([&](int i){ return weight[i]; }));\n\n    // Multi-start random subsets\n    auto t0 = chrono::steady_clock::now();\n    int iter = 0;\n    while (true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - t0).count();\n        if (elapsed > 1.75) break;\n        if (iter++ > 90) break;\n\n        vector<int> subset = sampleSubsetWeightedNoReplace(M);\n        // small chance to ensure diversity: occasionally replace one element with a nearby-best one\n        if (iter % 7 == 0) {\n            // Replace the worst-weight element inside subset by something better from top ids (if not present).\n            int wi = -1, worst = -1;\n            for (int t = 0; t < M; t++) {\n                int v = subset[t];\n                if (worst == -1 || weight[v] > weight[subset[wi]]) wi = t;\n            }\n            // find better not in subset\n            sort(subset.begin(), subset.end());\n            vector<char> in(NORD, 0);\n            for (int v : subset) in[v] = 1;\n            int repl = -1;\n            for (int u : ids) {\n                if (!in[u]) { repl = u; break; }\n            }\n            if (repl != -1) subset[wi] = repl;\n            // restore permutation size still M\n        }\n\n        trySubset(subset);\n    }\n\n    // Output best result\n    // Header: chosen order indices\n    cout << M << \"\\n\";\n    // bestSubset may be empty if something went wrong; but should not.\n    if ((int)bestSubset.size() != M) {\n        // fallback: just output first M ids by weight and a trivial macro route ordering\n        vector<int> fallback = ids;\n        fallback.resize(M);\n        bestSubset = fallback;\n        vector<int> seq = fallback;\n        // trivial order: by increasing startDist\n        sort(seq.begin(), seq.end(), [&](int i, int j){ return startDist[i] < startDist[j]; });\n        bestRoute = buildMacroRoute(seq);\n    }\n    for (int i = 0; i < M; i++) {\n        if (i) cout << ' ';\n        cout << (bestSubset[i] + 1);\n    }\n    cout << \"\\n\";\n\n    cout << bestRoute.size() << \"\\n\";\n    for (auto [x, y] : bestRoute) {\n        cout << x << \" \" << y << \" \";\n    }\n    cout << \"\\n\";\n    return 0;\n}","ahc007":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct DSU {\n    int n;\n    vector<int> p, sz;\n    int comps;\n    DSU() : n(0), comps(0) {}\n    DSU(int n_) { init(n_); }\n    void init(int n_) {\n        n = n_;\n        p.resize(n);\n        sz.assign(n, 1);\n        iota(p.begin(), p.end(), 0);\n        comps = n;\n    }\n    int find(int x) {\n        while (p[x] != x) {\n            p[x] = p[p[x]];\n            x = p[x];\n        }\n        return x;\n    }\n    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        comps--;\n        return true;\n    }\n};\n\nstatic inline int distRound(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    double d = std::sqrt((double)dx * dx + (double)dy * dy);\n    return (int)llround(d);\n}\n\n// Check if (DSU_cur accepted edges) + (all remaining edges from remIdx..M-1) is connected.\n// This uses precomputed sufRoot[remIdx][v] = root of v in DSU built with only suffix edges.\nstatic bool feasibleSkip(int N, int remIdx, const DSU &curDSU,\n                          const vector<vector<uint16_t>> &sufRoot) {\n    if (curDSU.comps == 1) return true;\n\n    // Compress current DSU components to ids 0..k-1\n    vector<int> idOfRoot(N, -1);\n    vector<int> compId(N);\n    int k = 0;\n    for (int v = 0; v < N; v++) {\n        int r = curDSU.find(v);\n        int &id = idOfRoot[r];\n        if (id == -1) id = k++;\n        compId[v] = id;\n    }\n    if (k == 1) return true;\n\n    // Build DSU over current components, union components that share a suffix DSU root.\n    DSU comb(k);\n    vector<int> firstA(N, -1); // suffix-root is in [0..N-1]\n    for (int v = 0; v < N; v++) {\n        int a = compId[v];\n        int bRoot = (int)sufRoot[remIdx][v];\n        int &f = firstA[bRoot];\n        if (f == -1) f = a;\n        else comb.unite(a, f);\n    }\n    return comb.comps == 1;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M;\n    while ( (cin >> N >> M) ) {\n        vector<int> x(N), y(N);\n        for (int i = 0; i < N; i++) cin >> x[i] >> y[i];\n\n        vector<int> U(M), V(M);\n        for (int i = 0; i < M; i++) {\n            cin >> U[i] >> V[i];\n        }\n\n        vector<int> d(M);\n        for (int i = 0; i < M; i++) {\n            d[i] = distRound(x[U[i]], y[U[i]], x[V[i]], y[V[i]]);\n            if (d[i] == 0) d[i] = 1; // just in case (shouldn't happen in given generator)\n        }\n\n        // Compute MST on proxy weights d_i (offline) to bias heuristic\n        vector<int> ord(M);\n        iota(ord.begin(), ord.end(), 0);\n        sort(ord.begin(), ord.end(), [&](int a, int b){\n            if (d[a] != d[b]) return d[a] < d[b];\n            return a < b;\n        });\n        DSU dsuTmp(N);\n        vector<char> inMST(M, 0);\n        for (int idx : ord) {\n            if (dsuTmp.unite(U[idx], V[idx])) inMST[idx] = 1;\n        }\n\n        // Precompute suffix connectivity roots:\n        // sufRoot[i][v] = DSU root of v using all edges from i..M-1\n        vector<vector<uint16_t>> sufRoot(M + 1, vector<uint16_t>(N));\n        DSU sufDSU(N);\n        for (int v = 0; v < N; v++) sufRoot[M][v] = (uint16_t)v;\n        for (int i = M - 1; i >= 0; i--) {\n            sufDSU.unite(U[i], V[i]);\n            for (int v = 0; v < N; v++) sufRoot[i][v] = (uint16_t)sufDSU.find(v);\n        }\n\n        // Online decisions\n        DSU curDSU(N);\n\n        for (int i = 0; i < M; i++) {\n            long long li;\n            cin >> li;\n\n            int ru = curDSU.find(U[i]);\n            int rv = curDSU.find(V[i]);\n            if (ru == rv) {\n                cout << 0 << \"\\n\" << flush;\n                continue;\n            }\n\n            // Heuristic acceptance threshold based on progress and (optional) MST-bias.\n            double progress = (M <= 1 ? 1.0 : (double)i / (double)(M - 1));\n            double lambda = 1.6 + 1.4 * progress;   // in [1.6, 3.0]\n            if (inMST[i]) lambda += 0.2;          // accept MST-d edges slightly easier\n            else lambda -= 0.1;                   // accept non-tree edges slightly harder\n            lambda = max(1.0, min(3.0, lambda));\n\n            bool accept = false;\n            // accept if li <= lambda * d[i]\n            long double rhs = (long double)lambda * (long double)d[i];\n            if ((long double)li <= rhs) accept = true;\n\n            if (!accept) {\n                // Only skip if still feasible to finish connected.\n                // If we skip edge i, remaining edges start at i+1.\n                bool ok = feasibleSkip(N, i + 1, curDSU, sufRoot);\n                if (!ok) accept = true;\n            }\n\n            if (accept) {\n                curDSU.unite(ru, rv);\n                cout << 1 << \"\\n\" << flush;\n            } else {\n                cout << 0 << \"\\n\" << flush;\n            }\n        }\n\n        // If the judge checks connectivity, the feasibility invariant should guarantee it.\n        // (No extra output here.)\n    }\n    return 0;\n}","ahc008":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const int H = 30, W = 30;\nstatic const int V = H * W;\nstatic const int INF = 1e9;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    cin >> N;\n    vector<int> petType(N);\n    vector<int> petPos(N);\n    vector<char> petAt(V, 0);\n\n    for (int i = 0; i < N; i++) {\n        int px, py, pt;\n        cin >> px >> py >> pt;\n        --px; --py;\n        petPos[i] = px * W + py;\n        petType[i] = pt;\n        petAt[petPos[i]] = 1;\n    }\n\n    int M;\n    cin >> M;\n    vector<int> humanPos(M);\n    vector<char> humanAt(V, 0);\n\n    for (int i = 0; i < M; i++) {\n        int hx, hy;\n        cin >> hx >> hy;\n        --hx; --hy;\n        humanPos[i] = hx * W + hy;\n        humanAt[humanPos[i]] = 1;\n    }\n\n    auto inb = [&](int x, int y) {\n        return (0 <= x && x < H && 0 <= y && y < W);\n    };\n    auto manhattan = [&](int a, int b) {\n        int ax = a / W, ay = a % W;\n        int bx = b / W, by = b % W;\n        return abs(ax - bx) + abs(ay - by);\n    };\n\n    vector<int> dx = {-1, 1, 0, 0};\n    vector<int> dy = {0, 0, -1, 1};\n    // Move char mapping\n    auto moveChar = [&](int from, int to) -> char {\n        int fx = from / W, fy = from % W;\n        int tx = to / W, ty = to % W;\n        if (tx == fx - 1 && ty == fy) return 'U';\n        if (tx == fx + 1 && ty == fy) return 'D';\n        if (tx == fx && ty == fy - 1) return 'L';\n        if (tx == fx && ty == fy + 1) return 'R';\n        return '.';\n    };\n    // Block char mapping (from at adjacent, make to- cell impassable)\n    auto blockChar = [&](int from, int to) -> char {\n        int fx = from / W, fy = from % W;\n        int tx = to / W, ty = to % W;\n        if (tx == fx - 1 && ty == fy) return 'u';\n        if (tx == fx + 1 && ty == fy) return 'd';\n        if (tx == fx && ty == fy - 1) return 'l';\n        if (tx == fx && ty == fy + 1) return 'r';\n        return '.';\n    };\n\n    // ---- 1) Build a low-risk wall path (top to bottom), avoiding initial humans cells ----\n    const int64_t INFLL = (1LL<<60);\n\n    vector<int> cellCost(V, 0);\n    // forbid only initial humans positions\n    vector<char> humanInitAt = humanAt;\n\n    for (int x = 0; x < H; x++) for (int y = 0; y < W; y++) {\n        int id = x * W + y;\n        if (humanInitAt[id]) {\n            cellCost[id] = INF;\n            continue;\n        }\n        int cost = 1;\n        // pets in cell itself (not forbidden by the statement for later, but expensive)\n        if (petAt[id]) cost += 300;\n        // pets adjacent (this blocksability restriction)\n        int danger = 0;\n        for (int k = 0; k < 4; k++) {\n            int nx = x + dx[k], ny = y + dy[k];\n            if (!inb(nx, ny)) continue;\n            int nid = nx * W + ny;\n            if (petAt[nid]) danger++;\n        }\n        cost += danger * 25;\n        cellCost[id] = cost;\n    }\n\n    auto chooseWallPath = [&]() -> vector<int> {\n        // Multi-source Dijkstra from top row to bottom row, using cellCost as node weight.\n        vector<int64_t> dist(V, INFLL);\n        vector<int> parent(V, -1);\n\n        using P = pair<int64_t,int>;\n        priority_queue<P, vector<P>, greater<P>> pq;\n\n        for (int y = 0; y < W; y++) {\n            int s = 0 * W + y;\n            if (cellCost[s] >= INF) continue;\n            dist[s] = cellCost[s];\n            parent[s] = -2; // source marker\n            pq.push({dist[s], s});\n        }\n\n        vector<int> bestBottomCandidates;\n        int bestBottom = -1;\n        int64_t bestDist = INFLL;\n\n        while (!pq.empty()) {\n            auto [d, u] = pq.top(); pq.pop();\n            if (d != dist[u]) continue;\n            int ux = u / W, uy = u % W;\n\n            if (ux == H - 1) {\n                if (d < bestDist) {\n                    bestDist = d;\n                    bestBottom = u;\n                }\n                // don't break: could be multiple sources with same d\n            }\n\n            for (int k = 0; k < 4; k++) {\n                int vx = ux + dx[k], vy = uy + dy[k];\n                if (!inb(vx, vy)) continue;\n                int v = vx * W + vy;\n                if (cellCost[v] >= INF) continue;\n                int64_t nd = d + cellCost[v];\n                if (nd < dist[v]) {\n                    dist[v] = nd;\n                    parent[v] = u;\n                    pq.push({nd, v});\n                }\n            }\n        }\n\n        if (bestBottom == -1) {\n            // fallback: straight-ish middle wall\n            int ymid = W / 2;\n            vector<int> path;\n            for (int x = 0; x < H; x++) path.push_back(x * W + ymid);\n            return path;\n        }\n\n        vector<int> path;\n        int cur = bestBottom;\n        while (true) {\n            path.push_back(cur);\n            int p = parent[cur];\n            if (p == -2) break;\n            cur = p;\n        }\n        reverse(path.begin(), path.end());\n        return path;\n    };\n\n    vector<int> wall = chooseWallPath();\n    vector<char> wallSet(V, 0);\n    for (int id : wall) wallSet[id] = 1;\n\n    // ---- 2) Decide which side (component) to target using final wall=all wall cells blocked ----\n    auto computeComponentsWithFinalWall = [&]() {\n        vector<char> isBlocked(V, 0);\n        for (int id : wall) isBlocked[id] = 1;\n\n        vector<int> comp(V, -1);\n        int compCnt = 0;\n        vector<int> compSize;\n        vector<int> compPet;\n        vector<int> compHuman;\n\n        for (int i = 0; i < V; i++) {\n            if (isBlocked[i]) continue;\n            if (comp[i] != -1) continue;\n            queue<int> q;\n            q.push(i);\n            comp[i] = compCnt;\n            int sz = 0;\n            int pcount = 0;\n            int hcount = 0;\n            while (!q.empty()) {\n                int u = q.front(); q.pop();\n                sz++;\n                if (petAt[u]) pcount += 1;\n                if (humanInitAt[u]) hcount += 1;\n                int ux = u / W, uy = u % W;\n                for (int k = 0; k < 4; k++) {\n                    int vx = ux + dx[k], vy = uy + dy[k];\n                    if (!inb(vx, vy)) continue;\n                    int v = vx * W + vy;\n                    if (isBlocked[v]) continue;\n                    if (comp[v] == -1) {\n                        comp[v] = compCnt;\n                        q.push(v);\n                    }\n                }\n            }\n            compSize.push_back(sz);\n            compPet.push_back(pcount);\n            compHuman.push_back(hcount);\n            compCnt++;\n        }\n        return tuple<vector<int>, vector<int>, vector<int>, vector<int>, int>(comp, compSize, compPet, compHuman, compCnt);\n    };\n\n    auto [compFinal, compSize, compPet, compHuman, compCnt] = computeComponentsWithFinalWall();\n\n    int desiredComp = -1;\n    long long bestMetric = (1LL<<62);\n    for (int c = 0; c < compCnt; c++) {\n        long long p = compPet[c];\n        long long hcount = compHuman[c];\n        long long sz = compSize[c];\n        // Bias toward fewer pets and toward components containing more humans initially\n        long long metric = p * 100 - hcount * 60 - sz;\n        if (metric < bestMetric) {\n            bestMetric = metric;\n            desiredComp = c;\n        }\n    }\n    if (desiredComp == -1) desiredComp = 0;\n\n    // ---- 3) Pick targets in desired component (spread them a bit) ----\n    vector<int> desiredCells;\n    desiredCells.reserve(V);\n    for (int id = 0; id < V; id++) {\n        if (compFinal[id] == desiredComp) desiredCells.push_back(id);\n    }\n\n    auto distToWallManhattan = [&](int id) -> int {\n        int best = INT_MAX;\n        for (int w : wall) best = min(best, manhattan(id, w));\n        return best;\n    };\n    auto distToBoundary = [&](int id) -> int {\n        int x = id / W, y = id % W;\n        return min({x, H - 1 - x, y, W - 1 - y});\n    };\n\n    vector<pair<int,int>> scored; // (score, id)\n    scored.reserve(desiredCells.size());\n    for (int id : desiredCells) {\n        int s = distToWallManhattan(id) * 2 + distToBoundary(id);\n        scored.push_back({s, id});\n    }\n    sort(scored.begin(), scored.end(), [&](auto a, auto b){ return a.first > b.first; });\n\n    // candidates from top K\n    int TOPK = min<int>(120, (int)scored.size());\n    vector<int> cand;\n    for (int i = 0; i < TOPK; i++) cand.push_back(scored[i].second);\n\n    vector<int> targets;\n    targets.reserve(M);\n\n    // Greedy farthest-point selection among cand, to spread humans\n    if (!cand.empty()) {\n        targets.push_back(cand[0]);\n        while ((int)targets.size() < M && (int)targets.size() < (int)cand.size()) {\n            int bestId = -1;\n            int bestVal = -1;\n            for (int id : cand) {\n                int mind = INT_MAX;\n                for (int t : targets) mind = min(mind, manhattan(id, t));\n                // primary: spread, secondary: base score\n                int baseScore = 0;\n                // compute baseScore from scored list quickly via dist heuristic again:\n                baseScore = distToWallManhattan(id) * 2 + distToBoundary(id);\n                int val = mind * 3 + baseScore;\n                if (val > bestVal) {\n                    bestVal = val;\n                    bestId = id;\n                }\n            }\n            if (bestId == -1) break;\n            // Avoid duplicates\n            if (find(targets.begin(), targets.end(), bestId) == targets.end())\n                targets.push_back(bestId);\n            else break;\n        }\n    }\n\n    if (targets.empty()) targets.push_back(desiredCells.empty() ? 0 : desiredCells[0]);\n    while ((int)targets.size() < M) targets.push_back(targets.back());\n\n    // Assign each human a target (spread)\n    vector<int> humanTarget(M);\n    for (int i = 0; i < M; i++) humanTarget[i] = targets[i];\n\n    // ---- 4) Interactive simulation ----\n    int builder = 0; // choose one human as wall builder\n    vector<int> waitCnt(wall.size(), 0);\n    const int MAX_WAIT = 25;\n\n    // blocked cells actually placed so far\n    vector<char> blocked(V, 0);\n\n    auto isAdj = [&](int a, int b) {\n        int ax = a / W, ay = a % W;\n        int bx = b / W, by = b % W;\n        return abs(ax - bx) + abs(ay - by) == 1;\n    };\n\n    auto canBlockNow = [&](int cell, const vector<char>& petAtNow, const vector<char>& humanAtNow) -> bool {\n        if (cell < 0 || cell >= V) return false;\n        if (blocked[cell]) return false;\n        if (petAtNow[cell]) return false;\n        if (humanAtNow[cell]) return false;\n        int x = cell / W, y = cell % W;\n        for (int k = 0; k < 4; k++) {\n            int nx = x + dx[k], ny = y + dy[k];\n            if (!inb(nx, ny)) continue;\n            int nid = nx * W + ny;\n            if (petAtNow[nid]) return false;\n        }\n        return true;\n    };\n\n    // BFS for builder to reach adjacency around next wall cell\n    auto builderNextMove = [&](int bpos, int wcell) -> int {\n        // candidates: neighbors of wcell that are not blocked\n        vector<int> cand;\n        int wx = wcell / W, wy = wcell % W;\n        for (int k = 0; k < 4; k++) {\n            int nx = wx + dx[k], ny = wy + dy[k];\n            if (!inb(nx, ny)) continue;\n            int nid = nx * W + ny;\n            if (!blocked[nid]) cand.push_back(nid);\n        }\n        if (cand.empty()) return bpos;\n\n        vector<int> dist(V, -1), par(V, -1);\n        queue<int> q;\n        dist[bpos] = 0;\n        q.push(bpos);\n\n        while (!q.empty()) {\n            int u = q.front(); q.pop();\n            int ux = u / W, uy = u % W;\n            for (int k = 0; k < 4; k++) {\n                int vx = ux + dx[k], vy = uy + dy[k];\n                if (!inb(vx, vy)) continue;\n                int v = vx * W + vy;\n                if (blocked[v]) continue;\n                if (dist[v] == -1) {\n                    dist[v] = dist[u] + 1;\n                    par[v] = u;\n                    q.push(v);\n                }\n            }\n        }\n\n        int best = -1;\n        int bestD = INT_MAX;\n        for (int s : cand) {\n            if (dist[s] != -1 && dist[s] < bestD) {\n                bestD = dist[s];\n                best = s;\n            }\n        }\n        if (best == -1) return bpos;\n\n        // next step from bpos towards best\n        int cur = best;\n        while (par[cur] != bpos && par[cur] != -1) cur = par[cur];\n        if (par[cur] == -1) return bpos;\n        return cur;\n    };\n\n    // Dijkstra/A* for human movement to target\n    auto nextStepToTarget = [&](int start, int target, int forbiddenCell, int PENALTY) -> int {\n        if (start == target) return start;\n\n        vector<int> dist(V, INF);\n        vector<int> par(V, -1);\n        using P = pair<int,int>;\n        priority_queue<P, vector<P>, greater<P>> pq;\n        dist[start] = 0;\n        pq.push({0, start});\n\n        while (!pq.empty()) {\n            auto [d, u] = pq.top(); pq.pop();\n            if (d != dist[u]) continue;\n            if (u == target) break;\n\n            int ux = u / W, uy = u % W;\n            for (int k = 0; k < 4; k++) {\n                int vx = ux + dx[k], vy = uy + dy[k];\n                if (!inb(vx, vy)) continue;\n                int v = vx * W + vy;\n\n                if (blocked[v]) continue;\n                if (forbiddenCell != -1 && v == forbiddenCell) continue;\n\n                int cost = 1;\n                if (wallSet[v] && !blocked[v]) cost += PENALTY; // discourage standing on wall cells early\n                // Pets/humans are allowed to be on squares; so no restrictions here.\n\n                if (dist[v] > d + cost) {\n                    dist[v] = d + cost;\n                    par[v] = u;\n                    pq.push({dist[v], v});\n                }\n            }\n        }\n\n        if (dist[target] == INF) return start;\n        // reconstruct next\n        int cur = target;\n        while (par[cur] != -1 && par[cur] != start) cur = par[cur];\n        if (par[cur] == -1) return start;\n        return cur;\n    };\n\n    int idx = 0; // next wall cell to block\n    const int MOVE_LIMIT = 200; // after this, stop moving other humans (heuristic)\n\n    for (int turn = 0; turn < 300; turn++) {\n        // update petAt/humanAt at start of this turn\n        fill(petAt.begin(), petAt.end(), 0);\n        for (int i = 0; i < N; i++) petAt[petPos[i]] = 1;\n\n        fill(humanAt.begin(), humanAt.end(), 0);\n        for (int i = 0; i < M; i++) humanAt[humanPos[i]] = 1;\n\n        int plannedBlock = -1;\n        vector<char> action(M, '.');\n\n        // decide builder action first\n        if (idx < (int)wall.size()) {\n            int wcell = wall[idx];\n            int bpos = humanPos[builder];\n\n            if (isAdj(bpos, wcell)) {\n                if (canBlockNow(wcell, petAt, humanAt)) {\n                    plannedBlock = wcell;\n                    action[builder] = blockChar(bpos, wcell);\n                    // after executing, we will set blocked and idx++\n                } else {\n                    waitCnt[idx]++;\n                    if (waitCnt[idx] > MAX_WAIT) {\n                        idx++; // skip this wall cell\n                        action[builder] = '.';\n                    } else {\n                        action[builder] = '.';\n                    }\n                }\n            } else {\n                action[builder] = ' ';\n                int next = builderNextMove(bpos, wcell);\n                if (next == bpos) action[builder] = '.';\n                else action[builder] = moveChar(bpos, next);\n            }\n        } else {\n            action[builder] = '.';\n        }\n\n        // decide other humans\n        const int PENALTY = 30;\n        bool moveOthers = (turn < MOVE_LIMIT) || (idx < (int)wall.size());\n        for (int i = 0; i < M; i++) {\n            if (i == builder) continue;\n            if (!moveOthers) {\n                action[i] = '.';\n                continue;\n            }\n            int start = humanPos[i];\n            int target = humanTarget[i];\n\n            if (start == target) {\n                action[i] = '.';\n                continue;\n            }\n            // forbidden: the exact cell the builder will block this turn (if any)\n            int forbid = plannedBlock;\n\n            int next = nextStepToTarget(start, target, forbid, PENALTY);\n            if (next == start) action[i] = '.';\n            else action[i] = moveChar(start, next);\n        }\n\n        // output\n        string s;\n        s.reserve(M);\n        for (int i = 0; i < M; i++) s.push_back(action[i]);\n        cout << s << endl;\n        cout.flush();\n\n        // apply builder's action effects on internal state (simultaneous with humans)\n        // but pets will move after; we read them from input next.\n        // Apply humans movements + wall blocks for next state's humans/blocked.\n        for (int i = 0; i < M; i++) {\n            char c = action[i];\n            int x = humanPos[i] / W, y = humanPos[i] % W;\n            if (c == '.' ) {\n                continue;\n            } else if (c == 'U' || c == 'D' || c == 'L' || c == 'R') {\n                if (c == 'U') x--;\n                if (c == 'D') x++;\n                if (c == 'L') y--;\n                if (c == 'R') y++;\n                humanPos[i] = x * W + y;\n            } else {\n                // lowercase: block one adjacent cell\n                int bx = x, by = y;\n                if (c == 'u') bx--;\n                if (c == 'd') bx++;\n                if (c == 'l') by--;\n                if (c == 'r') by++;\n                int cell = bx * W + by;\n                if (0 <= cell && cell < V) blocked[cell] = 1;\n            }\n        }\n\n        // If builder actually planned to block, update idx and waitCnt\n        if (plannedBlock != -1) {\n            // plannedBlock must correspond to current idx wall cell\n            waitCnt[idx] = 0;\n            idx++;\n        }\n\n        // read pet movement strings\n        for (int i = 0; i < N; i++) {\n            string mv;\n            cin >> mv;\n            int pos = petPos[i];\n            int x = pos / W, y = pos % W;\n            if (mv != \".\") {\n                for (char ch : mv) {\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                petPos[i] = x * W + y;\n            }\n            // '.' => unchanged\n        }\n    }\n\n    return 0;\n}","ahc009":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int H = 20;\nstatic constexpr int W = 20;\nstatic constexpr int N = H * W;\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> hwall(H); // between (i,j) and (i,j+1), size 20x19\n    for (int i = 0; i < H; i++) {\n        cin >> hwall[i]; // length 19\n    }\n    vector<string> vwall(H - 1); // between (i,j) and (i+1,j), size 19x20\n    for (int i = 0; i < H - 1; i++) {\n        cin >> vwall[i]; // length 20\n    }\n\n    int start = si * W + sj;\n    int target = ti * W + tj;\n    long double P = (long double)p;\n    long double Q = 1.0L - P;\n\n    // direction indices: 0=U, 1=D, 2=L, 3=R\n    const char dirChar[4] = {'U','D','L','R'};\n    int moveTo[N][4];\n\n    auto id = [&](int r, int c) { return r * W + c; };\n\n    for (int r = 0; r < H; r++) {\n        for (int c = 0; c < W; c++) {\n            int v = id(r, c);\n\n            // U\n            if (r == 0) moveTo[v][0] = v;\n            else {\n                // wall between (r-1,c) and (r,c) is vwall[r-1][c]\n                if (vwall[r-1][c] == '1') moveTo[v][0] = v;\n                else moveTo[v][0] = id(r-1, c);\n            }\n            // D\n            if (r == H-1) moveTo[v][1] = v;\n            else {\n                if (vwall[r][c] == '1') moveTo[v][1] = v;\n                else moveTo[v][1] = id(r+1, c);\n            }\n            // L\n            if (c == 0) moveTo[v][2] = v;\n            else {\n                // wall between (r,c-1) and (r,c) is hwall[r][c-1]\n                if (hwall[r][c-1] == '1') moveTo[v][2] = v;\n                else moveTo[v][2] = id(r, c-1);\n            }\n            // R\n            if (c == W-1) moveTo[v][3] = v;\n            else {\n                // wall between (r,c) and (r,c+1) is hwall[r][c]\n                if (hwall[r][c] == '1') moveTo[v][3] = v;\n                else moveTo[v][3] = id(r, c+1);\n            }\n        }\n    }\n\n    // BFS distances from target in the static grid graph (ignoring forgetting)\n    const int INF = 1e9;\n    vector<int> dist(N, INF);\n    queue<int> q;\n    dist[target] = 0;\n    q.push(target);\n\n    while (!q.empty()) {\n        int v = q.front(); q.pop();\n        int dv = dist[v];\n        for (int a = 0; a < 4; a++) {\n            int u = moveTo[v][a];\n            if (u == v) continue; // blocked edge\n            if (dist[u] > dv + 1) {\n                dist[u] = dv + 1;\n                q.push(u);\n            }\n        }\n    }\n\n    // Horizon\n    int L = 200;\n\n    vector<long double> distOverQ(N);\n    for (int v = 0; v < N; v++) {\n        distOverQ[v] = (long double)dist[v] / Q; // Q>0 guaranteed since p<=0.5\n    }\n\n    // potential[t][v], where t is 0-indexed (meaning \"after next action at time t+1\")\n    // potential = max(0, 401 - (time_est)) if time_est<=L else 0\n    vector<long double> pot((size_t)L * N, 0.0L);\n    for (int t = 0; t < L; t++) {\n        int tNext = t + 1;\n        for (int v = 0; v < N; v++) {\n            long double te = (long double)tNext + distOverQ[v]; // expected time estimate\n            if (te <= (long double)L) {\n                long double val = 401.0L - te;\n                if (val < 0) val = 0;\n                pot[(size_t)t * N + v] = val;\n            }\n        }\n    }\n\n    auto exactExpected = [&](const string &s) -> long double {\n        vector<long double> dp(N, 0.0L), dpNext(N, 0.0L);\n        dp[start] = 1.0L;\n        long double ans = 0.0L;\n\n        for (int t = 0; t < (int)s.size(); t++) {\n            int a = -1;\n            if (s[t] == 'U') a = 0;\n            else if (s[t] == 'D') a = 1;\n            else if (s[t] == 'L') a = 2;\n            else a = 3;\n\n            fill(dpNext.begin(), dpNext.end(), 0.0L);\n            long double probReach = 0.0L;\n\n            for (int v = 0; v < N; v++) {\n                if (v == target) continue;\n                long double dv = dp[v];\n                if (dv == 0.0L) continue;\n\n                int v2 = moveTo[v][a];\n                if (v2 == target) {\n                    probReach += dv * Q;      // remembered and moved into target\n                    dpNext[v] += dv * P;     // forgotten => stay at v\n                } else {\n                    dpNext[v2] += dv * Q;    // remembered and moved\n                    dpNext[v] += dv * P;     // forgotten => stay\n                }\n            }\n\n            ans += probReach * (401.0L - (long double)(t+1));\n            dp.swap(dpNext);\n        }\n        return ans;\n    };\n\n    int K = 3; // number of diversified candidates\n    vector<string> candidates;\n    candidates.reserve(K);\n\n    for (int cand = 0; cand < K; cand++) {\n        // RNG seed\n        long long seed = 123456789LL;\n        seed ^= (long long)si * 10007 + sj * 1009;\n        seed ^= (long long)ti * 10037 + tj * 997;\n        seed ^= (long long)((p + 1e-12) * 100000.0);\n        seed ^= (long long)cand * 1000003LL;\n        std::mt19937 rng((uint32_t)seed);\n\n        long double eps = (cand == 0 ? 0.0L : 0.12L);\n\n        vector<long double> dp(N, 0.0L), dpNext(N, 0.0L);\n        vector<long double> bestBuf(N, 0.0L), secondBuf(N, 0.0L);\n\n        dp[start] = 1.0L;\n        string seq;\n        seq.reserve(L);\n\n        for (int t = 0; t < L; t++) {\n            long double bestScore = -1e100L, secondScore = -1e100L;\n            int bestA = 0, secondA = 0;\n            bool hasSecond = false;\n\n            for (int a = 0; a < 4; a++) {\n                fill(dpNext.begin(), dpNext.end(), 0.0L);\n                long double probReach = 0.0L;\n\n                for (int v = 0; v < N; v++) {\n                    if (v == target) continue;\n                    long double dv = dp[v];\n                    if (dv == 0.0L) continue;\n\n                    int v2 = moveTo[v][a];\n                    if (v2 == target) {\n                        probReach += dv * Q;\n                        dpNext[v] += dv * P;\n                    } else {\n                        dpNext[v2] += dv * Q;\n                        dpNext[v] += dv * P;\n                    }\n                }\n\n                long double score = probReach * (401.0L - (long double)(t + 1));\n                // heuristic future value\n                size_t base = (size_t)t * N;\n                for (int u = 0; u < N; u++) {\n                    if (u == target) continue;\n                    long double du = dpNext[u];\n                    if (du == 0.0L) continue;\n                    score += du * pot[base + u];\n                }\n\n                if (score > bestScore) {\n                    secondScore = bestScore;\n                    secondA = bestA;\n                    hasSecond = true;\n                    bestScore = score;\n                    bestA = a;\n                    bestBuf = dpNext;\n                } else if (!hasSecond || score > secondScore) {\n                    secondScore = score;\n                    secondA = a;\n                    hasSecond = true;\n                    secondBuf = dpNext;\n                }\n            }\n\n            int chosenA = bestA;\n            if (hasSecond && eps > 0.0L) {\n                // sometimes choose second best\n                long double r = (long double)rng() / (long double)rng.max();\n                if (r < eps) chosenA = secondA;\n            }\n\n            if (chosenA == bestA) dp = bestBuf;\n            else dp = secondBuf;\n\n            seq.push_back(dirChar[chosenA]);\n        }\n\n        candidates.push_back(seq);\n    }\n\n    // Choose best by exact expected value\n    long double bestVal = -1e100L;\n    int bestIdx = 0;\n    for (int i = 0; i < (int)candidates.size(); i++) {\n        long double val = exactExpected(candidates[i]);\n        if (val > bestVal) {\n            bestVal = val;\n            bestIdx = i;\n        }\n    }\n\n    cout << candidates[bestIdx] << \"\\n\";\n    return 0;\n}","ahc010":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 30;\nstatic constexpr int CELLS = N * N;          // 900\nstatic constexpr int DIRS = 4;\nstatic constexpr int STATES = CELLS * DIRS; // 3600\n\n// Directions: 0=left, 1=up, 2=right, 3=down\nstatic constexpr int di[4] = {0, -1, 0, 1};\nstatic constexpr int dj[4] = {-1, 0, 1, 0};\n\nstruct EvalResult {\n    long long score;\n    int best1;\n    int best2;\n    int numCycles;\n};\n\nstatic int8_t toBase[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\n// toRot[t][r][d] = exit direction (0..3) or -1\nstatic int8_t toRot[8][4][4];\n\nstatic int16_t neighCell[CELLS][4]; // neighCell[c][exitDir] = neighbor cell index or -1\n\nstatic uint8_t tileType[CELLS];     // input tile t\nstatic uint8_t rotCurr[CELLS];\nstatic uint8_t rotBest[CELLS];\n\nstatic int nextState[STATES];\nstatic int vis[STATES];\nstatic int posInPath[STATES];\nstatic int pathArr[STATES];\n\nstatic inline long long llmax0(long long x){ return x; }\n\nEvalResult evaluate(const uint8_t rot[CELLS]) {\n    // Build functional graph transitions for all states\n    for (int c = 0; c < CELLS; c++) {\n        int t = tileType[c];\n        int r = rot[c];\n        for (int d = 0; d < 4; d++) {\n            int v = c * 4 + d; // state: enter from direction d\n            int exitDir = toRot[t][r][d];\n            if (exitDir < 0) {\n                nextState[v] = -1;\n                continue;\n            }\n            int nb = neighCell[c][exitDir];\n            if (nb < 0) {\n                nextState[v] = -1;\n                continue;\n            }\n            int entryNext = (exitDir + 2) & 3;\n            nextState[v] = nb * 4 + entryNext;\n        }\n    }\n\n    // Find all directed cycles in this functional graph\n    int best1 = 0, best2 = 0, cnt1 = 0, numCycles = 0;\n    memset(vis, 0, sizeof(vis));\n\n    for (int v0 = 0; v0 < STATES; v0++) {\n        if (vis[v0] != 0) continue;\n\n        int cur = v0;\n        int pathLen = 0;\n        while (cur != -1 && vis[cur] == 0) {\n            vis[cur] = 1;              // in current traversal\n            posInPath[cur] = pathLen; // position in pathArr\n            pathArr[pathLen++] = cur;\n            cur = nextState[cur];\n        }\n\n        if (cur != -1 && vis[cur] == 1) {\n            // Found a cycle: nodes pathArr[posInPath[cur] .. pathLen-1]\n            int len = pathLen - posInPath[cur];\n            numCycles++;\n\n            if (len > best1) {\n                best2 = best1;\n                best1 = len;\n                cnt1 = 1;\n            } else if (len == best1) {\n                cnt1++;\n                if (cnt1 >= 2) best2 = best1;\n            } else if (len > best2) {\n                best2 = len;\n            }\n        }\n\n        // Mark path nodes as done\n        for (int i = 0; i < pathLen; i++) vis[pathArr[i]] = 2;\n    }\n\n    long long score = (numCycles >= 2) ? 1LL * best1 * best2 : 0LL;\n    return {score, best1, best2, numCycles};\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // Precompute rotation mapping\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                // d is global entry direction after rotation by r (CCW)\n                // original entry direction is d_orig = (d + r) mod 4\n                int d_orig = (d + r) & 3;\n                int exit_orig = toBase[t][d_orig];\n                if (exit_orig < 0) {\n                    toRot[t][r][d] = -1;\n                } else {\n                    // exit direction rotates with tile: exit_global = exit_orig - r\n                    toRot[t][r][d] = (exit_orig - r + 4) & 3;\n                }\n            }\n        }\n    }\n\n    // Read input\n    for (int i = 0; i < N; i++) {\n        string s;\n        cin >> s;\n        for (int j = 0; j < N; j++) {\n            int t = s[j] - '0';\n            tileType[i * N + j] = (uint8_t)t;\n        }\n    }\n\n    // Precompute neighbor cells\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            int c = i * N + j;\n            for (int dir = 0; dir < 4; dir++) {\n                int ni = i + di[dir], nj = j + dj[dir];\n                if (0 <= ni && ni < N && 0 <= nj && nj < N) neighCell[c][dir] = ni * N + nj;\n                else neighCell[c][dir] = -1;\n            }\n        }\n    }\n\n    // Random engine\n    mt19937_64 rng((uint64_t)chrono::steady_clock::now().time_since_epoch().count());\n    auto randInt = [&](int L, int R) -> int {\n        uniform_int_distribution<int> dist(L, R);\n        return dist(rng);\n    };\n    auto rand01 = [&]() -> double {\n        return uniform_real_distribution<double>(0.0, 1.0)(rng);\n    };\n\n    const double TIME_LIMIT = 1.85; // seconds\n    auto startTime = chrono::steady_clock::now();\n    auto elapsedSec = [&]() -> double {\n        return chrono::duration<double>(chrono::steady_clock::now() - startTime).count();\n    };\n\n    long long bestScore = -1;\n    int bestRestart = 0;\n\n    // Multi-restart SA\n    for (int restart = 0; restart < 4; restart++) {\n        if (elapsedSec() > TIME_LIMIT) break;\n\n        if (restart == 0) {\n            // deterministic init\n            for (int c = 0; c < CELLS; c++) rotCurr[c] = 0;\n        } else {\n            for (int c = 0; c < CELLS; c++) rotCurr[c] = (uint8_t)randInt(0, 3);\n        }\n\n        EvalResult curRes = evaluate(rotCurr);\n        long long curScore = curRes.score;\n\n        if (curScore > bestScore) {\n            bestScore = curScore;\n            bestRestart = restart;\n            memcpy(rotBest, rotCurr, CELLS);\n        }\n\n        const double tempStart = 1e7;\n        const double tempEnd = 1e3;\n\n        while (elapsedSec() < TIME_LIMIT) {\n            int c = rng() % CELLS;\n            uint8_t oldR = rotCurr[c];\n\n            // Local continuity estimate to bias rotation proposals\n            int t = tileType[c];\n            int local[4];\n            for (int r = 0; r < 4; r++) {\n                int cnt = 0;\n                for (int entry = 0; entry < 4; entry++) {\n                    int exitDir = toRot[t][r][entry];\n                    if (exitDir < 0) continue;\n                    int nb = neighCell[c][exitDir];\n                    if (nb < 0) continue;\n                    int entryNext = (exitDir + 2) & 3;\n                    int nbT = tileType[nb];\n                    int nbR = rotCurr[nb];\n                    if (toRot[nbT][nbR][entryNext] >= 0) cnt++;\n                }\n                local[r] = cnt;\n            }\n\n            uint8_t newR = oldR;\n\n            if (rand01() < 0.15) {\n                // exploration\n                do { newR = (uint8_t)((oldR + 1 + (rng() % 3)) & 3); } while (newR == oldR);\n            } else {\n                // pick among best local rotations excluding old\n                int best = -1;\n                for (int r = 0; r < 4; r++) if ((uint8_t)r != oldR) best = max(best, local[r]);\n                if (best < 0) continue;\n\n                int threshold = best - 1;\n                vector<int> cand;\n                for (int r = 0; r < 4; r++) {\n                    if ((uint8_t)r == oldR) continue;\n                    if (local[r] >= threshold) cand.push_back(r);\n                }\n                if (cand.empty()) {\n                    for (int r = 0; r < 4; r++) if ((uint8_t)r != oldR) cand.push_back(r);\n                }\n                newR = (uint8_t)cand[rng() % cand.size()];\n            }\n\n            if (newR == oldR) continue;\n\n            rotCurr[c] = newR;\n            EvalResult nres = evaluate(rotCurr);\n            long long newScore = nres.score;\n\n            long long delta = newScore - curScore;\n\n            double prog = elapsedSec() / TIME_LIMIT;\n            double temp = tempEnd + (tempStart - tempEnd) * (1.0 - prog);\n            temp = max(temp, 1e-9);\n\n            bool accept = false;\n            if (delta >= 0) {\n                accept = true;\n            } else {\n                double prob = exp((double)delta / temp);\n                if (rand01() < prob) accept = true;\n            }\n\n            if (accept) {\n                curScore = newScore;\n                if (curScore > bestScore) {\n                    bestScore = curScore;\n                    memcpy(rotBest, rotCurr, CELLS);\n                }\n            } else {\n                rotCurr[c] = oldR;\n            }\n        }\n    }\n\n    // Output rotations as a 900-char string\n    string out;\n    out.reserve(CELLS);\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            int c = i * N + j;\n            out.push_back(char('0' + (int)rotBest[c]));\n        }\n    }\n    cout << out << \"\\n\";\n    return 0;\n}","ahc011":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct DSU {\n    int n;\n    vector<int> p, sz;\n    DSU(int n_=0){ init(n_); }\n    void init(int n_) {\n        n = n_;\n        p.resize(n);\n        sz.assign(n, 1);\n        iota(p.begin(), p.end(), 0);\n    }\n    int find(int x){\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 Evaluator {\n    int N, M;\n    vector<pair<int,int>> vertPairs; // (top, bottom)\n    vector<pair<int,int>> horPairs;  // (left, right)\n    DSU dsu;\n    vector<int> compsz, compedges;\n    vector<pair<int,int>> usedEdges;\n\n    Evaluator(int N_) : N(N_), M(N_*N_), dsu(M) {\n        for(int i=0;i<N-1;i++){\n            for(int j=0;j<N;j++){\n                int a = i*N + j;\n                int b = (i+1)*N + j;\n                vertPairs.push_back({a,b});\n            }\n        }\n        for(int i=0;i<N;i++){\n            for(int j=0;j<N-1;j++){\n                int a = i*N + j;\n                int b = i*N + (j+1);\n                horPairs.push_back({a,b});\n            }\n        }\n        compsz.assign(M, 0);\n        compedges.assign(M, 0);\n    }\n\n    inline int eval(const vector<uint8_t>& b) {\n        // b[idx]=0 for empty, else mask\n        dsu.init(M);\n        usedEdges.clear();\n\n        // build unions for edges\n        for(auto [top, bot] : vertPairs){\n            if(b[top] == 0 || b[bot] == 0) continue;\n            // top has down (8), bot has up (2)\n            if( (b[top] & 8) && (b[bot] & 2) ){\n                usedEdges.push_back({top, bot});\n                dsu.unite(top, bot);\n            }\n        }\n        for(auto [L, R] : horPairs){\n            if(b[L] == 0 || b[R] == 0) continue;\n            // L has right (4), R has left (1)\n            if( (b[L] & 4) && (b[R] & 1) ){\n                usedEdges.push_back({L, R});\n                dsu.unite(L, R);\n            }\n        }\n\n        fill(compsz.begin(), compsz.end(), 0);\n        fill(compedges.begin(), compedges.end(), 0);\n\n        // count vertices in each component\n        for(int v=0; v<M; v++){\n            if(b[v] == 0) continue;\n            int r = dsu.find(v);\n            compsz[r]++;\n        }\n\n        // count edges per component\n        for(auto [a,bx] : usedEdges){\n            int r = dsu.find(a);\n            compedges[r]++;\n        }\n\n        int best = 0;\n        for(int r=0; r<M; r++){\n            int vs = compsz[r];\n            if(vs == 0) continue;\n            // acyclic connected component <=> edges == verts - 1\n            if(compedges[r] == vs - 1){\n                best = max(best, vs);\n            }\n        }\n        return best;\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    long long T;\n    cin >> N >> T;\n    vector<string> s(N);\n    for(int i=0;i<N;i++) cin >> s[i];\n\n    int M = N*N;\n    vector<uint8_t> board(M);\n    int emptyIdx = -1;\n    auto hexToVal = [&](char c)->int{\n        if('0'<=c && c<='9') return c-'0';\n        return 10 + (c-'a');\n    };\n    for(int i=0;i<N;i++){\n        for(int j=0;j<N;j++){\n            int v = hexToVal(s[i][j]);\n            int idx = i*N + j;\n            board[idx] = (uint8_t)v;\n            if(v == 0) emptyIdx = idx;\n        }\n    }\n\n    Evaluator evaluator(N);\n    int bestSGlobal = evaluator.eval(board);\n    vector<char> bestMovesGlobal;\n\n    int dr[4] = {-1, 1, 0, 0};\n    int dc[4] = {0, 0, -1, 1};\n    char dirChar[4] = {'U','D','L','R'};\n    int opp[4] = {1,0,3,2};\n\n    auto inBounds = [&](int r,int c)->bool{\n        return 0<=r && r<N && 0<=c && c<N;\n    };\n\n    // deterministic-ish randomness\n    uint64_t seed = (uint64_t)chrono::steady_clock::now().time_since_epoch().count();\n    seed ^= 0x9e3779b97f4a7c15ULL * (uint64_t)N;\n    // mix in board content\n    for(int i=0;i<M;i++) seed = seed * 1315423911u + board[i];\n    mt19937_64 rng(seed);\n\n    auto elapsedSec = [&](){\n        using namespace std::chrono;\n        static auto st = steady_clock::now();\n        return duration<double>(steady_clock::now() - st).count();\n    };\n\n    double LIMIT = 2.75; // keep margin under 3s\n    int maxRestarts = 12;\n\n    for(int restart=0; restart<maxRestarts; restart++){\n        if(elapsedSec() > LIMIT) break;\n\n        vector<uint8_t> b = board;\n        int e = emptyIdx;\n        vector<char> moves;\n        moves.reserve((size_t)T);\n\n        int curS = evaluator.eval(b);\n\n        int bestS = curS;\n        vector<char> bestMoves = moves;\n\n        int prevDir = -1;\n\n        for(long long step=0; step<T; step++){\n            if(curS == N*N - 1) break;\n            if(elapsedSec() > LIMIT) break;\n\n            int er = e / N, ec = e % N;\n\n            // gather legal moves\n            vector<pair<int,int>> cand; // (dir, S')\n            for(int dir=0; dir<4; dir++){\n                int nr = er + dr[dir], nc = ec + dc[dir];\n                if(!inBounds(nr,nc)) continue;\n                int nei = nr*N + nc;\n\n                // try move\n                // apply swap\n                swap(b[e], b[nei]);\n                int s2 = evaluator.eval(b);\n                // undo\n                swap(b[e], b[nei]);\n\n                cand.push_back({dir, s2});\n            }\n\n            if(cand.empty()) break;\n\n            // optional: avoid immediate backtracking if possible\n            vector<pair<int,int>> cand2;\n            if(prevDir != -1){\n                for(auto [dir,s2] : cand){\n                    if(dir != opp[prevDir]) cand2.push_back({dir,s2});\n                }\n            }\n            if(cand2.empty()) cand2 = cand;\n\n            // choose with annealing bias toward higher S\n            int maxS = -1;\n            for(auto [dir,s2] : cand2) maxS = max(maxS, s2);\n\n            // temperature schedule\n            double temp = 2.5 + 3.0 * (1.0 - (double)step / (double)T); // ~5.5 -> 2.5\n\n            // roulette based on exp((s2 - maxS)/temp), so best has weight 1\n            double sumW = 0.0;\n            vector<double> w(cand2.size());\n            for(size_t i=0;i<cand2.size();i++){\n                double diff = (double)(cand2[i].second - maxS); // <=0\n                double x = diff / temp;\n                // clamp to avoid underflow too harshly; exp(-50) ~ 1.9e-22\n                if(x < -50) x = -50;\n                w[i] = exp(x);\n                sumW += w[i];\n            }\n            uniform_real_distribution<double> dist(0.0, sumW);\n            double pick = dist(rng);\n\n            size_t chosen = 0;\n            double acc = 0.0;\n            for(size_t i=0;i<cand2.size();i++){\n                acc += w[i];\n                if(acc >= pick){\n                    chosen = i;\n                    break;\n                }\n            }\n\n            int chosenDir = cand2[chosen].first;\n            int chosenS = cand2[chosen].second;\n\n            // apply chosen move for real\n            int nr = er + dr[chosenDir], nc = ec + dc[chosenDir];\n            int nei = nr*N + nc;\n            swap(b[e], b[nei]);\n            e = nei;\n\n            moves.push_back(dirChar[chosenDir]);\n            prevDir = chosenDir;\n            curS = chosenS;\n\n            if(curS > bestS){\n                bestS = curS;\n                bestMoves = moves;\n            }\n        }\n\n        if(bestS > bestSGlobal){\n            bestSGlobal = bestS;\n            bestMovesGlobal = bestMoves;\n        }\n        if(bestSGlobal == N*N - 1) break;\n    }\n\n    string out;\n    out.reserve(bestMovesGlobal.size());\n    for(char c : bestMovesGlobal) out.push_back(c);\n    cout << out << \"\\n\";\n    return 0;\n}","ahc012":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\n\nstatic const ll LIM = 1000000000LL;\n\nstruct Point {\n    ll x, y;\n};\n\nstruct Candidate {\n    int orient; // 0..3\n    int V, H;\n    vector<ll> cuts1; // proj1 cuts\n    vector<ll> cuts2; // proj2 cuts\n    int matched = -1; // sum min(a_d, b_d)\n};\n\nstatic uint64_t splitmix64(uint64_t &x) {\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\nstruct RNG {\n    uint64_t state;\n    explicit RNG(uint64_t seed) : state(seed) {}\n    ll nextLL(ll l, ll r) {\n        return (ll)(splitmix64(state) % (uint64_t)(r - l + 1)) + l;\n    }\n    int nextInt(int l, int r) { return (int)nextLL(l, r); }\n};\n\nstatic inline ll proj_value(int orient, const Point& p, int which) {\n    // which=0 -> proj1, which=1 -> proj2\n    // Orient definitions:\n    // 0: (x, y)\n    // 1: (x, x+y)\n    // 2: (x, x-y)\n    // 3: (x+y, x-y)\n    if (orient == 0) {\n        if (which == 0) return p.x;\n        else return p.y;\n    } else if (orient == 1) {\n        if (which == 0) return p.x;\n        else return p.x + p.y;\n    } else if (orient == 2) {\n        if (which == 0) return p.x;\n        else return p.x - p.y;\n    } else { // orient == 3\n        if (which == 0) return p.x + p.y;\n        else return p.x - p.y;\n    }\n}\n\nstatic inline bool in_bound(ll v) {\n    return (-LIM <= v && v <= LIM);\n}\n\nstatic ll pick_cut(ll prev, double target, const unordered_set<ll>& occupied, RNG &rng) {\n    // Try around target first.\n    ll base = (ll)floor(target);\n    for (ll delta = -30; delta <= 30; delta++) {\n        ll c = base + delta;\n        if (c <= prev) continue;\n        if (!in_bound(c)) continue;\n        if (occupied.find(c) != occupied.end()) continue;\n        return c;\n    }\n    // Fallback: walk upward until free (should be plenty).\n    // Also randomize step a bit to avoid pathological cases.\n    ll step = rng.nextLL(1, 5);\n    for (ll tries = 0; tries < 5000; tries++) {\n        ll c = prev + 1 + tries * step;\n        if (!in_bound(c)) break;\n        if (occupied.find(c) == occupied.end()) return c;\n    }\n    // Last resort (should never happen).\n    return prev + 1;\n}\n\nstatic vector<ll> make_cuts_by_quantiles(\n    const vector<ll>& sortedProj, // size N\n    const unordered_set<ll>& occupied,\n    int numCuts,\n    RNG &rng,\n    int maxShift // in indices\n) {\n    int N = (int)sortedProj.size();\n    vector<ll> cuts;\n    cuts.reserve(numCuts);\n    if (numCuts <= 0) return cuts;\n    int cols = numCuts + 1;\n    ll prev = (ll)-4e18;\n\n    for (int t = 1; t <= numCuts; t++) {\n        // boundary between column t-1 and t\n        ll desiredLeft = (ll)t * N / cols; // number of points intended on left\n        int idx = (int)desiredLeft; // split: left uses [0..idx-1], right starts at idx\n        if (idx < 1) idx = 1;\n        if (idx > N - 1) idx = N - 1;\n\n        int off = rng.nextInt(-maxShift, maxShift);\n        int idx2 = idx + off;\n        idx2 = max(1, min(N - 1, idx2));\n\n        ll a = sortedProj[idx2 - 1];\n        ll b = sortedProj[idx2];\n\n        double target = ( (double)a + (double)b ) * 0.5;\n\n        ll c = pick_cut(prev, target, occupied, rng);\n        // enforce strictly increasing\n        if (c <= prev) c = prev + 1;\n        // ensure not occupied\n        while (occupied.find(c) != occupied.end()) c++;\n        // still should be within bounds\n        if (!in_bound(c)) {\n            // shift downward if possible\n            while (c > -LIM && occupied.find(c) != occupied.end()) c--;\n            if (!in_bound(c)) c = (prev + 1 > LIM ? LIM : prev + 1);\n        }\n\n        cuts.push_back(c);\n        prev = c;\n    }\n\n    // Ensure strictly increasing (should already).\n    for (int i = 1; i < (int)cuts.size(); i++) {\n        if (cuts[i] <= cuts[i-1]) cuts[i] = cuts[i-1] + 1;\n    }\n    return cuts;\n}\n\nstatic int evaluate_candidate(\n    const vector<Point>& pts,\n    int orient,\n    const vector<ll>& cuts1,\n    const vector<ll>& cuts2,\n    const array<int,11>& a // 1..10\n) {\n    int V = (int)cuts1.size();\n    int H = (int)cuts2.size();\n    int cols = V + 1;\n    int rows = H + 1;\n\n    int cells = cols * rows;\n    vector<int> cnt(cells, 0);\n\n    for (auto &p : pts) {\n        ll p1 = proj_value(orient, p, 0);\n        ll p2 = proj_value(orient, p, 1);\n        // points should never lie on cut lines because we avoided occupied constants,\n        // but even if they do, upper_bound mapping still keeps validity.\n        int col = (int)(upper_bound(cuts1.begin(), cuts1.end(), p1) - cuts1.begin());\n        int row = (int)(upper_bound(cuts2.begin(), cuts2.end(), p2) - cuts2.begin());\n        if (0 <= col && col < cols && 0 <= row && row < rows) {\n            cnt[col * rows + row]++;\n        }\n    }\n\n    array<int,11> b{};\n    b.fill(0);\n    for (int x : cnt) {\n        if (1 <= x && x <= 10) b[x]++;\n    }\n\n    int matched = 0;\n    for (int d = 1; d <= 10; d++) {\n        matched += min(a[d], b[d]);\n    }\n    return matched;\n}\n\nstatic void output_line_vertical(ll x, ostream& out) {\n    // line x = const\n    out << x << \" \" << -LIM << \" \" << x << \" \" << LIM << \"\\n\";\n}\nstatic void output_line_horizontal(ll y, ostream& out) {\n    // line y = const\n    out << -LIM << \" \" << y << \" \" << LIM << \" \" << y << \"\\n\";\n}\nstatic void output_line_x_plus_y(ll c, ostream& out) {\n    // x + y = c, points (0,c) and (1,c-1)\n    out << 0 << \" \" << c << \" \" << 1 << \" \" << (c - 1) << \"\\n\";\n}\nstatic void output_line_x_minus_y(ll c, ostream& out) {\n    // x - y = c, points (c,0) and (c+1,1)\n    out << c << \" \" << 0 << \" \" << (c + 1) << \" \" << 1 << \"\\n\";\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    int totalA = 0;\n    for (int d = 1; d <= 10; d++) {\n        cin >> a[d];\n        totalA += a[d];\n    }\n\n    vector<Point> pts(N);\n    for (int i = 0; i < N; i++) {\n        ll x, y;\n        cin >> x >> y;\n        pts[i] = {x, y};\n    }\n\n    // Precompute sorted projections and occupied sets for orientations.\n    const int ORI = 4;\n    vector<vector<ll>> sortedP1(ORI), sortedP2(ORI);\n    vector<unordered_set<ll>> occ1(ORI), occ2(ORI);\n\n    for (int t = 0; t < ORI; t++) {\n        sortedP1[t].reserve(N);\n        sortedP2[t].reserve(N);\n        occ1[t].reserve(N * 2);\n        occ2[t].reserve(N * 2);\n        for (auto &p : pts) {\n            ll v1 = proj_value(t, p, 0);\n            ll v2 = proj_value(t, p, 1);\n            sortedP1[t].push_back(v1);\n            sortedP2[t].push_back(v2);\n            occ1[t].insert(v1);\n            occ2[t].insert(v2);\n        }\n        sort(sortedP1[t].begin(), sortedP1[t].end());\n        sort(sortedP2[t].begin(), sortedP2[t].end());\n    }\n\n    int M = totalA;\n\n    // Candidate (V,H) pairs: V cuts on proj1, H cuts on proj2.\n    // We'll try combinations where (V+1)*(H+1) is not too far from M.\n    vector<pair<int,int>> pairs;\n    for (int V = 0; V <= K; V++) {\n        int cols = V + 1;\n        // target cells ~ M\n        double approx = (double)M / (double)cols;\n        int H0 = (int)floor(approx) - 1; // so (V+1)*(H0+1) ~ M\n        for (int dh = -4; dh <= 4; dh++) {\n            int H = H0 + dh;\n            if (H < 0 || H > K - V) continue;\n            long long cells = 1LL * (V + 1) * (H + 1);\n            if (cells < max(1, M/4) || cells > 1LL*M*4 + 10) continue;\n            pairs.push_back({V,H});\n        }\n    }\n    // Deduplicate and sort by closeness.\n    sort(pairs.begin(), pairs.end());\n    pairs.erase(unique(pairs.begin(), pairs.end()), pairs.end());\n    sort(pairs.begin(), pairs.end(), [&](auto &p, auto &q){\n        ll c1 = 1LL*(p.first+1)*(p.second+1);\n        ll c2 = 1LL*(q.first+1)*(q.second+1);\n        ll d1 = llabs(c1 - M);\n        ll d2 = llabs(c2 - M);\n        if (d1 != d2) return d1 < d2;\n        return (p.first+p.second) < (q.first+q.second);\n    });\n\n    int maxPairsToTry = min<int>(30, pairs.size());\n    pairs.resize(maxPairsToTry);\n\n    uint64_t seed = chrono::high_resolution_clock::now().time_since_epoch().count();\n    RNG rng(seed);\n\n    Candidate best;\n    best.matched = -1;\n\n    int budgetPerPair = 4; // number of random variants per (orientation, V,H)\n\n    for (int orient = 0; orient < ORI; orient++) {\n        for (auto [V,H] : pairs) {\n            if (V + H > K) continue;\n\n            for (int it = 0; it < budgetPerPair; it++) {\n                // Randomness magnitude:\n                int maxShift = 2 + it; // small perturbations\n\n                auto cuts1 = make_cuts_by_quantiles(sortedP1[orient], occ1[orient], V, rng, maxShift);\n                auto cuts2 = make_cuts_by_quantiles(sortedP2[orient], occ2[orient], H, rng, maxShift);\n\n                // Evaluate\n                int matched = evaluate_candidate(pts, orient, cuts1, cuts2, a);\n                if (matched > best.matched) {\n                    best.matched = matched;\n                    best.orient = orient;\n                    best.V = V;\n                    best.H = H;\n                    best.cuts1 = std::move(cuts1);\n                    best.cuts2 = std::move(cuts2);\n                }\n            }\n        }\n    }\n\n    // Output best candidate.\n    int k = (int)best.cuts1.size() + (int)best.cuts2.size();\n    if (k > K) {\n        // Shouldn't happen, but just in case, truncate (keeping validity).\n        k = 0;\n        best.cuts1.clear();\n        best.cuts2.clear();\n        best.V = best.H = 0;\n    }\n\n    cout << k << \"\\n\";\n    // Which family corresponds to which projection depends on orient.\n    // Family 0: proj1, family 1: proj2.\n    // We output corresponding lines:\n    // orient 0: proj1=x, proj2=y\n    // orient 1: proj1=x, proj2=x+y\n    // orient 2: proj1=x, proj2=x-y\n    // orient 3: proj1=x+y, proj2=x-y\n    for (ll c : best.cuts1) {\n        if (best.orient == 0 || best.orient == 1 || best.orient == 2) {\n            // proj1 = x\n            output_line_vertical(c, cout);\n        } else {\n            // proj1 = x+y\n            output_line_x_plus_y(c, cout);\n        }\n    }\n    for (ll c : best.cuts2) {\n        if (best.orient == 0) {\n            // proj2 = y\n            output_line_horizontal(c, cout);\n        } else if (best.orient == 1) {\n            // proj2 = x+y\n            output_line_x_plus_y(c, cout);\n        } else if (best.orient == 2) {\n            // proj2 = x-y\n            output_line_x_minus_y(c, cout);\n        } else {\n            // orient 3: proj2 = x-y\n            output_line_x_minus_y(c, cout);\n        }\n    }\n\n    return 0;\n}","ahc014":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Edge {\n    // kind: 0=H,1=V,2=D1 (slope +1),3=DM (slope -1)\n    int kind;\n    int a, b; // encoded coordinates (see access functions)\n};\n\nstruct Rect {\n    // vertices in cyclic order around perimeter\n    array<int, 4> v;\n    array<Edge, 4> edges; // 4 unit segments on the perimeter\n};\n\nstruct Candidate {\n    long long key;\n    int rid;\n    bool operator<(Candidate const& other) const {\n        return key < other.key; // max-heap\n    }\n};\n\nstruct SimResult {\n    long long sumWeight = 0;\n    vector<array<int,4>> ops; // p1..p4 as vertex ids\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M;\n    cin >> N >> M;\n    vector<char> initDot(N * N, 0);\n    for (int i = 0; i < M; i++) {\n        int x, y;\n        cin >> x >> y;\n        initDot[x * N + y] = 1;\n    }\n\n    const int c = (N - 1) / 2;\n\n    // Precompute weights for each vertex\n    vector<long long> weight(N * N, 0);\n    for (int x = 0; x < N; x++) for (int y = 0; y < N; y++) {\n        long long dx = x - c;\n        long long dy = y - c;\n        weight[x * N + y] = dx * dx + dy * dy + 1;\n    }\n\n    // Precompute all unit rectangles (axis unit squares + rotated unit diamonds)\n    vector<Rect> rects;\n    rects.reserve((N-1)*(N-1) + (N-3)*(N-2));\n\n    // Helper lambda to add a rect\n    auto addRect = [&](const array<int,4>& v, const array<Edge,4>& edges) {\n        Rect r;\n        r.v = v;\n        r.edges = edges;\n        rects.push_back(r);\n    };\n\n    // Axis-aligned unit squares:\n    // BL(x,y)= (x,y), BR(x+1,y), TR(x+1,y+1), TL(x,y+1)\n    for (int x = 0; x <= N - 2; x++) {\n        for (int y = 0; y <= N - 2; y++) {\n            int bl = x * N + y;\n            int br = (x+1) * N + y;\n            int tr = (x+1) * N + (y+1);\n            int tl = x * N + (y+1);\n            array<int,4> v = {bl, br, tr, tl}; // cyclic clockwise\n            // Edges:\n            // bottom: (x,y)-(x+1,y) => H(a=x,b=y)\n            // right:  (x+1,y)-(x+1,y+1) => V(a=x+1,b=y)\n            // top:    (x,y+1)-(x+1,y+1) => H(a=x,b=y+1)\n            // left:   (x,y)-(x,y+1) => V(a=x,b=y)\n            array<Edge,4> edges = {\n                Edge{0, x, y},\n                Edge{1, x+1, y},\n                Edge{0, x, y+1},\n                Edge{1, x, y}\n            };\n            addRect(v, edges);\n        }\n    }\n\n    // Rotated-by-45 unit diamonds:\n    // A=(x,y), B=(x+1,y+1), C=(x+2,y), D=(x+1,y-1)\n    // cyclic order A->B->C->D\n    for (int x = 0; x <= N - 3; x++) {\n        for (int y = 1; y <= N - 2; y++) {\n            int A = x * N + y;\n            int B = (x+1) * N + (y+1);\n            int C = (x+2) * N + y;\n            int D = (x+1) * N + (y-1);\n            array<int,4> v = {A, B, C, D};\n\n            // Edge marking:\n            // AB: (x,y)-(x+1,y+1) => D1(a=x,b=y) (slope +1)\n            // BC: (x+1,y+1)-(x+2,y) => DM(a=x+1,b=y)   (slope -1, store y_low=y)\n            // CD: (x+2,y)-(x+1,y-1) => D1(a=x+1,b=y-1)\n            // DA: (x+1,y-1)-(x,y) => DM(a=x,b=y-1)\n            array<Edge,4> edges = {\n                Edge{2, x, y},\n                Edge{3, x+1, y},\n                Edge{2, x+1, y-1},\n                Edge{3, x, y-1}\n            };\n            addRect(v, edges);\n        }\n    }\n\n    // Build vertex -> list of rectangles containing it\n    vector<vector<int>> adj(N*N);\n    for (int rid = 0; rid < (int)rects.size(); rid++) {\n        for (int k = 0; k < 4; k++) {\n            adj[rects[rid].v[k]].push_back(rid);\n        }\n    }\n\n    auto run = [&](long long lambdaPotential) -> SimResult {\n        SimResult res;\n        vector<char> dot = initDot;\n\n        int R = (int)rects.size();\n        vector<int> cnt(R, 0);\n        vector<char> usedRect(R, 0);\n\n        // Used edges for condition3\n        // H: (N-1)*N ; index a*N + b, a in [0..N-2], b in [0..N-1]\n        // V: N*(N-1) ; index a*(N-1) + b, a in [0..N-1], b in [0..N-2]\n        // D1: (N-1)*(N-1) ; index a*(N-1) + b, a in [0..N-2], b in [0..N-2]\n        // DM: (N-1)*(N-1) ; same indexing\n        vector<uint8_t> usedH((N-1)*N, 0);\n        vector<uint8_t> usedV(N*(N-1), 0);\n        vector<uint8_t> usedD1((N-1)*(N-1), 0);\n        vector<uint8_t> usedDM((N-1)*(N-1), 0);\n\n        auto edgeUsed = [&](const Edge& e) -> bool {\n            if (e.kind == 0) { // H\n                return usedH[e.a * N + e.b];\n            } else if (e.kind == 1) { // V\n                return usedV[e.a * (N-1) + e.b];\n            } else if (e.kind == 2) { // D1\n                return usedD1[e.a * (N-1) + e.b];\n            } else { // 3 DM\n                return usedDM[e.a * (N-1) + e.b];\n            }\n        };\n        auto setEdgeUsed = [&](const Edge& e) {\n            if (e.kind == 0) {\n                usedH[e.a * N + e.b] = 1;\n            } else if (e.kind == 1) {\n                usedV[e.a * (N-1) + e.b] = 1;\n            } else if (e.kind == 2) {\n                usedD1[e.a * (N-1) + e.b] = 1;\n            } else {\n                usedDM[e.a * (N-1) + e.b] = 1;\n            }\n        };\n\n        auto edgesAvailable = [&](int rid) -> bool {\n            for (auto &e : rects[rid].edges) {\n                if (edgeUsed(e)) return false;\n            }\n            return true;\n        };\n\n        // initial cnt and sumWeight\n        long long sumW = 0;\n        for (int id = 0; id < N*N; id++) if (dot[id]) sumW += weight[id];\n        res.sumWeight = sumW;\n\n        for (int rid = 0; rid < R; rid++) {\n            int ctmp = 0;\n            for (int k = 0; k < 4; k++) ctmp += (dot[rects[rid].v[k]] ? 1 : 0);\n            cnt[rid] = ctmp;\n        }\n\n        priority_queue<Candidate> pq;\n\n        auto pushIfCnt3 = [&](int rid) {\n            if (usedRect[rid]) return;\n            if (cnt[rid] != 3) return;\n\n            // find missing vertex u\n            int missIdx = -1;\n            int u = -1;\n            for (int i = 0; i < 4; i++) {\n                int vid = rects[rid].v[i];\n                if (!dot[vid]) { missIdx = i; u = vid; break; }\n            }\n            if (missIdx == -1) return;\n\n            // potentialCount: rectangles that would become cnt==3 if we add dot at u\n            long long potential = 0;\n            for (int rr : adj[u]) {\n                if (usedRect[rr]) continue;\n                if (cnt[rr] == 2) potential++;\n            }\n            long long key = weight[u] + lambdaPotential * potential;\n            pq.push(Candidate{key, rid});\n        };\n\n        for (int rid = 0; rid < R; rid++) {\n            if (cnt[rid] == 3) pushIfCnt3(rid);\n        }\n\n        while (!pq.empty()) {\n            auto cand = pq.top(); pq.pop();\n            int rid = cand.rid;\n            if (usedRect[rid]) continue;\n            if (cnt[rid] != 3) continue;\n\n            if (!edgesAvailable(rid)) continue;\n\n            int missIdx = -1;\n            int u = -1;\n            for (int i = 0; i < 4; i++) {\n                int vid = rects[rid].v[i];\n                if (!dot[vid]) { missIdx = i; u = vid; break; }\n            }\n            if (missIdx == -1) continue;\n            if (dot[u]) continue; // should not happen\n\n            // Execute the move\n            usedRect[rid] = 1;\n            for (auto &e : rects[rid].edges) setEdgeUsed(e);\n\n            dot[u] = 1;\n            res.sumWeight += weight[u];\n            // record p1..p4 in cyclic order starting from missIdx\n            array<int,4> op;\n            for (int t = 0; t < 4; t++) {\n                op[t] = rects[rid].v[(missIdx + t) % 4];\n            }\n            res.ops.push_back(op);\n\n            // update cnt for adjacent rectangles\n            for (int rr : adj[u]) {\n                if (usedRect[rr]) continue;\n                // u was empty before, now becomes dot -> cnt increases by 1\n                cnt[rr]++;\n                if (cnt[rr] == 3) pushIfCnt3(rr);\n            }\n        }\n\n        return res;\n    };\n\n    // Try two greedy variants\n    SimResult best = run(0);\n    SimResult alt = run(5);\n    if (alt.sumWeight > best.sumWeight) best = std::move(alt);\n\n    // Output\n    cout << best.ops.size() << \"\\n\";\n    for (auto &op : best.ops) {\n        for (int t = 0; t < 4; t++) {\n            int id = op[t];\n            int x = id / N;\n            int y = id % N;\n            cout << x << \" \" << y << (t == 3 ? '\\n' : ' ');\n        }\n    }\n    return 0;\n}","ahc015":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing State = array<array<int,10>,10>;\n\nstatic State tilt(const State& s, int dir) {\n    // dir: 0=F, 1=B, 2=L, 3=R\n    State t{};\n    for (auto &row : t) row.fill(0);\n\n    if (dir == 0) { // Forward: r -> 0\n        for (int c = 0; c < 10; c++) {\n            vector<int> vals;\n            vals.reserve(10);\n            for (int r = 0; r < 10; r++) if (s[r][c] != 0) vals.push_back(s[r][c]);\n            for (int r = 0; r < 10; r++) {\n                if (!vals.empty()) { t[r][c] = vals.front(); vals.erase(vals.begin()); }\n            }\n            // erase is too slow; do index placement instead\n        }\n        // Re-do with index approach (avoid erase cost)\n        for (auto &row : t) row.fill(0);\n        for (int c = 0; c < 10; c++) {\n            vector<int> vals;\n            vals.reserve(10);\n            for (int r = 0; r < 10; r++) if (s[r][c] != 0) vals.push_back(s[r][c]);\n            int k = 0;\n            for (int r = 0; r < 10; r++) {\n                if (k < (int)vals.size()) t[r][c] = vals[k++];\n            }\n        }\n    } else if (dir == 1) { // Backward: r -> 9\n        for (int c = 0; c < 10; c++) {\n            vector<int> vals;\n            vals.reserve(10);\n            for (int r = 9; r >= 0; r--) if (s[r][c] != 0) vals.push_back(s[r][c]);\n            int k = 0;\n            for (int r = 9; r >= 0; r--) {\n                if (k < (int)vals.size()) t[r][c] = vals[k++];\n            }\n        }\n    } else if (dir == 2) { // Left: c -> 0\n        for (int r = 0; r < 10; r++) {\n            vector<int> vals;\n            vals.reserve(10);\n            for (int c = 0; c < 10; c++) if (s[r][c] != 0) vals.push_back(s[r][c]);\n            int k = 0;\n            for (int c = 0; c < 10; c++) {\n                if (k < (int)vals.size()) t[r][c] = vals[k++];\n            }\n        }\n    } else { // dir == 3, Right: c -> 9\n        for (int r = 0; r < 10; r++) {\n            vector<int> vals;\n            vals.reserve(10);\n            for (int c = 9; c >= 0; c--) if (s[r][c] != 0) vals.push_back(s[r][c]);\n            int k = 0;\n            for (int c = 9; c >= 0; c--) {\n                if (k < (int)vals.size()) t[r][c] = vals[k++];\n            }\n        }\n    }\n\n    return t;\n}\n\nstatic long long calcNumerator(const State& s) {\n    bool vis[10][10];\n    for (int r = 0; r < 10; r++) for (int c = 0; c < 10; c++) vis[r][c] = false;\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 sum = 0;\n    int q[100];\n    for (int sr = 0; sr < 10; sr++) for (int sc = 0; sc < 10; sc++) {\n        if (s[sr][sc] == 0 || vis[sr][sc]) continue;\n        int flavor = s[sr][sc];\n\n        int head = 0, tail = 0;\n        q[tail++] = sr * 10 + sc;\n        vis[sr][sc] = true;\n\n        long long cnt = 0;\n        while (head < tail) {\n            int v = q[head++];\n            int r = v / 10, c = v % 10;\n            cnt++;\n            for (int k = 0; k < 4; k++) {\n                int nr = r + dr[k], nc = c + dc[k];\n                if (nr < 0 || nr >= 10 || nc < 0 || nc >= 10) continue;\n                if (vis[nr][nc]) continue;\n                if (s[nr][nc] != flavor) continue;\n                vis[nr][nc] = true;\n                q[tail++] = nr * 10 + nc;\n            }\n        }\n        sum += cnt * cnt;\n    }\n    return sum;\n}\n\nstatic int calcAdj(const State& s) {\n    int adj = 0;\n    for (int r = 0; r < 10; r++) for (int c = 0; c < 10; c++) {\n        int a = s[r][c];\n        if (!a) continue;\n        if (c+1 < 10 && s[r][c+1] == a) adj++;\n        if (r+1 < 10 && s[r+1][c] == a) adj++;\n    }\n    return adj;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    vector<int> f(101);\n    for (int i = 1; i <= 100; i++) cin >> f[i];\n\n    State g{};\n    for (auto &row : g) row.fill(0);\n\n    const char dirChar[4] = {'F','B','L','R'};\n\n    for (int t = 1; t <= 100; t++) {\n        int p;\n        cin >> p;\n\n        // Place into p-th empty cell in front-to-back, left-to-right order.\n        int cntEmpty = 0;\n        int rr = -1, cc = -1;\n        for (int r = 0; r < 10; r++) {\n            for (int c = 0; c < 10; c++) {\n                if (g[r][c] == 0) {\n                    cntEmpty++;\n                    if (cntEmpty == p) { rr = r; cc = c; }\n                }\n            }\n        }\n        g[rr][cc] = f[t];\n\n        if (t == 100) break; // last tilt doesn't affect anything\n\n        long long bestNum = -1;\n        int bestAdj = -1;\n        int bestDir = 0;\n\n        for (int dir = 0; dir < 4; dir++) {\n            State ng = tilt(g, dir);\n            long long num = calcNumerator(ng);\n            int adj = calcAdj(ng);\n            if (num > bestNum || (num == bestNum && adj > bestAdj)) {\n                bestNum = num;\n                bestAdj = adj;\n                bestDir = dir;\n            }\n        }\n\n        g = tilt(g, bestDir);\n        cout << dirChar[bestDir] << '\\n' << flush;\n    }\n\n    return 0;\n}","ahc016":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Candidate {\n    vector<uint64_t> canonBits; // flattened upper-triangle adjacency in canonical order\n    int edges = 0;\n    long long twoStars = 0;\n    long long triangles = 0;\n    vector<int> degSorted;\n};\n\nstatic inline uint64_t splitmix64(uint64_t x) {\n    x += 0x9e3779b97f4a7c15ULL;\n    x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9ULL;\n    x = (x ^ (x >> 27)) * 0x94d049bb133111ebULL;\n    return x ^ (x >> 31);\n}\n\nstruct WLCanonicalizer {\n    int N;\n    int L; // number of WL refinement steps\n    vector<long long> offset; // upper-triangle offsets in canonical order\n    int T; // N*(N-1)/2\n    uint64_t fullMask;\n    vector<uint64_t> greaterMask;\n\n    WLCanonicalizer(int N_, int L_) : N(N_), L(L_) {\n        offset.assign(N, 0);\n        for (int i = 0; i < N; i++) {\n            offset[i] = 1LL * i * (2LL * N - i - 1) / 2;\n        }\n        T = N * (N - 1) / 2;\n\n        fullMask = (N == 64 ? ~0ULL : ((1ULL << N) - 1));\n        greaterMask.assign(N, 0);\n        for (int j = 0; j < N; j++) {\n            uint64_t le = (j == 63 ? ~0ULL : ((1ULL << (j + 1)) - 1));\n            greaterMask[j] = fullMask & ~le;\n        }\n    }\n\n    // Compute degrees and triangles from adjacency (stored as row bitmasks)\n    static inline int popcnt_u64(uint64_t x) { return (int)__builtin_popcountll(x); }\n\n    void features(const vector<uint64_t>& adj, int &edges, long long &twoStars, long long &triangles,\n                   vector<int> *degSortedOut = nullptr) const {\n        vector<int> deg(N);\n        edges = 0;\n        twoStars = 0;\n        for (int i = 0; i < N; i++) {\n            deg[i] = popcnt_u64(adj[i]);\n            edges += deg[i];\n            twoStars += 1LL * deg[i] * (deg[i] - 1) / 2;\n        }\n        edges /= 2;\n\n        triangles = 0;\n        for (int i = 0; i < N; i++) {\n            for (int j = i + 1; j < N; j++) {\n                if ((adj[i] >> j) & 1ULL) {\n                    uint64_t common = adj[i] & adj[j] & greaterMask[j];\n                    triangles += popcnt_u64(common);\n                }\n            }\n        }\n\n        if (degSortedOut) {\n            vector<int> ds = deg;\n            sort(ds.begin(), ds.end());\n            *degSortedOut = std::move(ds);\n        }\n    }\n\n    // WL colors over rounds: col[r][v]\n    vector<int> canonicalOrder(const vector<uint64_t>& adj) const {\n        vector<int> deg(N);\n        for (int v = 0; v < N; v++) deg[v] = popcnt_u64(adj[v]);\n\n        vector<vector<uint64_t>> col(L + 1, vector<uint64_t>(N, 0));\n        // round 0: color by degree (hashed)\n        for (int v = 0; v < N; v++) {\n            col[0][v] = splitmix64((uint64_t)deg[v] + 0x9e3779b97f4a7c15ULL);\n        }\n\n        const uint64_t A1 = 0x1234567890abcdefULL;\n        const uint64_t A2 = 0xfedcba0987654321ULL;\n        const uint64_t A3 = 0x0f0f0f0f0f0f0f0fULL;\n\n        for (int r = 0; r < L; r++) {\n            for (int v = 0; v < N; v++) {\n                uint64_t sum1 = 0, sum2 = 0, xr = 0;\n                int cnt = 0;\n                uint64_t row = adj[v];\n                // iterate neighbors u\n                while (row) {\n                    int u = __builtin_ctzll(row);\n                    row &= row - 1;\n                    uint64_t cu = col[r][u];\n                    sum1 += splitmix64(cu + A1);\n                    sum2 += splitmix64(cu + A2);\n                    xr ^= splitmix64(cu + A3);\n                    cnt++;\n                }\n                uint64_t oldc = col[r][v];\n                uint64_t nc = splitmix64(oldc ^ (sum1 + 0x9e3779b97f4a7c15ULL)) ^\n                              splitmix64(sum2 ^ 0xbf58476d1ce4e5b9ULL) ^\n                              xr ^ splitmix64((uint64_t)cnt + 0x94d049bb133111ebULL);\n                col[r + 1][v] = nc;\n            }\n        }\n\n        vector<int> ord(N);\n        iota(ord.begin(), ord.end(), 0);\n\n        auto cmp = [&](int a, int b) {\n            for (int r = 0; r <= L; r++) {\n                uint64_t ca = col[r][a], cb = col[r][b];\n                if (ca != cb) return ca < cb;\n            }\n            return a < b; // tie-break (rare for random graphs)\n        };\n        sort(ord.begin(), ord.end(), cmp);\n        return ord;\n    }\n\n    vector<uint64_t> canonicalBits(const vector<uint64_t>& adj) const {\n        int W = (T + 63) / 64;\n        vector<uint64_t> bits(W, 0);\n\n        vector<int> ord = canonicalOrder(adj);\n\n        for (int a = 0; a < N; a++) {\n            int oa = ord[a];\n            uint64_t row = adj[oa];\n            for (int b = a + 1; b < N; b++) {\n                int ob = ord[b];\n                if ((row >> ob) & 1ULL) {\n                    int pos = (int)offset[a] + (b - a - 1);\n                    bits[pos >> 6] |= (1ULL << (pos & 63));\n                }\n            }\n        }\n        return bits;\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int M;\n    double epsDouble;\n    cin >> M >> epsDouble;\n    // eps is multiple of 0.01, but keep double for decisions\n    double eps = epsDouble;\n\n    // Choose N based on epsilon to trade off score vs robustness.\n    int N;\n    if (eps <= 0.10) N = 30;\n    else if (eps <= 0.20) N = 35;\n    else if (eps <= 0.30) N = 40;\n    else N = 45;\n\n    int L;\n    if (eps <= 0.20) L = 3;\n    else L = 2;\n\n    WLCanonicalizer canon(N, L);\n\n    // Precompute candidate graphs\n    vector<Candidate> cand(M);\n\n    // RNG seeds\n    uint64_t baseSeed = 0x6a09e667f3bcc909ULL ^ splitmix64((uint64_t)(M * 1000 + int(eps * 100 + 7)));\n    auto nextU64 = [&](uint64_t &state) -> uint64_t {\n        state = splitmix64(state);\n        return state;\n    };\n\n    for (int k = 0; k < M; k++) {\n        uint64_t state = baseSeed ^ splitmix64((uint64_t)k * 0x9e3779b97f4a7c15ULL);\n\n        vector<uint64_t> adj(N, 0ULL);\n        for (int i = 0; i < N; i++) {\n            for (int j = i + 1; j < N; j++) {\n                uint64_t r = nextU64(state);\n                if (r & 1ULL) {\n                    adj[i] |= (1ULL << j);\n                    adj[j] |= (1ULL << i);\n                }\n            }\n        }\n\n        int edges;\n        long long twoStars, triangles;\n        vector<int> degSorted;\n        canon.features(adj, edges, twoStars, triangles, &degSorted);\n\n        vector<uint64_t> cbits = canon.canonicalBits(adj);\n\n        cand[k].canonBits = std::move(cbits);\n        cand[k].edges = edges;\n        cand[k].twoStars = twoStars;\n        cand[k].triangles = triangles;\n        cand[k].degSorted = std::move(degSorted);\n    }\n\n    // Output graphs\n    cout << N << \"\\n\";\n    int T = N * (N - 1) / 2;\n\n    // Output in original vertex labels as required\n    for (int k = 0; k < M; k++) {\n        // We did not store original adj; reconstruct by using the same generation approach:\n        // Instead, to keep code simple and deterministic, re-generate adj here.\n        uint64_t state = baseSeed ^ splitmix64((uint64_t)k * 0x9e3779b97f4a7c15ULL);\n\n        vector<uint64_t> adj(N, 0ULL);\n        auto nextU64_local = [&](uint64_t &st) -> uint64_t {\n            st = splitmix64(st);\n            return st;\n        };\n\n        for (int i = 0; i < N; i++) {\n            for (int j = i + 1; j < N; j++) {\n                uint64_t r = nextU64_local(state);\n                if (r & 1ULL) {\n                    adj[i] |= (1ULL << j);\n                    adj[j] |= (1ULL << i);\n                }\n            }\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                s.push_back(((adj[i] >> j) & 1ULL) ? '1' : '0');\n            }\n        }\n        cout << s << \"\\n\";\n    }\n    cout.flush();\n\n    // Weights for tie-breakers (slightly increase for larger noise)\n    double f = min(1.0, eps / 0.4);\n    double wDeg = 0.03 * (1.0 + f);\n    double wE = 0.05 * (1.0 + f);\n    double w2 = 1e-3 * (1.0 + f);\n    double wT = 0.002 * (1.0 + f);\n\n    for (int q = 0; q < 100; q++) {\n        string H;\n        cin >> H;\n\n        // Parse H into adjacency bitmasks\n        vector<uint64_t> adj(N, 0ULL);\n        int idx = 0;\n        for (int i = 0; i < N; i++) {\n            for (int j = i + 1; j < N; j++) {\n                if (H[idx++] == '1') {\n                    adj[i] |= (1ULL << j);\n                    adj[j] |= (1ULL << i);\n                }\n            }\n        }\n\n        // Features and canonical encoding\n        int edges;\n        long long twoStars, triangles;\n        vector<int> degSorted;\n        canon.features(adj, edges, twoStars, triangles, &degSorted);\n\n        vector<uint64_t> canonH = canon.canonicalBits(adj);\n\n        // Choose best candidate\n        int best = 0;\n        long long bestScore = (1LL << 62);\n\n        int Wc = (T + 63) / 64;\n        for (int k = 0; k < M; k++) {\n            // Hamming distance between canonical bitsets\n            const auto &cb = cand[k].canonBits;\n            long long d = 0;\n            for (int w = 0; w < Wc; w++) {\n                d += __builtin_popcountll(cb[w] ^ canonH[w]);\n            }\n\n            // Tie-breaker distances\n            long long ediff = llabs((long long)edges - cand[k].edges);\n            long long d2 = llabs(twoStars - cand[k].twoStars);\n            long long dt = llabs(triangles - cand[k].triangles);\n\n            long long degDist = 0;\n            for (int i = 0; i < N; i++) degDist += llabs((long long)degSorted[i] - cand[k].degSorted[i]);\n\n            // Weighted sum into integer score\n            // (Multiplications kept as double then cast to ll)\n            long long score = d;\n            score += (long long)llround(wE * (double)ediff);\n            score += (long long)llround(w2 * (double)d2);\n            score += (long long)llround(wT * (double)dt);\n            score += (long long)llround(wDeg * (double)degDist);\n\n            if (score < bestScore) {\n                bestScore = score;\n                best = k;\n            }\n        }\n\n        cout << best << \"\\n\";\n        cout.flush();\n    }\n\n    return 0;\n}","ahc017":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct AdjItem {\n    int to;\n    int eid;\n};\n\nstruct PQNode {\n    double impSum;\n    int cnt;\n    int id;\n    int ver;\n};\n\nstruct PQCmp {\n    bool operator()(const PQNode& a, const PQNode& b) const {\n        if (a.impSum != b.impSum) return a.impSum > b.impSum; // min-heap by impSum\n        if (a.cnt != b.cnt) return a.cnt > b.cnt;             // then min-heap by cnt\n        return a.id > b.id;\n    }\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<int> U(M), V(M);\n    vector<long long> W(M);\n    vector<vector<AdjItem>> g(N);\n\n    for (int i = 0; i < M; i++) {\n        int u, v;\n        long long w;\n        cin >> u >> v >> w;\n        --u; --v;\n        U[i] = u; V[i] = v; W[i] = w;\n        g[u].push_back({v, i});\n        g[v].push_back({u, i});\n    }\n\n    // coordinates are not needed for this heuristic\n    for (int i = 0; i < N; i++) {\n        int x, y;\n        cin >> x >> y;\n    }\n\n    // --- Compute edge importance via (weighted) Brandes-like shortest-path dependency ---\n    // importance[e] ~ edgeBetw[e] * W[e]\n    vector<double> edgeBetw(M, 0.0);\n\n    const long long INF = (1LL<<62);\n    const double SIGMA_LIM = 1e300;\n    const double DELTA_LIM = 1e300;\n\n    vector<long long> dist(N);\n    vector<double> sigma(N), delta(N);\n    vector<vector<pair<int,int>>> pred; // pred[v] = list of (u, eid) where u->v is on a shortest path from source\n    pred.assign(N, {});\n\n    vector<int> order;\n    order.reserve(N);\n\n    auto t_start = chrono::steady_clock::now();\n    const double TIME_LIMIT_SEC = 5.7; // leave margin under 6.0s\n\n    int S = N;\n    // Time safety: if too slow, we stop early.\n    for (int s = 0; s < S; s++) {\n        if (s % 20 == 0) {\n            double elapsed = chrono::duration<double>(chrono::steady_clock::now() - t_start).count();\n            if (elapsed > TIME_LIMIT_SEC) break;\n        }\n\n        // init\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 i = 0; i < N; i++) pred[i].clear();\n        order.clear();\n\n        dist[s] = 0;\n        sigma[s] = 1.0;\n\n        priority_queue<pair<long long,int>, vector<pair<long long,int>>, greater<pair<long long,int>>> pq;\n        pq.push({0, s});\n\n        while (!pq.empty()) {\n            auto [d, v] = pq.top(); pq.pop();\n            if (d != dist[v]) continue;\n            order.push_back(v);\n\n            for (auto [to, eid] : g[v]) {\n                long long nd = d + W[eid];\n                if (nd < dist[to]) {\n                    dist[to] = nd;\n                    pq.push({nd, to});\n\n                    sigma[to] = sigma[v];\n                    pred[to].clear();\n                    pred[to].push_back({v, eid});\n                } else if (nd == dist[to]) {\n                    sigma[to] += sigma[v];\n                    if (sigma[to] > SIGMA_LIM) sigma[to] = SIGMA_LIM;\n                    pred[to].push_back({v, eid});\n                }\n            }\n        }\n\n        // accumulation\n        for (int i = (int)order.size() - 1; i >= 0; i--) {\n            int v = order[i];\n            if (sigma[v] == 0.0) continue;\n            double dv = delta[v];\n\n            for (auto [u, eid] : pred[v]) {\n                // u is predecessor on shortest-path DAG: u -> v\n                if (sigma[u] == 0.0) continue;\n                double c = (sigma[u] / sigma[v]) * (1.0 + dv);\n                if (c > DELTA_LIM) c = DELTA_LIM;\n\n                delta[u] += c;\n                if (delta[u] > DELTA_LIM) delta[u] = DELTA_LIM;\n\n                edgeBetw[eid] += c;\n            }\n        }\n    }\n\n    // undirected correction (each pair counted twice in undirected Brandes)\n    for (int e = 0; e < M; e++) edgeBetw[e] *= 0.5;\n\n    // convert to importance with edge weight factor\n    vector<double> imp(M);\n    double mx = 0.0;\n    for (int e = 0; e < M; e++) {\n        long double val = (long double)edgeBetw[e] * (long double)W[e];\n        double x = (val > 1e300L ? 1e300 : (double)val);\n        imp[e] = x;\n        mx = max(mx, x);\n    }\n    if (mx == 0.0) mx = 1.0;\n    for (int e = 0; e < M; e++) imp[e] /= mx; // normalize to [0..1] roughly\n\n    // --- Greedy scheduling: spread important edges across days with capacity K ---\n    vector<int> idx(M);\n    iota(idx.begin(), idx.end(), 0);\n    sort(idx.begin(), idx.end(), [&](int a, int b) {\n        if (imp[a] != imp[b]) return imp[a] > imp[b];\n        return W[a] > W[b];\n    });\n\n    vector<int> dayOfEdge(M, 0);\n    vector<vector<int>> edgesByDay(D);\n    vector<double> sumImpDay(D, 0.0);\n    vector<int> cntDay(D, 0);\n    vector<int> ver(D, 0);\n\n    priority_queue<PQNode, vector<PQNode>, PQCmp> pq;\n    for (int d = 0; d < D; d++) {\n        pq.push({0.0, 0, d, ver[d]});\n    }\n\n    for (int e : idx) {\n        while (true) {\n            auto cur = pq.top(); pq.pop();\n            int d = cur.id;\n            if (cur.ver != ver[d]) continue;\n            if (cntDay[d] >= K) continue;\n\n            dayOfEdge[e] = d;\n            edgesByDay[d].push_back(e);\n            cntDay[d]++;\n            sumImpDay[d] += imp[e];\n            ver[d]++;\n            pq.push({sumImpDay[d], cntDay[d], d, ver[d]});\n            break;\n        }\n    }\n\n    // --- Local improvement (proxy objective): minimize sum of squares of daily importance ---\n    auto computeP = [&]() -> long double {\n        long double P = 0;\n        for (int d = 0; d < D; d++) P += (long double)sumImpDay[d] * (long double)sumImpDay[d];\n        return P;\n    };\n\n    long double P = computeP();\n\n    for (int it = 0; it < 250; it++) {\n        int A = -1, B = -1;\n        for (int d = 0; d < D; d++) {\n            if (A == -1 || sumImpDay[d] > sumImpDay[A]) A = d;\n            if (B == -1 || sumImpDay[d] < sumImpDay[B]) B = d;\n        }\n        if (A == B) break;\n\n        // Find min/max edges in A and B\n        auto &LA = edgesByDay[A];\n        auto &LB = edgesByDay[B];\n\n        int posMinA = -1, posMaxA = -1, posMinB = -1, posMaxB = -1;\n        double minA = 1e300, maxA = -1e300;\n        double minB = 1e300, maxB = -1e300;\n\n        for (int i = 0; i < (int)LA.size(); i++) {\n            int e = LA[i];\n            if (imp[e] < minA) { minA = imp[e]; posMinA = i; }\n            if (imp[e] > maxA) { maxA = imp[e]; posMaxA = i; }\n        }\n        for (int i = 0; i < (int)LB.size(); i++) {\n            int e = LB[i];\n            if (imp[e] < minB) { minB = imp[e]; posMinB = i; }\n            if (imp[e] > maxB) { maxB = imp[e]; posMaxB = i; }\n        }\n\n        // Candidate 1: swap (minA) <-> (maxB)\n        int eA1 = LA[posMinA], eB1 = LB[posMaxB];\n        double newA1 = sumImpDay[A] - imp[eA1] + imp[eB1];\n        double newB1 = sumImpDay[B] - imp[eB1] + imp[eA1];\n        long double deltaP1 = (long double)newA1 * newA1 + (long double)newB1 * newB1\n                              - ((long double)sumImpDay[A] * sumImpDay[A] + (long double)sumImpDay[B] * sumImpDay[B]);\n\n        // Candidate 2: swap (maxA) <-> (minB)\n        int eA2 = LA[posMaxA], eB2 = LB[posMinB];\n        double newA2 = sumImpDay[A] - imp[eA2] + imp[eB2];\n        double newB2 = sumImpDay[B] - imp[eB2] + imp[eA2];\n        long double deltaP2 = (long double)newA2 * newA2 + (long double)newB2 * newB2\n                              - ((long double)sumImpDay[A] * sumImpDay[A] + (long double)sumImpDay[B] * sumImpDay[B]);\n\n        long double bestDelta = 0;\n        int mode = -1;\n        if (deltaP1 < bestDelta) { bestDelta = deltaP1; mode = 1; }\n        if (deltaP2 < bestDelta) { bestDelta = deltaP2; mode = 2; }\n\n        if (mode == -1) break; // no improvement\n\n        if (mode == 1) {\n            // swap LA[posMinA] and LB[posMaxB]\n            swap(edgesByDay[A][posMinA], edgesByDay[B][posMaxB]);\n            sumImpDay[A] = newA1;\n            sumImpDay[B] = newB1;\n            P += bestDelta;\n        } else {\n            // swap LA[posMaxA] and LB[posMinB]\n            swap(edgesByDay[A][posMaxA], edgesByDay[B][posMinB]);\n            sumImpDay[A] = newA2;\n            sumImpDay[B] = newB2;\n            P += bestDelta;\n        }\n    }\n\n    // --- Output ---\n    for (int e = 0; e < M; e++) {\n        cout << dayOfEdge[e] + 1 << (e + 1 == M ? '\\n' : ' ');\n    }\n    return 0;\n}","ahc019":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Dinic {\n    struct Edge {\n        int to, rev;\n        int cap;\n    };\n    int N;\n    vector<vector<Edge>> g;\n    vector<int> level, it;\n\n    Dinic(int n=0){ init(n); }\n    void init(int n){\n        N = n;\n        g.assign(N, {});\n        level.assign(N, 0);\n        it.assign(N, 0);\n    }\n\n    void add_edge(int fr, int to, int cap){\n        Edge a{to, (int)g[to].size(), cap};\n        Edge b{fr, (int)g[fr].size(), 0};\n        g[fr].push_back(a);\n        g[to].push_back(b);\n    }\n\n    bool bfs(int s, int t){\n        fill(level.begin(), level.end(), -1);\n        queue<int> q;\n        level[s] = 0;\n        q.push(s);\n        while(!q.empty()){\n            int v = q.front(); q.pop();\n            for(auto &e: g[v]){\n                if(e.cap > 0 && level[e.to] < 0){\n                    level[e.to] = level[v] + 1;\n                    q.push(e.to);\n                }\n            }\n        }\n        return level[t] >= 0;\n    }\n\n    int dfs(int v, int t, int f){\n        if(v == t) return f;\n        for(int &i = it[v]; i < (int)g[v].size(); i++){\n            Edge &e = g[v][i];\n            if(e.cap > 0 && level[e.to] == level[v] + 1){\n                int ret = dfs(e.to, t, min(f, e.cap));\n                if(ret > 0){\n                    e.cap -= ret;\n                    g[e.to][e.rev].cap += ret;\n                    return ret;\n                }\n            }\n        }\n        return 0;\n    }\n\n    int max_flow(int s, int t){\n        int flow = 0;\n        while(bfs(s,t)){\n            fill(it.begin(), it.end(), 0);\n            while(true){\n                int pushed = dfs(s,t,INT_MAX);\n                if(!pushed) break;\n                flow += pushed;\n            }\n        }\n        return flow;\n    }\n};\n\nstruct Coord {\n    int x, y, z;\n};\n\nstatic inline int idx3(int D, int x, int y, int z){\n    return x*D*D + y*D + z; // z fastest\n}\n\nstruct ObjectDecomp {\n    vector<pair<int,int>> dominoEdges; // pairs of cube indices in cubes[]\n    vector<int> unitCubes;            // cube indices in cubes[]\n    int keepDominoCount = 0;\n};\n\nstatic vector<pair<int,int>> maxDominoMatching(\n    const vector<Coord>& cubes,\n    const vector<int>& posToCube, // size D^3, maps position->cube index or -1\n    int D\n){\n    int nC = (int)cubes.size();\n    vector<int> cubeToLeft(nC, -1), cubeToRight(nC, -1);\n    vector<int> leftCubes, rightCubes;\n\n    for(int i=0;i<nC;i++){\n        auto c = cubes[i];\n        int p = (c.x + c.y + c.z) & 1;\n        if(p==0){\n            cubeToLeft[i] = (int)leftCubes.size();\n            leftCubes.push_back(i);\n        }else{\n            cubeToRight[i] = (int)rightCubes.size();\n            rightCubes.push_back(i);\n        }\n    }\n    int L = (int)leftCubes.size();\n    int R = (int)rightCubes.size();\n\n    int S = 0;\n    int leftStart = 1;\n    int rightStart = 1 + L;\n    int T = 1 + L + R;\n    Dinic dinic(T+1);\n\n    for(int i=0;i<L;i++) dinic.add_edge(S, leftStart+i, 1);\n    for(int j=0;j<R;j++) dinic.add_edge(rightStart+j, T, 1);\n\n    const int dx[6] = {1,-1,0,0,0,0};\n    const int dy[6] = {0,0,1,-1,0,0};\n    const int dz[6] = {0,0,0,0,1,-1};\n\n    // edges from left cubes to adjacent right cubes\n    for(int li=0; li<L; li++){\n        int uCube = leftCubes[li];\n        auto cu = cubes[uCube];\n        for(int dir=0; dir<6; dir++){\n            int nx = cu.x + dx[dir];\n            int ny = cu.y + dy[dir];\n            int nz = cu.z + dz[dir];\n            if(nx<0||nx>=D||ny<0||ny>=D||nz<0||nz>=D) continue;\n            int p = idx3(D, nx, ny, nz);\n            int vCube = posToCube[p];\n            if(vCube < 0) continue;\n            int rv = cubeToRight[vCube];\n            if(rv >= 0){\n                int vNode = rightStart + rv;\n                int uNode = leftStart + li;\n                dinic.add_edge(uNode, vNode, 1);\n            }\n        }\n    }\n\n    dinic.max_flow(S, T);\n\n    vector<pair<int,int>> matching;\n    // extract used edges: for left node, forward edges cap==0 means matched\n    for(int li=0; li<L; li++){\n        int uCube = leftCubes[li];\n        int uNode = leftStart + li;\n        for(auto &e: dinic.g[uNode]){\n            if(e.to >= rightStart && e.to < rightStart + R){\n                if(e.cap == 0){ // used (was cap 1)\n                    int rIndex = e.to - rightStart;\n                    int vCube = rightCubes[rIndex];\n                    matching.push_back({uCube, vCube});\n                }\n            }\n        }\n    }\n    return matching;\n}\n\nint main(){\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int D;\n    cin >> D;\n\n    // f[i][z][x], r[i][z][y]\n    vector<vector<string>> f(2, vector<string>(D));\n    vector<vector<string>> r(2, vector<string>(D));\n\n    for(int i=0;i<2;i++){\n        for(int z=0; z<D; z++){\n            string s; cin >> s; // length D, x from 0..D-1\n            f[i][z] = s;\n        }\n        for(int z=0; z<D; z++){\n            string s; cin >> s; // length D, y from 0..D-1\n            r[i][z] = s;\n        }\n    }\n\n    auto buildObjectCubes = [&](int i){\n        vector<Coord> cubes;\n        vector<int> posToCube(D*D*D, -1);\n        for(int x=0;x<D;x++){\n            for(int y=0;y<D;y++){\n                for(int z=0;z<D;z++){\n                    if(f[i][z][x] == '1' && r[i][z][y] == '1'){\n                        int p = idx3(D, x,y,z);\n                        int cid = (int)cubes.size();\n                        posToCube[p] = cid;\n                        cubes.push_back(Coord{x,y,z});\n                    }\n                }\n            }\n        }\n        return pair<vector<Coord>, vector<int>>(cubes, posToCube);\n    };\n\n    auto [cubes0, posToCube0] = buildObjectCubes(0);\n    auto [cubes1, posToCube1] = buildObjectCubes(1);\n\n    // maximum domino matchings\n    auto domEdges0_max = maxDominoMatching(cubes0, posToCube0, D);\n    auto domEdges1_max = maxDominoMatching(cubes1, posToCube1, D);\n\n    int k0 = (int)domEdges0_max.size();\n    int k1 = (int)domEdges1_max.size();\n    int keep = min(k0, k1); // shared domino count\n\n    auto decomposeWithKeep = [&](const vector<Coord>& cubes,\n                                  const vector<pair<int,int>>& domEdgesMax,\n                                  int keepCnt) -> ObjectDecomp {\n        int nC = (int)cubes.size();\n        vector<char> used(nC, 0);\n        ObjectDecomp dec;\n        dec.keepDominoCount = keepCnt;\n\n        for(int j=0;j<keepCnt;j++){\n            auto [a,b] = domEdgesMax[j];\n            used[a] = 1;\n            used[b] = 1;\n            dec.dominoEdges.push_back({a,b});\n        }\n        for(int cid=0; cid<nC; cid++){\n            if(!used[cid]) dec.unitCubes.push_back(cid);\n        }\n        return dec;\n    };\n\n    ObjectDecomp dec0 = decomposeWithKeep(cubes0, domEdges0_max, keep);\n    ObjectDecomp dec1 = decomposeWithKeep(cubes1, domEdges1_max, keep);\n\n    int u0 = (int)dec0.unitCubes.size();\n    int u1 = (int)dec1.unitCubes.size();\n\n    int dominoCount = keep;\n    int unitMax = max(u0, u1);\n    int nBlocks = dominoCount + unitMax; // unit ids start at dominoCount+1\n\n    vector<int> b0(D*D*D, 0), b1(D*D*D, 0);\n    int unitOffset = dominoCount + 1;\n\n    // assign domino blocks (ids 1..keep)\n    for(int j=0;j<dominoCount;j++){\n        auto [a,b] = dec0.dominoEdges[j];\n        auto ca = cubes0[a];\n        auto cb = cubes0[b];\n        b0[idx3(D, ca.x, ca.y, ca.z)] = j+1;\n        b0[idx3(D, cb.x, cb.y, cb.z)] = j+1;\n\n        auto [a2,b2] = dec1.dominoEdges[j];\n        auto ca2 = cubes1[a2];\n        auto cb2 = cubes1[b2];\n        b1[idx3(D, ca2.x, ca2.y, ca2.z)] = j+1;\n        b1[idx3(D, cb2.x, cb2.y, cb2.z)] = j+1;\n    }\n\n    // assign unit blocks\n    for(int t=0;t<u0;t++){\n        int cid = dec0.unitCubes[t];\n        auto c = cubes0[cid];\n        b0[idx3(D, c.x, c.y, c.z)] = unitOffset + t;\n    }\n    for(int t=0;t<u1;t++){\n        int cid = dec1.unitCubes[t];\n        auto c = cubes1[cid];\n        b1[idx3(D, c.x, c.y, c.z)] = unitOffset + t;\n    }\n\n    // Output\n    cout << nBlocks << \"\\n\";\n\n    auto printB = [&](const vector<int>& b){\n        for(int x=0;x<D;x++){\n            for(int y=0;y<D;y++){\n                for(int z=0;z<D;z++){\n                    int v = b[idx3(D,x,y,z)];\n                    cout << v;\n                    if(!(x==D-1 && y==D-1 && z==D-1)) cout << ' ';\n                }\n            }\n        }\n        cout << \"\\n\";\n    };\n\n    printB(b0);\n    printB(b1);\n\n    return 0;\n}","ahc020":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\n\nstruct Fenwick {\n    int n;\n    vector<int> bit;\n    int bitMask;\n\n    Fenwick() : n(0), bit(), bitMask(0) {}\n    Fenwick(int n_) { init(n_); }\n\n    void init(int n_) {\n        n = n_;\n        bit.assign(n + 1, 0);\n        bitMask = 1;\n        while (bitMask < n) bitMask <<= 1;\n    }\n\n    void add(int idx, int delta) { // idx: 1..n\n        for (; idx <= n; idx += idx & -idx) bit[idx] += delta;\n    }\n\n    int sumPrefix(int idx) const {\n        int s = 0;\n        for (; idx > 0; idx -= idx & -idx) s += bit[idx];\n        return s;\n    }\n\n    // Smallest index idx such that prefix sum >= k (1-indexed k)\n    int kth(int k) const {\n        int idx = 0;\n        for (int d = bitMask; d > 0; d >>= 1) {\n            int next = idx + d;\n            if (next <= n && bit[next] < k) {\n                idx = next;\n                k -= bit[next];\n            }\n        }\n        return idx + 1;\n    }\n\n    // radii domain is 0..5000, mapped to fenwick indices r+1.\n    // If total = number of items in multiset, and total>0 => last index with nonzero is kth(total).\n    int getMax(int total) const {\n        if (total == 0) return 0;\n        int pos = kth(total); // fenwick index\n        return pos - 1;       // radius = (r+1)-1\n    }\n};\n\nstatic int ceil_sqrt_ll(ll x) {\n    if (x <= 0) return 0;\n    ll r = (ll) sqrt((long double)x);\n    while (r * r < x) ++r;\n    while ((r - 1) * (r - 1) >= x) --r;\n    return (int)r;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, K;\n    cin >> N >> M >> K;\n    vector<ll> x(N), y(N);\n    for (int i = 0; i < N; i++) cin >> x[i] >> y[i];\n\n    vector<int> U(M), V(M);\n    vector<ll> W(M);\n    vector<vector<tuple<int,ll,int>>> adj(N);\n    for (int j = 0; j < M; j++) {\n        cin >> U[j] >> V[j] >> W[j];\n        --U[j]; --V[j];\n        adj[U[j]].push_back({V[j], W[j], j});\n        adj[V[j]].push_back({U[j], W[j], j});\n    }\n\n    vector<ll> ax(K), ay(K);\n    for (int k = 0; k < K; k++) cin >> ax[k] >> ay[k];\n\n    const int LIM = 5000;\n    const int INF_R = LIM + 1;\n\n    // r[i][k] = smallest integer radius P such that dist(i,k) <= P, or INF_R if >5000\n    vector<vector<uint16_t>> r(N, vector<uint16_t>(K, INF_R));\n    for (int i = 0; i < N; i++) {\n        for (int k = 0; k < K; k++) {\n            ll dx = x[i] - ax[k];\n            ll dy = y[i] - ay[k];\n            ll dist2 = dx*dx + dy*dy; // exact integer\n            ll lim2 = 1LL * LIM * LIM;\n            if (dist2 > lim2) {\n                r[i][k] = INF_R;\n            } else {\n                int rr = ceil_sqrt_ll(dist2);\n                if (rr > LIM) rr = INF_R;\n                r[i][k] = (uint16_t)rr;\n            }\n        }\n    }\n\n    // Candidate stations per resident (small list)\n    const int L = 8;\n    vector<vector<int>> cand(K);\n    for (int k = 0; k < K; k++) {\n        vector<pair<int,int>> tmp;\n        tmp.reserve(N);\n        for (int i = 0; i < N; i++) {\n            if (r[i][k] <= LIM) tmp.push_back({(int)r[i][k], i});\n        }\n        // Guaranteed non-empty by statement.\n        sort(tmp.begin(), tmp.end()); // by required radius asc\n        int take = min((int)tmp.size(), L);\n        cand[k].clear();\n        for (int t = 0; t < take; t++) cand[k].push_back(tmp[t].second);\n    }\n\n    // Build shortest-path tree from root 0\n    const ll INF = (1LL<<62);\n    vector<ll> dist(N, INF);\n    vector<int> parent(N, -1), parentEdgeId(N, -1);\n    dist[0] = 0;\n    parent[0] = -1;\n    priority_queue<pair<ll,int>, vector<pair<ll,int>>, greater<pair<ll,int>>> pq;\n    pq.push({0,0});\n\n    // tie-breaking preference: smaller last edge weight, then smaller parent id\n    vector<ll> bestEdgeW(N, INF);\n\n    while (!pq.empty()) {\n        auto [d,u] = pq.top(); pq.pop();\n        if (d != dist[u]) continue;\n        for (auto [v, ww, id] : adj[u]) {\n            ll nd = d + ww;\n            if (nd < dist[v]) {\n                dist[v] = nd;\n                parent[v] = u;\n                parentEdgeId[v] = id;\n                bestEdgeW[v] = ww;\n                pq.push({nd, v});\n            } else if (nd == dist[v]) {\n                if (ww < bestEdgeW[v] || (ww == bestEdgeW[v] && u < parent[v])) {\n                    parent[v] = u;\n                    parentEdgeId[v] = id;\n                    bestEdgeW[v] = ww;\n                }\n            }\n        }\n    }\n\n    vector<ll> weightToParent(N, 0);\n    for (int v = 1; v < N; v++) {\n        weightToParent[v] = W[parentEdgeId[v]];\n    }\n\n    // Local solve for a given initial assignment\n    auto solveTrial = [&](const vector<int>& assignInit) -> tuple<ll, vector<int>, vector<int>> {\n        vector<int> assign = assignInit;\n\n        // Fenwicks for multiset of required radii per station\n        // radii range 0..5000 -> fenwick size 5001, map r->r+1\n        vector<Fenwick> fenw(N);\n        for (int i = 0; i < N; i++) fenw[i].init(LIM + 1);\n\n        vector<int> sz(N, 0);\n        vector<int> P(N, 0);\n\n        for (int k = 0; k < K; k++) {\n            int i = assign[k];\n            int need = (int)r[i][k];\n            // need must be <=5000\n            fenw[i].add(need + 1, +1);\n            sz[i]++;\n        }\n\n        ll Pcost = 0;\n        for (int i = 0; i < N; i++) {\n            if (sz[i] > 0) P[i] = fenw[i].getMax(sz[i]);\n            else P[i] = 0;\n            Pcost += 1LL * P[i] * P[i];\n        }\n\n        // subtreeCnt: number of active stations in subtree\n        // active station = (sz[i] > 0) because residents are not at exact station coords.\n        vector<vector<int>> children(N);\n        for (int v = 1; v < N; v++) {\n            children[parent[v]].push_back(v);\n        }\n        vector<int> subtreeCnt(N, 0);\n        function<int(int)> dfs = [&](int v) -> int {\n            int cnt = (sz[v] > 0) ? 1 : 0;\n            for (int to : children[v]) cnt += dfs(to);\n            subtreeCnt[v] = cnt;\n            return cnt;\n        };\n        dfs(0);\n\n        ll edgeCost = 0;\n        for (int v = 1; v < N; v++) {\n            if (subtreeCnt[v] > 0) edgeCost += weightToParent[v];\n        }\n\n        ll totalCost = Pcost + edgeCost;\n\n        // Helpers for delta edge cost computation\n        vector<int> changeArr(N, 0), visStamp(N, 0);\n        int stamp = 1;\n\n        auto calcDeltaEdge = [&](int from, int to, bool fromInactive, bool toActive) -> ll {\n            if (!fromInactive && !toActive) return 0LL;\n            stamp++;\n            vector<int> touched;\n            touched.reserve(2 * N);\n\n            auto touch = [&](int v, int delta) {\n                if (visStamp[v] != stamp) {\n                    visStamp[v] = stamp;\n                    changeArr[v] = 0;\n                    touched.push_back(v);\n                }\n                changeArr[v] += delta;\n            };\n\n            if (fromInactive) {\n                for (int v = from; v != 0; v = parent[v]) touch(v, -1);\n            }\n            if (toActive) {\n                for (int v = to; v != 0; v = parent[v]) touch(v, +1);\n            }\n\n            ll dE = 0;\n            for (int v : touched) {\n                int before = subtreeCnt[v];\n                int after = before + changeArr[v];\n                bool b1 = before > 0;\n                bool b2 = after > 0;\n                if (b1 != b2) {\n                    dE += (b2 ? +weightToParent[v] : -weightToParent[v]);\n                }\n            }\n            return dE;\n        };\n\n        auto evalDelta = [&](int k, int to) -> ll {\n            int from = assign[k];\n            if (to == from) return 0LL;\n            int rFrom = (int)r[from][k];\n            int rTo = (int)r[to][k];\n            // candidates guarantee rTo<=5000\n            int oldPFrom = P[from], oldPTo = P[to];\n            bool fromInactive = (sz[from] == 1); // after removing k, station becomes empty\n            bool toActive = (sz[to] == 0);       // after adding k, station becomes non-empty\n\n            ll dE = calcDeltaEdge(from, to, fromInactive, toActive);\n\n            // simulate fenwick for deltaP\n            fenw[from].add(rFrom + 1, -1);\n            sz[from]--;\n            fenw[to].add(rTo + 1, +1);\n            sz[to]++;\n\n            int newPFrom = (sz[from] == 0 ? 0 : fenw[from].getMax(sz[from]));\n            int newPTo   = (sz[to] == 0 ? 0 : fenw[to].getMax(sz[to]));\n\n            ll dP = 1LL*newPFrom*newPFrom + 1LL*newPTo*newPTo\n                    - 1LL*oldPFrom*oldPFrom - 1LL*oldPTo*oldPTo;\n\n            // rollback\n            fenw[to].add(rTo + 1, -1);\n            sz[to]--;\n            fenw[from].add(rFrom + 1, +1);\n            sz[from]++;\n\n            return dP + dE;\n        };\n\n        // Local search\n        vector<int> order(K);\n        iota(order.begin(), order.end(), 0);\n        mt19937_64 rng(1234567); // deterministic\n\n        auto commitMove = [&](int k, int to, ll /*delta*/) {\n            int from = assign[k];\n            int rFrom = (int)r[from][k];\n            int rTo = (int)r[to][k];\n\n            int oldSzFrom = sz[from], oldSzTo = sz[to];\n            bool fromInactive = (oldSzFrom == 1);\n            bool toActive = (oldSzTo == 0);\n\n            int oldPFrom = P[from], oldPTo = P[to];\n\n            // apply move\n            fenw[from].add(rFrom + 1, -1);\n            sz[from]--;\n            fenw[to].add(rTo + 1, +1);\n            sz[to]++;\n\n            int newPFrom = (sz[from] == 0 ? 0 : fenw[from].getMax(sz[from]));\n            int newPTo   = (sz[to] == 0 ? 0 : fenw[to].getMax(sz[to]));\n            P[from] = newPFrom;\n            P[to] = newPTo;\n\n            Pcost += 1LL*newPFrom*newPFrom + 1LL*newPTo*newPTo\n                     - 1LL*oldPFrom*oldPFrom - 1LL*oldPTo*oldPTo;\n\n            assign[k] = to;\n\n            // update subtreeCnt/edgeCost only when active status toggles\n            if (fromInactive) {\n                for (int v = from; v != 0; v = parent[v]) {\n                    subtreeCnt[v]--;\n                    if (subtreeCnt[v] == 0) edgeCost -= weightToParent[v];\n                }\n            }\n            if (toActive) {\n                for (int v = to; v != 0; v = parent[v]) {\n                    if (subtreeCnt[v] == 0) edgeCost += weightToParent[v];\n                    subtreeCnt[v]++;\n                }\n            }\n\n            totalCost = Pcost + edgeCost;\n        };\n\n        // time guard\n        auto start = chrono::steady_clock::now();\n        auto timeUp = [&]() {\n            auto now = chrono::steady_clock::now();\n            return chrono::duration_cast<chrono::milliseconds>(now - start).count() > 450; // per trial\n        };\n\n        // 1-2 passes\n        for (int pass = 0; pass < 2; pass++) {\n            shuffle(order.begin(), order.end(), rng);\n            bool improved = false;\n            for (int k : order) {\n                if (timeUp()) break;\n                int from = assign[k];\n\n                ll bestDelta = 0;\n                int bestTo = -1;\n\n                for (int to : cand[k]) {\n                    if (to == from) continue;\n                    ll d = evalDelta(k, to);\n                    if (d < bestDelta) {\n                        bestDelta = d;\n                        bestTo = to;\n                    }\n                }\n                if (bestTo != -1 && bestDelta < 0) {\n                    commitMove(k, bestTo, bestDelta);\n                    improved = true;\n                }\n            }\n            if (!improved) break;\n            if (timeUp()) break;\n        }\n\n        vector<int> activeEdges(M, 0);\n        for (int v = 1; v < N; v++) {\n            if (subtreeCnt[v] > 0) activeEdges[parentEdgeId[v]] = 1;\n        }\n        return {totalCost, P, activeEdges};\n    };\n\n    // Prepare two initial assignments (deterministic + slight random)\n    vector<int> assign0(K), assign1(K);\n    mt19937_64 rng(987654321);\n\n    for (int k = 0; k < K; k++) {\n        // deterministic: smallest required radius (first in sorted candidates)\n        int best = cand[k][0];\n        assign0[k] = best;\n\n        // randomized among top T candidates\n        int T = min(3, (int)cand[k].size());\n        int idx = uniform_int_distribution<int>(0, T - 1)(rng);\n        assign1[k] = cand[k][idx];\n    }\n\n    auto [cost0, P0, B0] = solveTrial(assign0);\n    auto [cost1, P1, B1] = solveTrial(assign1);\n\n    ll bestCost = min(cost0, cost1);\n    vector<int> bestP = (cost0 <= cost1 ? P0 : P1);\n    vector<int> bestB = (cost0 <= cost1 ? B0 : B1);\n\n    // Output\n    for (int i = 0; i < N; i++) {\n        if (i) cout << ' ';\n        cout << bestP[i];\n    }\n    cout << '\\n';\n    for (int j = 0; j < M; j++) {\n        if (j) cout << ' ';\n        cout << bestB[j];\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 LIM = 10000;\n\nstruct SwapOp {\n    short x1, y1, x2, y2;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // Precompute cell id <-> (x,y)\n    auto id = [](int x, int y) -> int {\n        return x * (x + 1) / 2 + y;\n    };\n    vector<int> cx(V), cy(V);\n    for (int x = 0; x < N; x++) {\n        for (int y = 0; y <= x; y++) {\n            int idx = id(x, y);\n            cx[idx] = x;\n            cy[idx] = y;\n        }\n    }\n\n    // Read initial pyramid\n    vector<int> at(V);       // token value at cell\n    vector<int> pos(V);      // cell id where token value sits\n    for (int x = 0; x < N; x++) {\n        for (int y = 0; y <= x; y++) {\n            int b;\n            cin >> b;\n            int idx = id(x, y);\n            at[idx] = b;\n            pos[b] = idx;\n        }\n    }\n\n    // key[v] = which tier-block the value v belongs to in sorted order by value\n    // tier t block has size (t+1), cumulative prefix P(t) = 1+2+...+(t+1) = (t+1)(t+2)/2\n    vector<int> key(V, 0);\n    vector<int> pref(N, 0);\n    for (int t = 0; t < N; t++) {\n        pref[t] = (t + 1) * (t + 2) / 2; // 1..465\n    }\n    for (int v = 0; v < V; v++) {\n        int t = 0;\n        while (t < N && v >= pref[t]) t++;\n        key[v] = t; // 0..29\n    }\n\n    auto keyEdgeViolations = [&]() -> int {\n        int cnt = 0;\n        for (int x = 0; x <= N - 2; x++) {\n            for (int y = 0; y <= x; y++) {\n                int u = id(x, y);\n                int c1 = id(x + 1, y);\n                int c2 = id(x + 1, y + 1);\n                if (key[at[u]] > key[at[c1]]) cnt++;\n                if (key[at[u]] > key[at[c2]]) cnt++;\n            }\n        }\n        return cnt;\n    };\n\n    auto computeE = [&]() -> int {\n        int E = 0;\n        for (int x = 0; x <= N - 2; x++) {\n            for (int y = 0; y <= x; y++) {\n                int u = id(x, y);\n                int c1 = id(x + 1, y);\n                int c2 = id(x + 1, y + 1);\n                if (at[u] > at[c1]) E++;\n                if (at[u] > at[c2]) E++;\n            }\n        }\n        return E;\n    };\n\n    vector<SwapOp> ops;\n    ops.reserve(LIM);\n\n    int K = 0;\n\n    auto doSwap = [&](int a, int b) {\n        if (K >= LIM) return false;\n        if (a == b) return true;\n        int va = at[a], vb = at[b];\n        // record coordinates of the cells being swapped\n        ops.push_back(SwapOp{(short)cx[a], (short)cy[a], (short)cx[b], (short)cy[b]});\n        K++;\n        // apply swap\n        swap(at[a], at[b]);\n        pos[va] = b;\n        pos[vb] = a;\n        return true;\n    };\n\n    auto sweepDownKey = [&](int iter) {\n        // x increasing: parent at (x, y), children at (x+1, y) and (x+1, y+1)\n        for (int x = 0; x <= N - 2; x++) {\n            if ((iter & 1) == 0) {\n                for (int y = 0; y <= x; y++) {\n                    int u = id(x, y);\n                    int v1 = id(x + 1, y);\n                    int v2 = id(x + 1, y + 1);\n                    if ((iter & 2) == 0) {\n                        if (key[at[u]] > key[at[v1]]) { if (!doSwap(u, v1)) return; }\n                        if (key[at[u]] > key[at[v2]]) { if (!doSwap(u, v2)) return; }\n                    } else {\n                        if (key[at[u]] > key[at[v2]]) { if (!doSwap(u, v2)) return; }\n                        if (key[at[u]] > key[at[v1]]) { if (!doSwap(u, v1)) return; }\n                    }\n                }\n            } else {\n                for (int y = x; y >= 0; y--) {\n                    int u = id(x, y);\n                    int v1 = id(x + 1, y);\n                    int v2 = id(x + 1, y + 1);\n                    if ((iter & 2) == 0) {\n                        if (key[at[u]] > key[at[v1]]) { if (!doSwap(u, v1)) return; }\n                        if (key[at[u]] > key[at[v2]]) { if (!doSwap(u, v2)) return; }\n                    } else {\n                        if (key[at[u]] > key[at[v2]]) { if (!doSwap(u, v2)) return; }\n                        if (key[at[u]] > key[at[v1]]) { if (!doSwap(u, v1)) return; }\n                    }\n                }\n            }\n            if (K >= LIM) return;\n        }\n    };\n\n    auto sweepUpKey = [&](int iter) {\n        // x decreasing: for each node (x,y) look at its two parents\n        for (int x = N - 1; x >= 1; x--) {\n            if ((iter & 1) == 0) {\n                for (int y = 0; y <= x; y++) {\n                    int v = id(x, y);\n                    int p1 = (y - 1 >= 0) ? id(x - 1, y - 1) : -1; // left parent\n                    int p2 = (y <= x - 1) ? id(x - 1, y) : -1;   // right parent\n                    if ((iter & 2) == 0) {\n                        if (p1 != -1 && key[at[p1]] > key[at[v]]) { if (!doSwap(p1, v)) return; }\n                        if (p2 != -1 && key[at[p2]] > key[at[v]]) { if (!doSwap(p2, v)) return; }\n                    } else {\n                        if (p2 != -1 && key[at[p2]] > key[at[v]]) { if (!doSwap(p2, v)) return; }\n                        if (p1 != -1 && key[at[p1]] > key[at[v]]) { if (!doSwap(p1, v)) return; }\n                    }\n                }\n            } else {\n                for (int y = x; y >= 0; y--) {\n                    int v = id(x, y);\n                    int p1 = (y - 1 >= 0) ? id(x - 1, y - 1) : -1;\n                    int p2 = (y <= x - 1) ? id(x - 1, y) : -1;\n                    if ((iter & 2) == 0) {\n                        if (p1 != -1 && key[at[p1]] > key[at[v]]) { if (!doSwap(p1, v)) return; }\n                        if (p2 != -1 && key[at[p2]] > key[at[v]]) { if (!doSwap(p2, v)) return; }\n                    } else {\n                        if (p2 != -1 && key[at[p2]] > key[at[v]]) { if (!doSwap(p2, v)) return; }\n                        if (p1 != -1 && key[at[p1]] > key[at[v]]) { if (!doSwap(p1, v)) return; }\n                    }\n                }\n            }\n            if (K >= LIM) return;\n        }\n    };\n\n    auto sweepDownEqualVal = [&](int iter) {\n        // swap only if keys are equal and actual values violate\n        for (int x = 0; x <= N - 2; x++) {\n            if ((iter & 1) == 0) {\n                for (int y = 0; y <= x; y++) {\n                    int u = id(x, y);\n                    int v1 = id(x + 1, y);\n                    int v2 = id(x + 1, y + 1);\n                    auto tryChild = [&](int c) {\n                        if (key[at[u]] == key[at[c]] && at[u] > at[c]) {\n                            doSwap(u, c);\n                        }\n                    };\n                    if ((iter & 2) == 0) {\n                        tryChild(v1);\n                        tryChild(v2);\n                    } else {\n                        tryChild(v2);\n                        tryChild(v1);\n                    }\n                    if (K >= LIM) return;\n                }\n            } else {\n                for (int y = x; y >= 0; y--) {\n                    int u = id(x, y);\n                    int v1 = id(x + 1, y);\n                    int v2 = id(x + 1, y + 1);\n                    auto tryChild = [&](int c) {\n                        if (key[at[u]] == key[at[c]] && at[u] > at[c]) {\n                            doSwap(u, c);\n                        }\n                    };\n                    if ((iter & 2) == 0) {\n                        tryChild(v1);\n                        tryChild(v2);\n                    } else {\n                        tryChild(v2);\n                        tryChild(v1);\n                    }\n                    if (K >= LIM) return;\n                }\n            }\n        }\n    };\n\n    auto sweepUpEqualVal = [&](int iter) {\n        for (int x = N - 1; x >= 1; x--) {\n            if ((iter & 1) == 0) {\n                for (int y = 0; y <= x; y++) {\n                    int v = id(x, y);\n                    int p1 = (y - 1 >= 0) ? id(x - 1, y - 1) : -1;\n                    int p2 = (y <= x - 1) ? id(x - 1, y) : -1;\n\n                    auto tryParent = [&](int p) {\n                        if (p != -1 && key[at[p]] == key[at[v]] && at[p] > at[v]) {\n                            doSwap(p, v);\n                        }\n                    };\n                    if ((iter & 2) == 0) {\n                        tryParent(p1);\n                        tryParent(p2);\n                    } else {\n                        tryParent(p2);\n                        tryParent(p1);\n                    }\n                    if (K >= LIM) return;\n                }\n            } else {\n                for (int y = x; y >= 0; y--) {\n                    int v = id(x, y);\n                    int p1 = (y - 1 >= 0) ? id(x - 1, y - 1) : -1;\n                    int p2 = (y <= x - 1) ? id(x - 1, y) : -1;\n\n                    auto tryParent = [&](int p) {\n                        if (p != -1 && key[at[p]] == key[at[v]] && at[p] > at[v]) {\n                            doSwap(p, v);\n                        }\n                    };\n                    if ((iter & 2) == 0) {\n                        tryParent(p1);\n                        tryParent(p2);\n                    } else {\n                        tryParent(p2);\n                        tryParent(p1);\n                    }\n                    if (K >= LIM) return;\n                }\n            }\n        }\n    };\n\n    // Stage 1: fix key-order inversions along edges\n    int maxIter1 = 60;\n    for (int iter = 0; iter < maxIter1; iter++) {\n        if (K >= LIM) break;\n        sweepDownKey(iter);\n        if (K >= LIM) break;\n        sweepUpKey(iter);\n\n        if (keyEdgeViolations() == 0) break;\n    }\n\n    // If already perfect, stop\n    if (computeE() == 0) {\n        cout << K << \"\\n\";\n        for (auto &op : ops) {\n            cout << op.x1 << \" \" << op.y1 << \" \" << op.x2 << \" \" << op.y2 << \"\\n\";\n        }\n        return 0;\n    }\n\n    // Stage 2: only equal-key edges can still violate now, so fix them by value compare-swap\n    int maxIter2 = 120;\n    for (int iter = 0; iter < maxIter2; iter++) {\n        if (K >= LIM) break;\n        sweepDownEqualVal(iter);\n        if (K >= LIM) break;\n        sweepUpEqualVal(iter);\n\n        if (computeE() == 0) break;\n    }\n\n    cout << K << \"\\n\";\n    for (auto &op : ops) {\n        cout << op.x1 << \" \" << op.y1 << \" \" << op.x2 << \" \" << op.y2 << \"\\n\";\n    }\n    return 0;\n}","toyota2023summer-final":"#include <bits/stdc++.h>\nusing namespace std;\n\n// We assume the judge is interactive-like: flush after each output during insertion.\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int D, N;\n    cin >> D >> N;\n    vector<vector<bool>> obs(D, vector<bool>(D, false));\n    for (int k = 0; k < N; k++) {\n        int ri, rj;\n        cin >> ri >> rj;\n        obs[ri][rj] = true;\n    }\n\n    const int ei = 0;\n    const int ej = (D - 1) / 2; // entrance\n    if (obs[ei][ej]) {\n        // Should not happen per statement.\n        return 0;\n    }\n\n    // Map each non-obstacle cell to a node id in [0, V)\n    vector<vector<int>> id(D, vector<int>(D, -1));\n    vector<pair<int,int>> coord;\n    coord.reserve(D*D);\n\n    int V = 0;\n    for (int i = 0; i < D; i++) for (int j = 0; j < D; j++) {\n        if (obs[i][j]) continue;\n        id[i][j] = V++;\n        coord.push_back({i, j});\n    }\n\n    int entranceVid = id[ei][ej];\n\n    // BFS tree\n    vector<int> parent(V, -1), depth(V, -1), bfsOrder(V, -1);\n    vector<vector<int>> children(V);\n    queue<int> q;\n    vector<char> vis(V, false);\n    vis[entranceVid] = true;\n    depth[entranceVid] = 0;\n    parent[entranceVid] = -1;\n    bfsOrder[entranceVid] = 0;\n    q.push(entranceVid);\n    int ord = 1;\n\n    auto push_if = [&](int ni, int nj, int pv) {\n        if (ni < 0 || ni >= D || nj < 0 || nj >= D) return;\n        int nid = id[ni][nj];\n        if (nid < 0) return; // obstacle\n        if (vis[nid]) return;\n        vis[nid] = true;\n        parent[nid] = pv;\n        depth[nid] = depth[pv] + 1;\n        bfsOrder[nid] = ord++;\n        q.push(nid);\n    };\n\n    while (!q.empty()) {\n        int v = q.front(); q.pop();\n        auto [x, y] = coord[v];\n        const int dx[4] = {-1, 1, 0, 0};\n        const int dy[4] = {0, 0, -1, 1};\n        for (int dir = 0; dir < 4; dir++) {\n            int nx = x + dx[dir];\n            int ny = y + dy[dir];\n            push_if(nx, ny, v);\n        }\n    }\n\n    // Build children lists from parent array\n    for (int v = 0; v < V; v++) {\n        if (v == entranceVid) continue;\n        int p = parent[v];\n        if (p >= 0) children[p].push_back(v);\n    }\n\n    // Container nodes are all nodes except entrance\n    vector<int> containers;\n    containers.reserve(V-1);\n    for (int v = 0; v < V; v++) {\n        if (v == entranceVid) continue;\n        containers.push_back(v);\n    }\n    int M = (int)containers.size(); // number of containers\n    // Problem guarantees M = D^2-1-N and all reachable from entrance in obstacle-only grid.\n\n    // Static depth order (proxy positions) for insertion heuristic\n    vector<int> posDepth(V, -1);\n    vector<pair<int,int>> depthList; // (depth, bfsOrder)\n    depthList.reserve(M);\n    for (int v : containers) {\n        depthList.push_back({depth[v], bfsOrder[v]});\n    }\n    sort(depthList.begin(), depthList.end()); // depth asc, then bfsOrder asc\n    // depthList currently doesn't keep node ids. Rebuild by sorting nodes directly.\n    vector<int> sortedByDepth = containers;\n    sort(sortedByDepth.begin(), sortedByDepth.end(), [&](int a, int b){\n        if (depth[a] != depth[b]) return depth[a] < depth[b];\n        return bfsOrder[a] < bfsOrder[b];\n    });\n    for (int i = 0; i < M; i++) posDepth[sortedByDepth[i]] = i;\n\n    // Insertion: reverse-topological (postorder) w.r.t. the BFS tree\n    vector<int> remChildCnt(V, 0);\n    for (int v : containers) remChildCnt[v] = (int)children[v].size();\n\n    vector<char> inserted(V, false);\n    vector<int> label(V, -1);\n\n    // Ready nodes: children already inserted => remChildCnt[v]==0\n    // Use set for easy iteration/removal (M <= 80 so fine).\n    set<int> ready;\n    for (int v : containers) if (remChildCnt[v] == 0) ready.insert(v);\n\n    // Assigned pairs for inversion proxy cost: (posDepth, label)\n    vector<pair<int,int>> assignedPairs;\n    assignedPairs.reserve(M);\n\n    for (int d = 0; d < M; d++) {\n        int t_d;\n        cin >> t_d;\n\n        int bestV = -1;\n        int bestCost = INT_MAX;\n\n        // Tie-breaking heuristic depends on label size\n        bool smallLabel = (t_d < M / 2);\n\n        for (int v : ready) {\n            int p = posDepth[v];\n            int cost = 0;\n            for (auto [p2, lab2] : assignedPairs) {\n                if (p2 < p) {\n                    if (lab2 > t_d) cost++;\n                } else if (p2 > p) {\n                    if (t_d > lab2) cost++;\n                }\n            }\n\n            if (cost < bestCost) {\n                bestCost = cost;\n                bestV = v;\n            } else if (cost == bestCost) {\n                int bp = posDepth[bestV];\n                if (smallLabel) {\n                    if (p < bp) bestV = v;\n                } else {\n                    if (p > bp) bestV = v;\n                }\n            }\n        }\n\n        // Output placement\n        auto [pi, pj] = coord[bestV];\n        cout << pi << ' ' << pj << \"\\n\" << flush;\n\n        // Update state\n        inserted[bestV] = true;\n        label[bestV] = t_d;\n        assignedPairs.push_back({posDepth[bestV], t_d});\n\n        ready.erase(bestV);\n\n        int p = parent[bestV];\n        if (p != entranceVid && p >= 0) {\n            remChildCnt[p]--;\n            if (remChildCnt[p] == 0) ready.insert(p);\n        }\n    }\n\n    // Transport: feasible removal order by min-heap of labels among currently removable nodes.\n    // Nodes removable iff parent already removed (parent-before-child on BFS tree).\n    vector<char> removed(V, false);\n\n    struct NodeLab {\n        int lab;\n        int v;\n        bool operator<(NodeLab const& other) const {\n            // for min-heap using priority_queue (largest on top), invert:\n            if (lab != other.lab) return lab > other.lab;\n            return v > other.v;\n        }\n    };\n\n    priority_queue<NodeLab> pq;\n\n    for (int ch : children[entranceVid]) pq.push({label[ch], ch});\n\n    vector<int> transportOrder;\n    transportOrder.reserve(M);\n\n    while ((int)transportOrder.size() < M) {\n        if (pq.empty()) break; // should not happen\n        auto cur = pq.top(); pq.pop();\n        int v = cur.v;\n        if (removed[v]) continue;\n\n        removed[v] = true;\n        transportOrder.push_back(v);\n\n        for (int ch : children[v]) {\n            if (!removed[ch]) pq.push({label[ch], ch});\n        }\n    }\n\n    // Output transport order coordinates\n    for (int k = 0; k < M; k++) {\n        auto [qi, qj] = coord[transportOrder[k]];\n        cout << qi << ' ' << qj << \"\\n\" << flush;\n    }\n\n    return 0;\n}","ahc024":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const int DIRS[4][2] = {{1,0},{-1,0},{0,1},{0,-1}};\n\nstruct Pos { int i, j; };\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int n, m;\n    cin >> n >> m;\n    vector<vector<int>> a(n, vector<int>(n));\n    for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) cin >> a[i][j];\n\n    auto idx = [&](int i, int j){ return i*n + j; };\n    auto unidx = [&](int id){ return pair<int,int>(id/n, id%n); };\n\n    // Precompute adjacency in original: AdjOrig[c][d] for 0<=c<d<=m.\n    vector<vector<unsigned char>> adjOrig(m+1, vector<unsigned char>(m+1, 0));\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            int c1 = a[i][j];\n            for (auto &dr: DIRS) {\n                int ni = i + dr[0], nj = j + dr[1];\n                int c2;\n                if (ni < 0 || ni >= n || nj < 0 || nj >= n) c2 = 0;\n                else c2 = a[ni][nj];\n                if (c1 == c2) continue;\n                int x = min(c1, c2), y = max(c1, c2);\n                adjOrig[x][y] = 1;\n            }\n        }\n    }\n\n    // allowed: colors that touch outside in the input => appear on boundary.\n    vector<unsigned char> allowed(m+1, 0);\n    for (int j = 0; j < n; j++) {\n        allowed[a[0][j]] = 1;\n        allowed[a[n-1][j]] = 1;\n    }\n    for (int i = 0; i < n; i++) {\n        allowed[a[i][0]] = 1;\n        allowed[a[i][n-1]] = 1;\n    }\n\n    // Forbidden colors (not touching outside in original).\n    vector<unsigned char> forbidden(m+1, 0);\n    for (int c = 1; c <= m; c++) forbidden[c] = !allowed[c];\n\n    // posByColor[c]: list of all cells with original color c\n    vector<vector<int>> posByColor(m+1);\n    for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) posByColor[a[i][j]].push_back(idx(i,j));\n\n    // Boundary cells for each allowed color (to choose randomized base).\n    vector<vector<int>> boundaryCells(m+1);\n    for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) {\n        if (i == 0 || i == n-1 || j == 0 || j == n-1) {\n            int c = a[i][j];\n            if (allowed[c]) boundaryCells[c].push_back(idx(i,j));\n        }\n    }\n\n    // Precompute all adjacent edges between allowed colors in the original:\n    // repEdges[x][y] (x<y) stores pairs (cell of x, cell of y) where those colors are adjacent.\n    vector<vector<vector<pair<int,int>>>> repEdges(m+1, vector<vector<pair<int,int>>>(m+1));\n    for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) {\n        int u = a[i][j];\n        if (j+1 < n) {\n            int v = a[i][j+1];\n            if (u != v && allowed[u] && allowed[v]) {\n                int x = min(u,v), y = max(u,v);\n                int id_x = (u==x ? idx(i,j) : idx(i,j+1));\n                int id_y = (u==x ? idx(i,j+1) : idx(i,j));\n                repEdges[x][y].push_back({id_x, id_y});\n            }\n        }\n        if (i+1 < n) {\n            int v = a[i+1][j];\n            if (u != v && allowed[u] && allowed[v]) {\n                int x = min(u,v), y = max(u,v);\n                int id_x = (u==x ? idx(i,j) : idx(i+1,j));\n                int id_y = (u==x ? idx(i+1,j) : idx(i,j));\n                repEdges[x][y].push_back({id_x, id_y});\n            }\n        }\n    }\n\n    // mustKeep cell: if forbidden color => always keep; else if adjacent to forbidden => keep.\n    vector<unsigned char> mustKeep(n*n, 0);\n    for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) {\n        int c = a[i][j];\n        int id = idx(i,j);\n        if (forbidden[c]) {\n            mustKeep[id] = 1;\n        } else {\n            bool ok = false;\n            for (auto &dr: DIRS) {\n                int ni = i + dr[0], nj = j + dr[1];\n                if (ni < 0 || ni >= n || nj < 0 || nj >= n) continue;\n                int cc = a[ni][nj];\n                if (forbidden[cc]) { ok = true; break; }\n            }\n            mustKeep[id] = ok ? 1 : 0;\n        }\n    }\n\n    auto checkAll = [&](const vector<vector<int>> &b)->bool{\n        // 1) Connectivity for colors 1..m\n        vector<unsigned char> vis(n*n, 0);\n        for (int c = 1; c <= m; c++) {\n            int start = -1;\n            int tot = 0;\n            for (int id: posByColor[c]) {\n                auto [i,j] = unidx(id);\n                if (b[i][j] == c) { tot++; if (start==-1) start=id; }\n            }\n            if (tot == 0) return false;\n            fill(vis.begin(), vis.end(), 0);\n            queue<int> q;\n            vis[start] = 1;\n            q.push(start);\n            int cnt = 1;\n            while(!q.empty()){\n                int cur = q.front(); q.pop();\n                auto [i,j] = unidx(cur);\n                for (auto &dr: DIRS) {\n                    int ni = i + dr[0], nj = j + dr[1];\n                    if (ni<0||ni>=n||nj<0||nj>=n) continue;\n                    if (b[ni][nj] != c) continue;\n                    int nid = idx(ni,nj);\n                    if (!vis[nid]) { vis[nid]=1; q.push(nid); cnt++; }\n                }\n            }\n            if (cnt != tot) return false;\n        }\n\n        // 2) Connectivity for color 0 (including outside squares)\n        int N = n+2;\n        vector<unsigned char> vis0(N*N, 0);\n        auto idExt = [&](int x,int y){ return x*N+y; };\n        queue<pair<int,int>> q;\n        vis0[idExt(0,0)] = 1;\n        q.push({0,0});\n        while(!q.empty()){\n            auto [x,y] = q.front(); q.pop();\n            for (auto &dr: DIRS) {\n                int nx = x + dr[0], ny = y + dr[1];\n                if (nx<0||nx>=N||ny<0||ny>=N) continue;\n                bool pass;\n                if (nx==0||nx==N-1||ny==0||ny==N-1) pass = true; // outside is always 0\n                else {\n                    pass = (b[nx-1][ny-1] == 0);\n                }\n                if (!pass) continue;\n                int nid = idExt(nx,ny);\n                if (!vis0[nid]) { vis0[nid]=1; q.push({nx,ny}); }\n            }\n        }\n        for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) {\n            if (b[i][j] == 0) {\n                if (!vis0[idExt(i+1,j+1)]) return false;\n            }\n        }\n\n        // 3) Adjacency matrix equality\n        vector<vector<unsigned char>> adjOut(m+1, vector<unsigned char>(m+1, 0));\n        for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) {\n            int c1 = b[i][j];\n            for (auto &dr: DIRS) {\n                int ni = i + dr[0], nj = j + dr[1];\n                int c2;\n                if (ni < 0 || ni >= n || nj < 0 || nj >= n) c2 = 0;\n                else c2 = b[ni][nj];\n                if (c1 == c2) continue;\n                int x = min(c1, c2), y = max(c1, c2);\n                adjOut[x][y] = 1;\n            }\n        }\n        for (int x = 0; x <= m; x++) for (int y = x+1; y <= m; y++) {\n            if (adjOut[x][y] != adjOrig[x][y]) return false;\n        }\n        return true;\n    };\n\n    auto connectColor = [&](vector<vector<int>> &b, int c) {\n        // find components of b==c using BFS restricted to b==c\n        vector<unsigned char> seen(n*n, 0);\n        vector<vector<int>> comps;\n        for (int id: posByColor[c]) {\n            auto [i,j] = unidx(id);\n            if (b[i][j] != c) continue;\n            if (seen[id]) continue;\n            vector<int> comp;\n            queue<int> q;\n            seen[id]=1;\n            q.push(id);\n            while(!q.empty()){\n                int cur=q.front(); q.pop();\n                comp.push_back(cur);\n                auto [ci,cj]=unidx(cur);\n                for (auto &dr: DIRS){\n                    int ni=ci+dr[0], nj=cj+dr[1];\n                    if (ni<0||ni>=n||nj<0||nj>=n) continue;\n                    if (b[ni][nj] != c) continue;\n                    int nid=idx(ni,nj);\n                    if (!seen[nid]){ seen[nid]=1; q.push(nid); }\n                }\n            }\n            comps.push_back(std::move(comp));\n        }\n        if (comps.size() <= 1) return;\n\n        // target = first component\n        vector<unsigned char> target(n*n, 0);\n        for (int id: comps[0]) target[id]=1;\n\n        vector<int> dist(n*n), parent(n*n);\n\n        for (size_t k = 1; k < comps.size(); k++) {\n            int startId = comps[k][0];\n\n            fill(dist.begin(), dist.end(), -1);\n            fill(parent.begin(), parent.end(), -1);\n\n            queue<int> q;\n            dist[startId]=0;\n            q.push(startId);\n\n            int reached = -1;\n            while(!q.empty() && reached==-1){\n                int cur=q.front(); q.pop();\n                if (target[cur]) { reached = cur; break; }\n                auto [ci,cj]=unidx(cur);\n                for (auto &dr: DIRS){\n                    int ni=ci+dr[0], nj=cj+dr[1];\n                    if (ni<0||ni>=n||nj<0||nj>=n) continue;\n                    if (a[ni][nj] != c) continue; // passable only within original region of color c\n                    int nid = idx(ni,nj);\n                    if (dist[nid]!=-1) continue;\n                    dist[nid]=dist[cur]+1;\n                    parent[nid]=cur;\n                    q.push(nid);\n                }\n            }\n            if (reached == -1) continue; // should not happen since original region is connected\n\n            // Set all cells on path (reached -> start) to color c\n            int cur = reached;\n            while(cur != startId) {\n                auto [ci,cj]=unidx(cur);\n                b[ci][cj]=c;\n                cur = parent[cur];\n                if (cur==-1) break;\n            }\n            auto [si,sj]=unidx(startId);\n            b[si][sj]=c;\n        }\n    };\n\n    auto buildOne = [&](mt19937_64 &rng)->pair<bool, vector<vector<int>>> {\n        vector<unsigned char> requiredMark(n*n, 0);\n        vector<int> baseCell(m+1, -1);\n\n        // Choose random bases for allowed colors.\n        for (int c = 1; c <= m; c++) {\n            if (!allowed[c]) continue;\n            if (boundaryCells[c].empty()) return {false, {}};\n            int pick = (int)(rng() % boundaryCells[c].size());\n            int baseId = boundaryCells[c][pick];\n            baseCell[c] = baseId;\n            requiredMark[baseId] = 1;\n        }\n\n        // Choose random representative edge endpoints for each allowed-allowed adjacency.\n        for (int x = 1; x <= m; x++) if (allowed[x]) {\n            for (int y = x+1; y <= m; y++) if (allowed[y] && adjOrig[x][y]) {\n                if (repEdges[x][y].empty()) return {false, {}};\n                auto &vec = repEdges[x][y];\n                auto e = vec[(size_t)(rng() % vec.size())];\n                requiredMark[e.first] = 1;  // endpoint cell of x\n                requiredMark[e.second] = 1; // endpoint cell of y\n            }\n        }\n\n        // Initial output b\n        vector<vector<int>> b(n, vector<int>(n, 0));\n        for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) {\n            int c = a[i][j];\n            if (forbidden[c]) b[i][j] = c;\n            else b[i][j] = 0;\n        }\n\n        // For each allowed color, connect required cells within original region and set them.\n        vector<int> parent(n*n), dist(n*n);\n        for (int c = 1; c <= m; c++) {\n            if (!allowed[c]) continue;\n            int base = baseCell[c];\n            // gather required positions\n            vector<int> req;\n            req.reserve(posByColor[c].size());\n            for (int id : posByColor[c]) {\n                if (mustKeep[id] || requiredMark[id]) req.push_back(id);\n            }\n            if (req.empty()) return {false, {}};\n\n            // BFS from base within region a==c to build parent tree\n            fill(dist.begin(), dist.end(), -1);\n            fill(parent.begin(), parent.end(), -1);\n            queue<int> q;\n            dist[base] = 0;\n            q.push(base);\n\n            while(!q.empty()){\n                int cur = q.front(); q.pop();\n                auto [ci,cj]=unidx(cur);\n                for (auto &dr: DIRS){\n                    int ni=ci+dr[0], nj=cj+dr[1];\n                    if (ni<0||ni>=n||nj<0||nj>=n) continue;\n                    if (a[ni][nj] != c) continue;\n                    int nid=idx(ni,nj);\n                    if (dist[nid]!=-1) continue;\n                    dist[nid]=dist[cur]+1;\n                    parent[nid]=cur;\n                    q.push(nid);\n                }\n            }\n\n            // mark union of paths base->req nodes\n            for (int t : req) {\n                if (dist[t]==-1) return {false, {}};\n                int cur = t;\n                while(cur != base) {\n                    auto [ci,cj]=unidx(cur);\n                    b[ci][cj]=c;\n                    cur = parent[cur];\n                    if (cur==-1) return {false, {}};\n                }\n                auto [bi,bj]=unidx(base);\n                b[bi][bj]=c;\n            }\n        }\n\n        // Fix 0 connectivity by restoring enclosed 0 holes\n        // Iteratively: find 0 cells unreachable from outside, restore to original colors,\n        // and connect affected ward colors.\n        for (int iter = 0; iter < 20; iter++) {\n            int N = n+2;\n            auto idExt = [&](int x,int y){ return x*N+y; };\n            vector<unsigned char> vis0(N*N, 0);\n            queue<pair<int,int>> q;\n            vis0[idExt(0,0)] = 1;\n            q.push({0,0});\n\n            while(!q.empty()){\n                auto [x,y]=q.front(); q.pop();\n                for (auto &dr: DIRS){\n                    int nx=x+dr[0], ny=y+dr[1];\n                    if (nx<0||nx>=N||ny<0||ny>=N) continue;\n                    bool pass;\n                    if (nx==0||nx==N-1||ny==0||ny==N-1) pass=true;\n                    else pass = (b[nx-1][ny-1]==0);\n                    if (!pass) continue;\n                    int nid=idExt(nx,ny);\n                    if (!vis0[nid]) { vis0[nid]=1; q.push({nx,ny}); }\n                }\n            }\n\n            vector<unsigned char> changed(m+1, 0);\n            bool anyHole=false;\n            for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) {\n                if (b[i][j] == 0 && !vis0[idExt(i+1,j+1)]) {\n                    anyHole=true;\n                    int c = a[i][j];\n                    b[i][j] = c;\n                    changed[c] = 1;\n                }\n            }\n            if (!anyHole) break;\n            for (int c = 1; c <= m; c++) if (changed[c]) connectColor(b, c);\n        }\n\n        // Final legality check\n        if (!checkAll(b)) return {false, {}};\n        return {true, b};\n    };\n\n    // Run multiple randomized trials and keep the best legal one (max zeros).\n    mt19937_64 rng((uint64_t)chrono::high_resolution_clock::now().time_since_epoch().count());\n\n    vector<vector<int>> best;\n    int bestZero = -1;\n    bool found = false;\n\n    auto startTime = chrono::high_resolution_clock::now();\n    int T = 10; // number of trials (tuneable)\n    for (int t = 0; t < T; t++) {\n        auto now = chrono::high_resolution_clock::now();\n        double elapsed = chrono::duration<double>(now - startTime).count();\n        if (elapsed > 1.75) break;\n\n        auto [ok, b] = buildOne(rng);\n        if (!ok) continue;\n        int zeroCnt = 0;\n        for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) if (b[i][j]==0) zeroCnt++;\n        if (!found || zeroCnt > bestZero) {\n            found = true;\n            bestZero = zeroCnt;\n            best = std::move(b);\n        }\n    }\n\n    if (!found) {\n        // Fallback: output original (always legal)\n        best = a;\n    }\n\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            if (j) cout << ' ';\n            cout << best[i][j];\n        }\n        cout << '\\n';\n    }\n    return 0;\n}","ahc025":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int8_t UNK = 2;\n\nstruct Judge {\n    int N, D, Q;\n    int used = 0;\n    vector<vector<int8_t>> cmpMemo; // cmpMemo[i][j] in {-1,0,1,UNK}\n\n    Judge(int n, int d, int q) : N(n), D(d), Q(q) {\n        cmpMemo.assign(N, vector<int8_t>(N, UNK));\n    }\n\n    // Sends one query comparing sums of disjoint non-empty sets L and R.\n    // Returns sign: -1 if sum(L) < sum(R), 0 if =, +1 if sum(L) > sum(R).\n    int doQuery(const vector<int>& L, const vector<int>& R) {\n        if (used >= Q) return 0; // should not happen in well-designed flow\n        // L and R must be non-empty and disjoint by construction.\n        used++;\n        cout << (int)L.size() << ' ' << (int)R.size();\n        for (int x : L) cout << ' ' << x;\n        for (int x : R) cout << ' ' << x;\n        cout << '\\n' << flush;\n\n        string s;\n        cin >> s;\n        char c = s[0];\n        if (c == '<') return -1;\n        if (c == '>') return 1;\n        return 0;\n    }\n\n    int cmpSingleton(int i, int j) {\n        if (i == j) return 0;\n        int8_t &m = cmpMemo[i][j];\n        if (m != UNK) return m;\n        if (used >= Q) return 0;\n        vector<int> L{ i }, R{ j };\n        int s = doQuery(L, R);\n        cmpMemo[i][j] = (int8_t)s;\n        cmpMemo[j][i] = (int8_t)(-s);\n        return s;\n    }\n\n    int cmpSets(const vector<int>& A, const vector<int>& B) {\n        // assumes A,B non-empty, disjoint\n        if (A.empty() || B.empty()) return 0;\n        return doQuery(A, B);\n    }\n\n    int queriesUsed() const { return used; }\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    Judge judge(N, D, Q);\n\n    vector<vector<int>> bins(D);\n    vector<int> d_i(N, 0);\n\n    // ---------- Phase 1: Pivot bucketization ----------\n    // Choose pivot count Kp based on query budget estimate.\n    auto ceil_log2 = [&](int x) -> int {\n        // returns minimal b such that 2^b >= x, for x>=1; b>=0\n        int b = 0;\n        int v = 1;\n        while (v < x) { v <<= 1; b++; }\n        return b;\n    };\n\n    long long budget = (long long)(0.40L * (long long)Q);\n    int maxKp = min(20, N);\n    int bestKp = 1;\n\n    for (int Kp = 1; Kp <= maxKp; Kp++) {\n        // pivot sorting worst-case with insertion: Kp*(Kp-1)/2 comparisons\n        long long sortCost = 1LL * Kp * (Kp - 1) / 2;\n        // binary search comparisons per item for upper_bound: <= ceil_log2(Kp+1)\n        int perItem = ceil_log2(Kp + 1);\n        long long itemCost = 1LL * (N - Kp) * perItem;\n        long long cost = sortCost + itemCost;\n        if (cost <= budget) bestKp = Kp;\n        else break;\n    }\n    int Kp = bestKp;\n\n    // Pick pivots (deterministic RNG)\n    uint64_t seed = 712367821ULL + (uint64_t)N * 1000003ULL + (uint64_t)D * 9176ULL + (uint64_t)Q;\n    std::mt19937_64 rng(seed);\n\n    vector<int> idx(N);\n    iota(idx.begin(), idx.end(), 0);\n    shuffle(idx.begin(), idx.end(), rng);\n    vector<int> pivots(idx.begin(), idx.begin() + Kp);\n\n    // Sort pivots ascending by weight using singleton comparisons\n    // Insertion sort (simple + bounded for small Kp)\n    for (int i = 1; i < Kp; i++) {\n        int j = i;\n        while (j > 0) {\n            if (judge.queriesUsed() >= Q) break;\n            // pivots[j] < pivots[j-1] ?\n            int s = judge.cmpSingleton(pivots[j], pivots[j - 1]);\n            if (s == -1) {\n                swap(pivots[j], pivots[j - 1]);\n                j--;\n            } else break;\n        }\n        if (judge.queriesUsed() >= Q) break;\n    }\n\n    vector<int> pivotPos(N, -1);\n    for (int i = 0; i < Kp; i++) pivotPos[pivots[i]] = i;\n\n    // Exponential distribution quantile mapping.\n    // weights are generated from Exponential(lambda=1e-5), rounded and truncated above cap.\n    const double lambda = 1e-5;\n    double cap = 1e5 * (double)N / (double)D;\n\n    auto estimateFromBucket = [&](int bucket) -> double {\n        // bucket in [0..Kp], mapping to p=(bucket+0.5)/(Kp+1)\n        double p = (bucket + 0.5) / (double)(Kp + 1);\n        // quantile: F^{-1}(p) = -ln(1-p)/lambda\n        double x = -log(1.0 - p) / lambda;\n        if (x < 1.0) x = 1.0;\n        if (x > cap) x = cap;\n        return x;\n    };\n\n    vector<int> bucket(N, Kp / 2);\n    vector<double> w_est(N, 1.0);\n\n    // For pivots themselves, bucket = position\n    for (int p : pivots) {\n        bucket[p] = pivotPos[p];\n        w_est[p] = estimateFromBucket(bucket[p]);\n    }\n\n    // For others, determine bucket by upper_bound among pivots: count pivots strictly < item\n    for (int i = 0; i < N; i++) {\n        if (judge.queriesUsed() >= Q) break;\n        if (pivotPos[i] != -1) continue;\n\n        int lo = 0, hi = Kp; // first pivot >= i\n        while (lo < hi) {\n            if (judge.queriesUsed() >= Q) break;\n            int mid = (lo + hi) / 2;\n            // if w_i > pivot[mid], pivot[mid] < w_i => move right\n            int s = judge.cmpSingleton(i, pivots[mid]);\n            if (s == 1) lo = mid + 1;\n            else hi = mid;\n        }\n        // lo = number of pivots strictly less than i\n        bucket[i] = lo;\n        w_est[i] = estimateFromBucket(bucket[i]);\n    }\n\n    // ---------- Phase 2: Initial partition (LPT-style) ----------\n    vector<int> order(N);\n    iota(order.begin(), order.end(), 0);\n    sort(order.begin(), order.end(), [&](int a, int b) {\n        return w_est[a] > w_est[b];\n    });\n\n    vector<double> binSumEst(D, 0.0);\n    for (int b = 0; b < D; b++) bins[b].clear();\n\n    for (int x : order) {\n        int best = 0;\n        for (int b = 1; b < D; b++) {\n            if (binSumEst[b] < binSumEst[best]) best = b;\n        }\n        bins[best].push_back(x);\n        d_i[x] = best;\n        binSumEst[best] += w_est[x];\n    }\n\n    auto moveItem = [&](int item, int from, int to) {\n        auto &v = bins[from];\n        for (int i = 0; i < (int)v.size(); i++) {\n            if (v[i] == item) {\n                v.erase(v.begin() + i);\n                break;\n            }\n        }\n        bins[to].push_back(item);\n        d_i[item] = to;\n    };\n\n    // ---------- Phase 3: Local balancing with remaining queries ----------\n    int iters = 0;\n    int maxIters = 120; // keep modest\n\n    while (judge.queriesUsed() < Q && iters < maxIters) {\n        // find movable heavy bin (size >= 2)\n        int h = -1;\n        for (int b = 0; b < D; b++) {\n            if ((int)bins[b].size() >= 2) { h = b; break; }\n        }\n        if (h == -1) break;\n\n        // light bin: any non-empty bin\n        int l = -1;\n        for (int b = 0; b < D; b++) {\n            if (!bins[b].empty()) { l = b; break; }\n        }\n        if (l == -1) break;\n\n        // Make h the heaviest among bins with size>=2\n        for (int b = 0; b < D && judge.queriesUsed() < Q; b++) {\n            if (b == h) continue;\n            if ((int)bins[b].size() < 2) continue;\n            int s = judge.cmpSets(bins[h], bins[b]); // h ? b\n            if (s == -1) h = b; // h < b => b heavier\n        }\n        if (judge.queriesUsed() >= Q) break;\n\n        // Make l the lightest among all non-empty bins\n        for (int b = 0; b < D && judge.queriesUsed() < Q; b++) {\n            if (b == l) continue;\n            int s = judge.cmpSets(bins[l], bins[b]); // l ? b\n            if (s == 1) l = b; // l heavier => b lighter\n        }\n        if (judge.queriesUsed() >= Q) break;\n\n        // If h is not heavier than l, stop\n        int sHL = judge.cmpSets(bins[h], bins[l]);\n        if (sHL <= 0) break; // h <= l\n\n        // Candidate move from heavy h to light l\n        vector<int> cand = bins[h];\n        sort(cand.begin(), cand.end(), [&](int a, int b) {\n            return w_est[a] > w_est[b];\n        });\n\n        int bestX = cand.empty() ? -1 : cand[0];\n        bool moved = false;\n\n        for (int x : cand) {\n            if (judge.queriesUsed() >= Q) break;\n\n            // left = h without x (must be non-empty)\n            vector<int> left;\n            left.reserve(bins[h].size() - 1);\n            for (int y : bins[h]) if (y != x) left.push_back(y);\n            if (left.empty()) continue;\n\n            // right = l with x\n            vector<int> right = bins[l];\n            right.push_back(x);\n\n            int s = judge.cmpSets(left, right); // (h-x) ? (l+x)\n            if (s <= 0) { // (h-x) <= (l+x): accept\n                moveItem(x, h, l);\n                moved = true;\n                break;\n            }\n        }\n\n        if (!moved) {\n            // No crossing found (or budget exhausted): move the largest estimated item\n            if (bestX != -1 && (int)bins[h].size() >= 2) {\n                moveItem(bestX, h, l);\n            }\n        }\n\n        iters++;\n    }\n\n    // ---------- Dummy queries to reach exactly Q ----------\n    while (judge.queriesUsed() < Q) {\n        // compare singleton 0 vs 1 (disjoint, non-empty). N>=30 always, so ok.\n        if (N >= 2) {\n            vector<int> L{0}, R{1};\n            judge.doQuery(L, R);\n        } else {\n            // Should never happen for constraints\n            vector<int> L{0}, R{0}; // invalid but unreachable\n            judge.doQuery(L, R);\n        }\n    }\n\n    // ---------- Output final division ----------\n    for (int i = 0; i < N; i++) {\n        if (i) cout << ' ';\n        cout << d_i[i];\n    }\n    cout << '\\n' << flush;\n\n    return 0;\n}","ahc026":"#include <bits/stdc++.h>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int n, m;\n    cin >> n >> m;\n    vector<vector<int>> st(m);\n    for (int i = 0; i < m; i++) {\n        st[i].resize(n / m);\n        for (int j = 0; j < n / m; j++) cin >> st[i][j];\n    }\n\n    vector<int> posStack(n + 1, -1), posIndex(n + 1, -1);\n\n    auto rebuildPos = [&]() {\n        fill(posStack.begin(), posStack.end(), -1);\n        fill(posIndex.begin(), posIndex.end(), -1);\n        for (int i = 0; i < m; i++) {\n            for (int j = 0; j < (int)st[i].size(); j++) {\n                int x = st[i][j];\n                posStack[x] = i;\n                posIndex[x] = j;\n            }\n        }\n    };\n\n    rebuildPos();\n\n    vector<pair<int,int>> ops; // (v, i) where i=0 for op2\n    ops.reserve(5000);\n\n    const int INF = 1e9;\n\n    for (int v = 1; v <= n; v++) {\n        int s = posStack[v];\n        int idx = posIndex[v];\n        if (s < 0) {\n            // Should not happen\n            cerr << \"Error: box \" << v << \" not found.\\n\";\n            return 0;\n        }\n\n        if (idx == (int)st[s].size() - 1) {\n            // v is on top\n            ops.emplace_back(v, 0);\n            st[s].pop_back();\n        } else {\n            // u is immediately above v\n            int u = st[s][idx + 1];\n\n            // moved chunk is st[s][idx+1 .. end-1]\n            int maxC = 0;\n            for (int t = idx + 1; t < (int)st[s].size(); t++) {\n                maxC = max(maxC, st[s][t]);\n            }\n\n            int bestDest = -1;\n            tuple<int,int,int> bestKey; // (safeFlag, height, -minD)\n\n            for (int d = 0; d < m; d++) {\n                if (d == s) continue;\n                int height = (int)st[d].size();\n                int minD = INF;\n                if (height > 0) {\n                    for (int x : st[d]) minD = min(minD, x);\n                }\n\n                bool safe = (height == 0) ? true : (minD > maxC);\n                int safeFlag = safe ? 0 : 1;\n\n                // -minD: larger minD => smaller (-minD) => preferred when safeFlag & height tie\n                int negMinD = (height == 0 ? -INF : -minD);\n\n                tuple<int,int,int> key = {safeFlag, height, negMinD};\n                if (bestDest == -1 || key < bestKey) {\n                    bestDest = d;\n                    bestKey = key;\n                }\n            }\n\n            // op1(u, bestDest+1)\n            ops.emplace_back(u, bestDest + 1);\n\n            // move suffix starting at idx+1 from st[s] to st[bestDest]\n            vector<int> moved(st[s].begin() + (idx + 1), st[s].end());\n            st[s].erase(st[s].begin() + (idx + 1), st[s].end());\n            st[bestDest].insert(st[bestDest].end(), moved.begin(), moved.end());\n\n            // now v must be on top of st[s]\n            ops.emplace_back(v, 0);\n            st[s].pop_back();\n        }\n\n        rebuildPos();\n    }\n\n    if ((int)ops.size() > 5000) {\n        // Should not happen with this construction\n        cerr << \"Too many operations: \" << ops.size() << \"\\n\";\n        return 0;\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 SplitMix64 {\n    uint64_t x;\n    explicit SplitMix64(uint64_t seed = 0) : x(seed) {}\n    uint64_t next_u64() {\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 next_int(int l, int r) { // inclusive\n        return l + (int)(next_u64() % (uint64_t)(r - l + 1));\n    }\n    double next_double(double l, double r) {\n        // [l, r)\n        uint64_t v = next_u64();\n        long double t = (long double)(v) / (long double)numeric_limits<uint64_t>::max();\n        return (double)((long double)l + t * (long double)(r - l));\n    }\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 V = N * N;\n    vector<int> d(V);\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            int x;\n            cin >> x;\n            d[i * N + j] = x;\n        }\n    }\n\n    auto inside = [&](int i, int j) {\n        return 0 <= i && i < N && 0 <= j && j < N;\n    };\n    auto idx = [&](int i, int j) { return i * N + j; };\n\n    // Build adjacency graph (moves allowed by walls)\n    vector<vector<int>> g(V);\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            int a = idx(i, j);\n            // down\n            if (i + 1 < N && h[i][j] == '0') {\n                int b = idx(i + 1, j);\n                g[a].push_back(b);\n                g[b].push_back(a);\n            }\n            // right\n            if (j + 1 < N && v[i][j] == '0') {\n                int b = idx(i, j + 1);\n                g[a].push_back(b);\n                g[b].push_back(a);\n            }\n        }\n    }\n\n    // BFS distances from root (0,0)\n    const int root = 0;\n    vector<int> dist(V, -1);\n    queue<int> q;\n    dist[root] = 0;\n    q.push(root);\n    while (!q.empty()) {\n        int x = q.front(); q.pop();\n        for (int y : g[x]) {\n            if (dist[y] == -1) {\n                dist[y] = dist[x] + 1;\n                q.push(y);\n            }\n        }\n    }\n\n    // Parent candidates: neighbors with dist-1\n    vector<vector<int>> candParents(V);\n    for (int vv = 0; vv < V; vv++) {\n        if (vv == root) continue;\n        int dv = dist[vv];\n        for (int uu : g[vv]) {\n            if (dist[uu] == dv - 1) candParents[vv].push_back(uu);\n        }\n        // Guaranteed reachable => should be non-empty\n        // (problem statement guarantees reachability from root).\n    }\n\n    // Vertex order by dist descending (useful for subtree DP)\n    vector<int> verts(V);\n    iota(verts.begin(), verts.end(), 0);\n    sort(verts.begin(), verts.end(), [&](int a, int b) {\n        return dist[a] > dist[b];\n    });\n\n    auto getDir = [&](int from, int to) -> char {\n        int fi = from / N, fj = from % N;\n        int ti = to / N, tj = to % N;\n        if (ti == fi + 1 && tj == fj) return 'D';\n        if (ti == fi - 1 && tj == fj) return 'U';\n        if (ti == fi && tj == fj + 1) return 'R';\n        if (ti == fi && tj == fj - 1) return 'L';\n        // Should always be adjacent in the tree\n        return '?';\n    };\n\n    long long sum_d = 0;\n    for (int x : d) sum_d += x;\n\n    int Lfixed = 2 * (V - 1);\n    long long bestNumer = (1LL<<62);\n    string bestRoute;\n\n    SplitMix64 rng((uint64_t)chrono::steady_clock::now().time_since_epoch().count());\n\n    vector<int> parent(V), subMax(V), subSize(V);\n    vector<long long> subSum(V);\n    vector<vector<int>> children(V);\n\n    vector<int> last(V);\n    vector<int> pos_after; pos_after.reserve(Lfixed);\n\n    auto evaluate = [&](const vector<int>& pos) -> long long {\n        // pos size = Lfixed, pos[k] = vertex after (k+1)-th move in one cycle\n        long long numer = 0; // sum S_t for t in [L..2L-1]\n        fill(last.begin(), last.end(), 0);\n\n        long long sum_d_last = 0;\n        int L = Lfixed;\n        int T = 2 * L - 1;\n\n        for (int t = 1; t <= T; t++) {\n            int vv = pos[(t - 1) % L];\n            int old = last[vv];\n            last[vv] = t;\n            sum_d_last += (long long)d[vv] * (t - old);\n            long long S = (long long)t * sum_d - sum_d_last;\n            if (t >= L) numer += S;\n        }\n        return numer;\n    };\n\n    auto buildRouteAndPos = [&](const vector<vector<int>>& ordChildren,\n                                 const vector<int>& par) -> pair<string, vector<int>> {\n        string route;\n        route.reserve(Lfixed);\n        vector<int> pos;\n        pos.reserve(Lfixed);\n\n        vector<pair<int,int>> st;\n        st.reserve(V);\n        st.push_back({root, 0});\n\n        while (!st.empty()) {\n            int u = st.back().first;\n            int &i = st.back().second;\n            if (i == (int)ordChildren[u].size()) {\n                st.pop_back();\n                if (st.empty()) break;\n                int p = par[u];\n                route.push_back(getDir(u, p));\n                pos.push_back(p); // moved to parent\n            } else {\n                int c = ordChildren[u][i++];\n                route.push_back(getDir(u, c));\n                pos.push_back(c); // moved to child\n                st.push_back({c, 0});\n            }\n        }\n        // pos.size() should be Lfixed\n        return {route, pos};\n    };\n\n    // Deterministic initial candidate (greedy parents + one ordering)\n    {\n        double p_greedy = 1.0;\n        for (int i = 0; i < V; i++) children[i].clear();\n        parent[root] = -1;\n\n        // build parent in increasing dist order\n        vector<int> byDist(V);\n        iota(byDist.begin(), byDist.end(), 0);\n        sort(byDist.begin(), byDist.end(), [&](int a, int b) { return dist[a] < dist[b]; });\n\n        for (int vv : byDist) {\n            if (vv == root) continue;\n            auto &cp = candParents[vv];\n            int bestp = cp[0];\n            for (int u : cp) if (d[u] > d[bestp]) bestp = u;\n            int pick = bestp;\n            parent[vv] = pick;\n            children[pick].push_back(vv);\n        }\n\n        // subtree dp\n        for (int vtx : verts) {\n            subMax[vtx] = d[vtx];\n            subSum[vtx] = d[vtx];\n            subSize[vtx] = 1;\n            for (int c : children[vtx]) {\n                subMax[vtx] = max(subMax[vtx], subMax[c]);\n                subSum[vtx] += subSum[c];\n                subSize[vtx] += subSize[c];\n            }\n        }\n\n        // child ordering: ascending by subMax (often helps by delaying high-d subtrees)\n        vector<vector<int>> ordChildren = children;\n        for (int u = 0; u < V; u++) {\n            auto &ch = ordChildren[u];\n            if (ch.size() <= 1) continue;\n            sort(ch.begin(), ch.end(), [&](int a, int b) {\n                return subMax[a] < subMax[b];\n            });\n        }\n\n        auto [route, pos] = buildRouteAndPos(ordChildren, parent);\n        long long numer = evaluate(pos);\n        if (numer < bestNumer) {\n            bestNumer = numer;\n            bestRoute = route;\n        }\n    }\n\n    // Randomized candidates\n    auto startTime = chrono::steady_clock::now();\n    double TIME_LIMIT_SEC = 1.75; // keep margin\n\n    vector<int> byDist(V);\n    iota(byDist.begin(), byDist.end(), 0);\n    sort(byDist.begin(), byDist.end(), [&](int a, int b) { return dist[a] < dist[b]; });\n\n    int iter = 0;\n    while (true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - startTime).count();\n        if (elapsed > TIME_LIMIT_SEC) break;\n        iter++;\n        // parameters\n        double p_greedy = rng.next_double(0.7, 0.99);\n        int orderType = rng.next_int(0, 2); // 0: subMax, 1: subSum, 2: d(child)\n        bool ascending = rng.next_int(0, 1);\n        double noiseRate = rng.next_double(0.0, 0.25);\n\n        // build parent\n        for (int i = 0; i < V; i++) children[i].clear();\n        parent[root] = -1;\n\n        for (int vv : byDist) {\n            if (vv == root) continue;\n            auto &cp = candParents[vv];\n            int pick;\n            if (rng.next_double(0.0, 1.0) < p_greedy) {\n                // greedy by d[parent]\n                pick = cp[0];\n                for (int u : cp) if (d[u] > d[pick]) pick = u;\n            } else {\n                pick = cp[rng.next_int(0, (int)cp.size() - 1)];\n            }\n            parent[vv] = pick;\n            children[pick].push_back(vv);\n        }\n\n        // subtree dp\n        for (int vtx : verts) {\n            subMax[vtx] = d[vtx];\n            subSum[vtx] = d[vtx];\n            subSize[vtx] = 1;\n            for (int c : children[vtx]) {\n                subMax[vtx] = max(subMax[vtx], subMax[c]);\n                subSum[vtx] += subSum[c];\n                subSize[vtx] += subSize[c];\n            }\n        }\n\n        // order children with key + noise\n        vector<vector<int>> ordChildren(V);\n        for (int u = 0; u < V; u++) ordChildren[u] = children[u];\n\n        for (int u = 0; u < V; u++) {\n            auto &ch = ordChildren[u];\n            if (ch.size() <= 1) continue;\n\n            vector<pair<double,int>> tmp;\n            tmp.reserve(ch.size());\n            for (int c : ch) {\n                double key;\n                if (orderType == 0) key = (double)subMax[c];\n                else if (orderType == 1) key = (double)subSum[c];\n                else key = (double)d[c];\n\n                double sign = rng.next_double(-1.0, 1.0);\n                double adj = key + noiseRate * key * sign;\n                tmp.push_back({adj, c});\n            }\n            sort(tmp.begin(), tmp.end(), [&](auto &A, auto &B) {\n                if (A.first != B.first) return ascending ? (A.first < B.first) : (A.first > B.first);\n                return A.second < B.second;\n            });\n            for (int i = 0; i < (int)ch.size(); i++) ch[i] = tmp[i].second;\n        }\n\n        auto [route, pos] = buildRouteAndPos(ordChildren, parent);\n        // length should be fixed\n        // (we don't assert to avoid overhead, but it's always true)\n        long long numer = evaluate(pos);\n        if (numer < bestNumer) {\n            bestNumer = numer;\n            bestRoute = std::move(route);\n        }\n    }\n\n    cout << bestRoute << \"\\n\";\n    return 0;\n}","ahc028":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M;\n    cin >> N >> M;\n    int si, sj;\n    cin >> si >> sj;\n\n    vector<string> grid(N);\n    for (int i = 0; i < N; i++) cin >> grid[i];\n\n    vector<string> t(M);\n    for (int k = 0; k < M; k++) cin >> t[k];\n\n    auto idxOf = [N](int r, int c) { return r * N + c; };\n    auto coordOf = [N](int id) { return pair<int,int>{id / N, id % N}; };\n    int C = N * N;\n\n    // positions for each letter\n    vector<vector<int>> posByLetter(26);\n    for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) {\n        int a = grid[i][j] - 'A';\n        posByLetter[a].push_back(idxOf(i, j));\n    }\n\n    // Precompute dist between cells\n    vector<vector<int>> distCell(C, vector<int>(C, 0));\n    for (int a = 0; a < C; a++) {\n        auto [ar, ac] = coordOf(a);\n        for (int b = a; b < C; b++) {\n            auto [br, bc] = coordOf(b);\n            int d = abs(ar - br) + abs(ac - bc);\n            distCell[a][b] = distCell[b][a] = d;\n        }\n    }\n\n    // Precompute dist from cell -> best distance to any cell of a letter\n    vector<vector<int>> distCellToLetter(C, vector<int>(26, INT_MAX/4));\n    for (int p = 0; p < C; p++) {\n        for (int l = 0; l < 26; l++) {\n            int best = INT_MAX/4;\n            for (int q : posByLetter[l]) best = min(best, distCell[p][q]);\n            distCellToLetter[p][l] = best;\n        }\n    }\n\n    // Precompute min dist between any cells of letter x and y (proxy for ordering)\n    vector<vector<int>> distLetter(26, vector<int>(26, INT_MAX/4));\n    for (int x = 0; x < 26; x++) for (int y = 0; y < 26; y++) {\n        int best = INT_MAX/4;\n        for (int p : posByLetter[x]) {\n            for (int q : posByLetter[y]) best = min(best, distCell[p][q]);\n        }\n        distLetter[x][y] = best;\n    }\n\n    int startCell = idxOf(si, sj);\n\n    // start/end letters for each t\n    vector<int> st(M), en(M);\n    for (int i = 0; i < M; i++) {\n        st[i] = t[i][0] - 'A';\n        en[i] = t[i][4] - 'A';\n    }\n\n    // overlapLen[i][j]: max r (0..4) s.t. suffix of t[i] of length r == prefix of t[j] of length r\n    vector<vector<uint8_t>> overlapLen(M, vector<uint8_t>(M, 0));\n    for (int i = 0; i < M; i++) for (int j = 0; j < M; j++) if (i != j) {\n        uint8_t best = 0;\n        for (int r = 4; r >= 0; r--) {\n            bool ok = true;\n            for (int k = 0; k < r; k++) {\n                if (t[i][5 - r + k] != t[j][k]) { ok = false; break; }\n            }\n            if (ok) { best = (uint8_t)r; break; }\n        }\n        overlapLen[i][j] = best;\n    }\n\n    // maxOverlapFrom[i] for tie-breaking\n    vector<uint8_t> maxOverlapFrom(M, 0);\n    for (int i = 0; i < M; i++) {\n        uint8_t mx = 0;\n        for (int j = 0; j < M; j++) if (i != j) mx = max(mx, overlapLen[i][j]);\n        maxOverlapFrom[i] = mx;\n    }\n\n    // pick candidate starting strings\n    vector<pair<int,int>> startCand; // (distance proxy, idx)\n    for (int i = 0; i < M; i++) {\n        int proxy = distCellToLetter[startCell][st[i]]; // movement to get first letter\n        startCand.push_back({proxy, i});\n    }\n    sort(startCand.begin(), startCand.end());\n    int RESTARTS = min(12, M);\n\n    ll bestCost = (1LL<<60);\n    vector<pair<int,int>> bestOps;\n\n    auto simulate = [&](const vector<int>& order) -> pair<ll, vector<pair<int,int>>> {\n        // build merged letter sequence using overlaps between consecutive strings\n        vector<char> seq;\n        seq.reserve(5 * M);\n        auto appendString = [&](int idx, int fromPos) {\n            for (int p = fromPos; p < 5; p++) seq.push_back(t[idx][p]);\n        };\n\n        appendString(order[0], 0);\n        for (int i = 1; i < M; i++) {\n            int prev = order[i-1], cur = order[i];\n            int r = overlapLen[prev][cur];\n            appendString(cur, r);\n        }\n\n        vector<pair<int,int>> ops;\n        ops.reserve(seq.size());\n\n        int curCell = startCell;\n        ll cost = 0;\n\n        for (int pos = 0; pos < (int)seq.size(); pos++) {\n            int l0 = seq[pos] - 'A';\n            int nextL = (pos + 1 < (int)seq.size()) ? (seq[pos+1] - 'A') : -1;\n\n            const auto &cand = posByLetter[l0];\n            int bestCell = -1;\n            int bestVal = INT_MAX;\n\n            if (nextL == -1) {\n                for (int ccell : cand) {\n                    int v = distCell[curCell][ccell];\n                    if (v < bestVal) { bestVal = v; bestCell = ccell; }\n                }\n            } else {\n                // depth-1 lookahead\n                for (int ccell : cand) {\n                    int v = distCell[curCell][ccell] + distCellToLetter[ccell][nextL];\n                    if (v < bestVal) { bestVal = v; bestCell = ccell; }\n                }\n            }\n\n            auto [r, c] = coordOf(bestCell);\n            ops.push_back({r, c});\n            cost += (ll)distCell[curCell][bestCell] + 1;\n            curCell = bestCell;\n        }\n\n        return {cost, ops};\n    };\n\n    for (int rep = 0; rep < RESTARTS; rep++) {\n        int startIdx = startCand[rep].second;\n\n        vector<char> used(M, 0);\n        vector<int> order;\n        order.reserve(M);\n\n        order.push_back(startIdx);\n        used[startIdx] = 1;\n        int cur = startIdx;\n\n        for (int step = 1; step < M; step++) {\n            int bestJ = -1;\n            int bestR = -1;\n            int bestDist = INT_MAX;\n            int bestMx = -1;\n\n            for (int j = 0; j < M; j++) if (!used[j]) {\n                int r = overlapLen[cur][j];\n                int d = distLetter[en[cur]][st[j]]; // proxy boundary movement\n                int mx = maxOverlapFrom[j];\n                if (r > bestR || (r == bestR && d < bestDist) || (r == bestR && d == bestDist && mx > bestMx)) {\n                    bestR = r;\n                    bestDist = d;\n                    bestMx = mx;\n                    bestJ = j;\n                }\n            }\n            used[bestJ] = 1;\n            order.push_back(bestJ);\n            cur = bestJ;\n        }\n\n        auto [cost, ops] = simulate(order);\n        if ((int)ops.size() > 5000) continue;\n        if (cost < bestCost) {\n            bestCost = cost;\n            bestOps = std::move(ops);\n        }\n    }\n\n    // Output operations: each line \"i j\"\n    for (auto [i, j] : bestOps) {\n        cout << i << ' ' << j << '\\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    if (!(cin >> N >> M >> eps)) return 0;\n\n    // Read shapes (not needed for the safe strategy).\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>> ans;\n    ans.reserve(N * N);\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            cout << \"q 1 \" << i << \" \" << j << \"\\n\";\n            cout.flush();\n\n            long long v;\n            if (!(cin >> v)) return 0;\n            if (v > 0) ans.emplace_back(i, j);\n        }\n    }\n\n    cout << \"a \" << ans.size();\n    for (auto [i, j] : ans) cout << \" \" << i << \" \" << j;\n    cout << \"\\n\";\n    cout.flush();\n\n    int ok;\n    if (!(cin >> ok)) return 0;\n    // ok==1 means success, ok==0 means wrong (should not happen with this strategy).\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    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    // cost[k][w] = 100 * sum_d max(0, a[d][k] - w*W)\n    // where w is width in columns (height is always W), w in [1..W]\n    vector<vector<long long>> cost(N, vector<long long>(W + 1, 0));\n    for (int k = 0; k < N; k++) {\n        for (int w = 1; w <= W; w++) {\n            long long b = 1LL * w * W;\n            long long diffSum = 0;\n            for (int d = 0; d < D; d++) {\n                if (a[d][k] > b) diffSum += (a[d][k] - b);\n            }\n            cost[k][w] = 100LL * diffSum;\n        }\n    }\n\n    const long long INF = (1LL<<62);\n\n    // dp[i][cap] = min cost using first i items (0..i-1), total width cap.\n    // parent pointers to reconstruct widths.\n    vector<vector<long long>> dp(N + 1, vector<long long>(W + 1, INF));\n    vector<vector<int>> parentCap(N + 1, vector<int>(W + 1, -1));\n    vector<vector<int>> parentW(N + 1, vector<int>(W + 1, -1));\n\n    dp[0][0] = 0;\n\n    auto maxCapAfter = [&](int i) -> int {\n        // after placing i items, remaining N-i items need at least 1 width each\n        // => cap <= W - (N-i)\n        return W - (N - i);\n    };\n\n    for (int i = 1; i <= N; i++) {\n        int capLo = i; // since each of i widths >=1\n        int capHi = maxCapAfter(i);\n        if (capHi < capLo) continue;\n\n        for (int cap = capLo; cap <= capHi; cap++) {\n            // choose width w for item (i-1)\n            // previous capPrev = cap - w must be >= i-1\n            // and w >= 1\n            int wLo = 1;\n            int wHi = cap - (i - 1);\n            for (int w = wLo; w <= wHi; w++) {\n                int capPrev = cap - w;\n                if (capPrev < 0) continue;\n                if (dp[i-1][capPrev] == INF) continue;\n                long long cand = dp[i-1][capPrev] + cost[i-1][w];\n                if (cand < dp[i][cap]) {\n                    dp[i][cap] = cand;\n                    parentCap[i][cap] = capPrev;\n                    parentW[i][cap] = w;\n                }\n            }\n        }\n    }\n\n    // choose best cap for i=N\n    long long best = INF;\n    int bestCap = -1;\n    for (int cap = N; cap <= W; cap++) {\n        if (dp[N][cap] < best) {\n            best = dp[N][cap];\n            bestCap = cap;\n        }\n    }\n\n    // Reconstruct widths w_k\n    vector<int> wAns(N, 1);\n    int cap = bestCap;\n    for (int i = N; i >= 1; i--) {\n        int w = parentW[i][cap];\n        int capPrev = parentCap[i][cap];\n        if (w == -1 || capPrev == -1) {\n            // Should not happen; but keep safe fallback.\n            w = 1;\n            capPrev = cap - 1;\n        }\n        wAns[i-1] = w;\n        cap = capPrev;\n    }\n\n    // Build fixed rectangles (same for every day)\n    vector<int> x0(N), x1(N);\n    int curX = 0;\n    for (int k = 0; k < N; k++) {\n        x0[k] = curX;\n        x1[k] = curX + wAns[k];\n        curX = x1[k];\n    }\n    // Ensure within bounds\n    curX = min(curX, W);\n\n    // Output: for all days, same rectangles\n    for (int d = 0; d < D; d++) {\n        for (int k = 0; k < N; k++) {\n            cout << x0[k] << ' ' << 0 << ' ' << x1[k] << ' ' << W << \"\\n\";\n        }\n    }\n    return 0;\n}","ahc032":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing int64 = long long;\n\nstatic constexpr int MOD = 998244353;\n\nstruct OpInfo {\n    array<uint8_t, 9> idx;   // affected cell indices (0..80)\n    array<int, 9> add;       // values to add at those indices (0..MOD-1)\n    uint8_t m, p, q;         // for output\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, K;\n    cin >> N >> M >> K;\n\n    vector<vector<int>> a(N, vector<int>(N));\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) cin >> a[i][j];\n    }\n\n    vector<vector<vector<int>>> s(M, vector<vector<int>>(3, vector<int>(3)));\n    for (int m = 0; m < M; m++) {\n        for (int i = 0; i < 3; i++) {\n            for (int j = 0; j < 3; j++) cin >> s[m][i][j];\n        }\n    }\n\n    const int NN = N * N;\n\n    // Build all possible operations (m, p, q)\n    // where stamp top-left (p,q) is within [0..N-3].\n    vector<OpInfo> opsAll;\n    opsAll.reserve(M * (N - 2) * (N - 2));\n\n    for (int m = 0; m < M; m++) {\n        for (int p = 0; p <= N - 3; p++) {\n            for (int q = 0; q <= N - 3; q++) {\n                OpInfo info;\n                info.m = (uint8_t)m;\n                info.p = (uint8_t)p;\n                info.q = (uint8_t)q;\n                int t = 0;\n                for (int di = 0; di < 3; di++) {\n                    for (int dj = 0; dj < 3; dj++) {\n                        int ii = p + di;\n                        int jj = q + dj;\n                        info.idx[t] = (uint8_t)(ii * N + jj);\n                        info.add[t] = s[m][di][dj];\n                        t++;\n                    }\n                }\n                opsAll.push_back(info);\n            }\n        }\n    }\n    const int numOps = (int)opsAll.size();\n\n    // initial residues\n    array<int, 81> initX{}; // N fixed to 9 by statement, but keep array size 81\n    // If N might differ, we'd need dynamic array, but contest constraints say N=9.\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            initX[i * N + j] = a[i][j]; // already in [0..MOD-1]\n        }\n    }\n\n    auto evaluate = [&](const vector<int>& opsList) -> int64 {\n        array<int, 81> x;\n        memcpy(x.data(), initX.data(), sizeof(int) * 81);\n\n        for (int opId : opsList) {\n            const auto &op = opsAll[opId];\n            for (int t = 0; t < 9; t++) {\n                uint8_t idx = op.idx[t];\n                int y = x[idx] + op.add[t];\n                if (y >= MOD) y -= MOD;\n                x[idx] = y;\n            }\n        }\n\n        int64 score = 0;\n        for (int i = 0; i < N * N; i++) score += x[i];\n        return score;\n    };\n\n    // Precompute top candidates by immediate delta from initial state\n    vector<int64> deltaInit(numOps, 0);\n    for (int opId = 0; opId < numOps; opId++) {\n        const auto &op = opsAll[opId];\n        int64 d = 0;\n        for (int t = 0; t < 9; t++) {\n            uint8_t idx = op.idx[t];\n            int cur = initX[idx];\n            int y = cur + op.add[t];\n            if (y >= MOD) y -= MOD;\n            d += (int64)(y - cur);\n        }\n        deltaInit[opId] = d;\n    }\n    vector<int> topOpsIdx(numOps);\n    iota(topOpsIdx.begin(), topOpsIdx.end(), 0);\n    nth_element(topOpsIdx.begin(), topOpsIdx.begin() + min(numOps, 200), topOpsIdx.end(),\n                [&](int i, int j){ return deltaInit[i] > deltaInit[j]; });\n    int topKeep = min(numOps, 200);\n    topOpsIdx.resize(topKeep);\n    // sort topOpsIdx for stable sampling bias\n    sort(topOpsIdx.begin(), topOpsIdx.end(), [&](int i, int j){ return deltaInit[i] > deltaInit[j]; });\n\n    auto greedy_stochastic = [&](uint64_t seed) -> vector<int> {\n        std::mt19937_64 rng(seed);\n\n        array<int, 81> x;\n        memcpy(x.data(), initX.data(), sizeof(int) * 81);\n\n        vector<int> chosen;\n        chosen.reserve(K);\n\n        const int TOPS = 7; // choose uniformly among top TOPS by one-step delta\n        vector<pair<int64,int>> best; best.reserve(TOPS);\n\n        for (int step = 0; step < K; step++) {\n            best.clear();\n\n            for (int opId = 0; opId < numOps; opId++) {\n                const auto &op = opsAll[opId];\n                int64 delta = 0;\n                for (int t = 0; t < 9; t++) {\n                    uint8_t idx = op.idx[t];\n                    int cur = x[idx];\n                    int y = cur + op.add[t];\n                    if (y >= MOD) y -= MOD;\n                    delta += (int64)(y - cur);\n                }\n\n                if ((int)best.size() < TOPS) {\n                    best.push_back({delta, opId});\n                } else {\n                    // keep best by delta\n                    int minPos = 0;\n                    for (int i = 1; i < (int)best.size(); i++) {\n                        if (best[i].first < best[minPos].first) minPos = i;\n                    }\n                    if (delta > best[minPos].first) best[minPos] = {delta, opId};\n                }\n            }\n\n            // select uniformly among the best candidates found\n            int pick = (int)(rng() % best.size());\n            int opId = best[pick].second;\n            chosen.push_back(opId);\n\n            // apply it\n            const auto &op = opsAll[opId];\n            for (int t = 0; t < 9; t++) {\n                uint8_t idx = op.idx[t];\n                int y = x[idx] + op.add[t];\n                if (y >= MOD) y -= MOD;\n                x[idx] = y;\n            }\n        }\n        return chosen;\n    };\n\n    auto anneal = [&](vector<int> opsInit, int64 scoreInit, uint64_t seed,\n                      int64 timeBudgetMs) -> pair<int64, vector<int>> {\n        std::mt19937_64 rng(seed);\n\n        vector<int> ops = std::move(opsInit);\n        int64 curScore = scoreInit;\n        int64 bestScore = curScore;\n        vector<int> bestOps = ops;\n\n        auto start = chrono::steady_clock::now();\n\n        auto randOp = [&](bool biasTop) -> int {\n            if (biasTop && !topOpsIdx.empty() && (rng() % 100) < 70) {\n                return topOpsIdx[rng() % topOpsIdx.size()];\n            }\n            return (int)(rng() % numOps);\n        };\n\n        const double T0 = 5e9;\n        const double Tend = 1e8;\n\n        auto elapsedMs = [&]() -> int64 {\n            return chrono::duration_cast<chrono::milliseconds>(chrono::steady_clock::now() - start).count();\n        };\n\n        while (elapsedMs() < timeBudgetMs) {\n            // Temperature schedule based on elapsed\n            double prog = min(1.0, (double)elapsedMs() / (double)timeBudgetMs);\n            double T = T0 * pow(Tend / T0, prog);\n\n            // choose move type\n            int sz = (int)ops.size();\n            int r = (int)(rng() % 100);\n\n            if (sz == 0) {\n                // must insert\n                int newOp = randOp(true);\n                ops.push_back(newOp);\n                int64 candScore = evaluate(ops);\n                bool accept = (candScore >= curScore);\n                if (!accept) {\n                    double diff = (double)(candScore - curScore);\n                    double prob = exp(diff / T);\n                    double u = (double)rng() / (double)rng.max();\n                    accept = (u < prob);\n                }\n                if (accept) {\n                    curScore = candScore;\n                    if (candScore > bestScore) {\n                        bestScore = candScore;\n                        bestOps = ops;\n                    }\n                } else {\n                    ops.pop_back();\n                }\n                continue;\n            }\n\n            if (sz == K) {\n                // can't insert\n                if (r < 60) {\n                    // replacement\n                    int pos = (int)(rng() % sz);\n                    int oldOp = ops[pos];\n                    int newOp = randOp(true);\n                    if (newOp == oldOp) continue;\n\n                    ops[pos] = newOp;\n                    int64 candScore = evaluate(ops);\n\n                    bool accept = (candScore >= curScore);\n                    if (!accept) {\n                        double diff = (double)(candScore - curScore);\n                        double prob = exp(diff / T);\n                        double u = (double)rng() / (double)rng.max();\n                        accept = (u < prob);\n                    }\n\n                    if (accept) {\n                        curScore = candScore;\n                        if (candScore > bestScore) {\n                            bestScore = candScore;\n                            bestOps = ops;\n                        }\n                    } else {\n                        ops[pos] = oldOp;\n                    }\n                } else {\n                    // deletion\n                    int pos = (int)(rng() % sz);\n                    int oldOp = ops[pos];\n                    ops.erase(ops.begin() + pos);\n\n                    int64 candScore = evaluate(ops);\n                    bool accept = (candScore >= curScore);\n                    if (!accept) {\n                        double diff = (double)(candScore - curScore);\n                        double prob = exp(diff / T);\n                        double u = (double)rng() / (double)rng.max();\n                        accept = (u < prob);\n                    }\n\n                    if (accept) {\n                        curScore = candScore;\n                        if (candScore > bestScore) {\n                            bestScore = candScore;\n                            bestOps = ops;\n                        }\n                    } else {\n                        ops.insert(ops.begin() + pos, oldOp);\n                    }\n                }\n                continue;\n            }\n\n            // general case: replacement / insertion / deletion\n            if (r < 50) {\n                // replacement\n                int pos = (int)(rng() % sz);\n                int oldOp = ops[pos];\n                int newOp = randOp(true);\n                if (newOp == oldOp) continue;\n\n                ops[pos] = newOp;\n                int64 candScore = evaluate(ops);\n\n                bool accept = (candScore >= curScore);\n                if (!accept) {\n                    double diff = (double)(candScore - curScore);\n                    double prob = exp(diff / T);\n                    double u = (double)rng() / (double)rng.max();\n                    accept = (u < prob);\n                }\n\n                if (accept) {\n                    curScore = candScore;\n                    if (candScore > bestScore) {\n                        bestScore = candScore;\n                        bestOps = ops;\n                    }\n                } else {\n                    ops[pos] = oldOp;\n                }\n            } else if (r < 80) {\n                // insertion\n                int newOp = randOp(true);\n                ops.push_back(newOp);\n                int64 candScore = evaluate(ops);\n\n                bool accept = (candScore >= curScore);\n                if (!accept) {\n                    double diff = (double)(candScore - curScore);\n                    double prob = exp(diff / T);\n                    double u = (double)rng() / (double)rng.max();\n                    accept = (u < prob);\n                }\n\n                if (accept) {\n                    curScore = candScore;\n                    if (candScore > bestScore) {\n                        bestScore = candScore;\n                        bestOps = ops;\n                    }\n                } else {\n                    ops.pop_back();\n                }\n            } else {\n                // deletion\n                int pos = (int)(rng() % sz);\n                int oldOp = ops[pos];\n                ops.erase(ops.begin() + pos);\n\n                int64 candScore = evaluate(ops);\n                bool accept = (candScore >= curScore);\n                if (!accept) {\n                    double diff = (double)(candScore - curScore);\n                    double prob = exp(diff / T);\n                    double u = (double)rng() / (double)rng.max();\n                    accept = (u < prob);\n                }\n\n                if (accept) {\n                    curScore = candScore;\n                    if (candScore > bestScore) {\n                        bestScore = candScore;\n                        bestOps = ops;\n                    }\n                } else {\n                    ops.insert(ops.begin() + pos, oldOp);\n                }\n            }\n        }\n\n        return {bestScore, bestOps};\n    };\n\n    // Global time budget ~ 1.9 sec\n    auto globalStart = chrono::steady_clock::now();\n    auto globalElapsedMs = [&]() -> int64 {\n        return chrono::duration_cast<chrono::milliseconds>(chrono::steady_clock::now() - globalStart).count();\n    };\n\n    int64 bestScore = -1;\n    vector<int> bestOps;\n\n    const int RESTARTS = 3;\n    for (int r = 0; r < RESTARTS; r++) {\n        if (globalElapsedMs() > 1850) break;\n\n        uint64_t seed = 123456789ULL + 10007ULL * r;\n\n        vector<int> initOps = greedy_stochastic(seed);\n        int64 initScore = evaluate(initOps);\n\n        int64 remain = 1850 - globalElapsedMs();\n        int64 budgetMs = max<int64>(150, remain / (RESTARTS - r)); // ensure some time each\n\n        auto [sc, ops] = anneal(std::move(initOps), initScore, seed + 99991ULL, (int)budgetMs);\n        if (sc > bestScore) {\n            bestScore = sc;\n            bestOps = std::move(ops);\n        }\n    }\n\n    // Output\n    int L = (int)bestOps.size();\n    if (L > K) L = K; // should not happen\n    cout << L << \"\\n\";\n    for (int i = 0; i < L; i++) {\n        int opId = bestOps[i];\n        const auto &op = opsAll[opId];\n        cout << (int)op.m << \" \" << (int)op.p << \" \" << (int)op.q << \"\\n\";\n    }\n    return 0;\n}","ahc033":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Crane {\n    int x, y;\n    bool holding = false;\n    int holdId = -1;\n    bool bombed = false;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    cin >> N;\n    vector<vector<int>> A(N, vector<int>(N));\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) cin >> A[i][j];\n    }\n\n    // Plan: bomb small cranes on the first turn, then use only the large crane.\n    // Processing receiving gates in order r=0..N-1, picking N containers each time gate has one.\n    // When holding a container b, deliver it to dispatch gate (b/N, N-1).\n\n    const int R = N, C = N;\n    vector<vector<int>> grid(R, vector<int>(C, -1)); // container id or -1\n    vector<int> recvNext(R, 0); // next index to place for receiving gate row i\n\n    vector<Crane> cranes(N);\n    for (int i = 0; i < N; i++) {\n        cranes[i].x = i;\n        cranes[i].y = 0;\n        cranes[i].holding = false;\n        cranes[i].holdId = -1;\n        cranes[i].bombed = false;\n    }\n\n    enum Mode { GO_PICK, GO_DISPATCH };\n    Mode mode = GO_PICK;\n\n    int curGate = 0;     // receiving gate row\n    int pickedFromGate = 0;\n    int dispatchRow = -1;\n    int T = 0;\n\n    long long dispatchedCount = 0;\n    vector<vector<int>> dispatchSeq(N);\n\n    // operations[crane] is the string to output\n    vector<string> ops(N);\n\n    auto inb = [&](int x, int y) {\n        return 0 <= x && x < R && 0 <= y && y < C;\n    };\n\n    // Simulation loop up to 10000 turns\n    for (; T < 10000; T++) {\n        // ---- step 1: place arriving containers on receiving gates (left edge) ----\n        for (int i = 0; i < N; i++) {\n            if (recvNext[i] >= N) continue;\n            if (grid[i][0] != -1) continue; // already has a container\n\n            bool block = false;\n            for (int k = 0; k < N; k++) {\n                if (cranes[k].bombed) continue;\n                if (cranes[k].holding && cranes[k].x == i && cranes[k].y == 0) {\n                    block = true;\n                    break;\n                }\n            }\n            if (block) continue;\n\n            grid[i][0] = A[i][recvNext[i]];\n            recvNext[i]++;\n        }\n\n        // ---- decide actions for each crane for step 2 ----\n        vector<char> act(N, '.');\n\n        // Small cranes (1..N-1) are bombed on turn 1 (T==0) and then do '.'\n        for (int i = 1; i < N; i++) {\n            if (!cranes[i].bombed) {\n                if (T == 0) act[i] = 'B';\n                else act[i] = '.';\n            } else {\n                act[i] = '.';\n            }\n        }\n\n        // Large crane (0)\n        if (!cranes[0].bombed) {\n            if (mode == GO_PICK) {\n                // target receiving square: (curGate, 0)\n                if (cranes[0].x == curGate && cranes[0].y == 0) {\n                    if (!cranes[0].holding) {\n                        if (grid[curGate][0] != -1) {\n                            act[0] = 'P';\n                        } else {\n                            act[0] = '.';\n                        }\n                    } else {\n                        // Shouldn't happen in GO_PICK\n                        act[0] = '.';\n                    }\n                } else {\n                    // move towards (curGate, 0) while not holding\n                    if (cranes[0].x < curGate) act[0] = 'D';\n                    else if (cranes[0].x > curGate) act[0] = 'U';\n                    else if (cranes[0].y > 0) act[0] = 'L';\n                    else act[0] = '.';\n                }\n            } else { // GO_DISPATCH\n                // target dispatch square: (dispatchRow, N-1)\n                int tx = dispatchRow, ty = N - 1;\n                if (cranes[0].x == tx && cranes[0].y == ty) {\n                    if (cranes[0].holding) {\n                        if (grid[tx][ty] == -1) act[0] = 'Q';\n                        else act[0] = '.';\n                    } else {\n                        act[0] = '.';\n                    }\n                } else {\n                    // while carrying, prefer \"right-first\": go to col 4 then vertical\n                    if (cranes[0].y < N - 1) act[0] = 'R';\n                    else {\n                        if (cranes[0].x < tx) act[0] = 'D';\n                        else act[0] = 'U';\n                    }\n                }\n            }\n        }\n\n        // Append ops\n        for (int i = 0; i < N; i++) ops[i].push_back(act[i]);\n\n        // ---- step 2: apply actions simultaneously (with legality checks) ----\n        // Determine destinations for movement and bombing.\n        vector<pair<int,int>> src(N), dest(N);\n        vector<bool> bombAfter(N, false), activeAfter(N, false);\n        for (int i = 0; i < N; i++) {\n            src[i] = {cranes[i].x, cranes[i].y};\n            dest[i] = src[i];\n        }\n\n        auto getDest = [&](int i, char a) -> pair<int,int> {\n            int x = cranes[i].x, y = cranes[i].y;\n            if (a == 'U') x--;\n            if (a == 'D') x++;\n            if (a == 'L') y--;\n            if (a == 'R') y++;\n            return {x, y};\n        };\n\n        for (int i = 0; i < N; i++) {\n            char a = act[i];\n            if (cranes[i].bombed) {\n                if (a != '.') {\n                    cerr << \"Illegal: bombed crane acted at turn \" << T+1 << \"\\n\";\n                    return 0;\n                }\n                continue;\n            }\n\n            if (a == 'B') {\n                if (cranes[i].holding) {\n                    cerr << \"Illegal: crane bombing while holding\\n\";\n                    return 0;\n                }\n                bombAfter[i] = true;\n                activeAfter[i] = false;\n                dest[i] = src[i];\n            } else if (a == 'U' || a == 'D' || a == 'L' || a == 'R') {\n                auto nd = getDest(i, a);\n                if (!inb(nd.first, nd.second)) {\n                    cerr << \"Illegal: out of bounds move\\n\";\n                    return 0;\n                }\n                dest[i] = nd;\n                activeAfter[i] = true;\n            } else {\n                // '.', 'P', 'Q': no movement\n                dest[i] = src[i];\n                activeAfter[i] = true;\n            }\n        }\n\n        // Overlap check (only consider cranes that remain after step 2, excluding those that bomb)\n        vector<int> remaining;\n        for (int i = 0; i < N; i++) {\n            if (!cranes[i].bombed && !bombAfter[i]) remaining.push_back(i);\n        }\n        // Unique destinations\n        {\n            set<pair<int,int>> used;\n            for (int i : remaining) {\n                if (used.count(dest[i])) {\n                    cerr << \"Illegal: overlap after step2\\n\";\n                    return 0;\n                }\n                used.insert(dest[i]);\n            }\n            // Swap check among remaining\n            for (int a = 0; a < (int)remaining.size(); a++) for (int b = a+1; b < (int)remaining.size(); b++) {\n                int i = remaining[a], j = remaining[b];\n                if (src[i] == dest[j] && src[j] == dest[i] && src[i] != src[j]) {\n                    cerr << \"Illegal: swap/pass move detected\\n\";\n                    return 0;\n                }\n            }\n        }\n\n        // Apply movements\n        for (int i = 0; i < N; i++) {\n            if (cranes[i].bombed) continue;\n            if (bombAfter[i]) continue;\n            cranes[i].x = dest[i].first;\n            cranes[i].y = dest[i].second;\n        }\n        // Apply bombing\n        for (int i = 0; i < N; i++) {\n            if (bombAfter[i]) cranes[i].bombed = true;\n        }\n\n        // Apply P/Q\n        for (int i = 0; i < N; i++) {\n            if (cranes[i].bombed) continue;\n            char a = act[i];\n            if (a == 'P') {\n                if (cranes[i].holding) {\n                    cerr << \"Illegal: P while holding\\n\";\n                    return 0;\n                }\n                int x = cranes[i].x, y = cranes[i].y;\n                if (grid[x][y] == -1) {\n                    cerr << \"Illegal: P on empty cell\\n\";\n                    return 0;\n                }\n                cranes[i].holding = true;\n                cranes[i].holdId = grid[x][y];\n                grid[x][y] = -1;\n            } else if (a == 'Q') {\n                if (!cranes[i].holding) {\n                    cerr << \"Illegal: Q without holding\\n\";\n                    return 0;\n                }\n                int x = cranes[i].x, y = cranes[i].y;\n                if (grid[x][y] != -1) {\n                    cerr << \"Illegal: Q on occupied cell\\n\";\n                    return 0;\n                }\n                grid[x][y] = cranes[i].holdId;\n                cranes[i].holdId = -1;\n                cranes[i].holding = false;\n            } else {\n                // '.', movement handled already\n            }\n        }\n\n        // ---- step 3: dispatch containers from dispatch gates (right edge) ----\n        for (int i = 0; i < N; i++) {\n            int x = i, y = N-1;\n            if (grid[x][y] != -1) {\n                int b = grid[x][y];\n                grid[x][y] = -1;\n                dispatchedCount++;\n                int expectGate = b / N;\n                if (expectGate != i) {\n                    // Should not happen in this strategy\n                    // Still keep simulation running.\n                }\n                dispatchSeq[i].push_back(b);\n            }\n        }\n\n        // ---- update mode and counters based on crane0 action ----\n        if (!cranes[0].bombed) {\n            if (mode == GO_PICK) {\n                if (act[0] == 'P') {\n                    // Just picked some container b\n                    // mode becomes GO_DISPATCH with correct dispatch gate row\n                    int b = cranes[0].holdId; // after P, holdId is set\n                    dispatchRow = b / N;\n                    mode = GO_DISPATCH;\n                }\n            } else { // GO_DISPATCH\n                if (act[0] == 'Q') {\n                    // Released a container at dispatch gate; it should have been dispatched in step3.\n                    pickedFromGate++;\n                    if (pickedFromGate == N) {\n                        curGate++;\n                        pickedFromGate = 0;\n                    }\n                    if (curGate == N) {\n                        // All gates done; GO_PICK won't be used.\n                    }\n                    mode = GO_PICK;\n                }\n            }\n        }\n\n        if (dispatchedCount == 1LL * N * N) break;\n    }\n\n    if (dispatchedCount != 1LL * N * N) {\n        // Still output what we have; but ideally shouldn't happen.\n        // In contest evaluation this could hurt M3 badly.\n        // We just exit.\n        // (No extra printing to keep output format correct.)\n    }\n\n    // Ensure all strings same length\n    int L = ops[0].size();\n    for (int i = 0; i < N; i++) {\n        // ops[i] should already have length L due to synchronous simulation loop\n        // Still be safe.\n        if ((int)ops[i].size() < L) ops[i] += string(L - ops[i].size(), '.');\n    }\n\n    for (int i = 0; i < N; i++) {\n        cout << ops[i] << \"\\n\";\n    }\n    return 0;\n}","ahc034":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Shipment {\n    int sr, sc;\n    int tr, tc;\n    int amt;\n};\n\nstatic inline int manhattan(int r1, int c1, int r2, int c2) {\n    return abs(r1 - r2) + abs(c1 - c2);\n}\n\nstatic inline void movePath(int &r, int &c, int nr, int nc, vector<string> &ops) {\n    // vertical first, then horizontal: always shortest\n    while (r < nr) { ops.push_back(\"D\"); r++; }\n    while (r > nr) { ops.push_back(\"U\"); r--; }\n    while (c < nc) { ops.push_back(\"R\"); c++; }\n    while (c > nc) { ops.push_back(\"L\"); c--; }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    cin >> N;\n    vector<vector<int>> h(N, vector<int>(N));\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) cin >> h[i][j];\n    }\n\n    vector<pair<pair<int,int>, int>> supply; // ((r,c), amount)\n    vector<pair<pair<int,int>, int>> demand;\n    for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) {\n        if (h[i][j] > 0) supply.push_back({{i,j}, h[i][j]});\n        else if (h[i][j] < 0) demand.push_back({{i,j}, -h[i][j]});\n    }\n\n    // If already all zero (no shipments), output nothing.\n    if (supply.empty()) {\n        return 0;\n    }\n\n    // Create shipments: for each supply cell, greedily match nearest demand with remaining > 0.\n    vector<int> remD(demand.size());\n    for (int i = 0; i < (int)demand.size(); i++) remD[i] = demand[i].second;\n\n    vector<Shipment> shipments;\n    shipments.reserve(supply.size() + demand.size());\n\n    for (auto &s : supply) {\n        int sr = s.first.first, sc = s.first.second;\n        int srem = s.second;\n\n        while (srem > 0) {\n            int bestIdx = -1;\n            int bestDist = INT_MAX;\n            int bestRem = -1;\n\n            for (int j = 0; j < (int)demand.size(); j++) if (remD[j] > 0) {\n                int dr = demand[j].first.first, dc = demand[j].first.second;\n                int dist = manhattan(sr, sc, dr, dc);\n                if (dist < bestDist || (dist == bestDist && remD[j] > bestRem)) {\n                    bestDist = dist;\n                    bestRem = remD[j];\n                    bestIdx = j;\n                }\n            }\n\n            // Should always exist because total sum is 0.\n            if (bestIdx == -1) break;\n\n            int tr = demand[bestIdx].first.first;\n            int tc = demand[bestIdx].first.second;\n            int x = min(srem, remD[bestIdx]);\n\n            shipments.push_back({sr, sc, tr, tc, x});\n            srem -= x;\n            remD[bestIdx] -= x;\n        }\n    }\n\n    // (Optional sanity check)\n    // for (int x : remD) assert(x == 0);\n\n    // Schedule shipments: greedy by closeness of next source from current position.\n    vector<char> done(shipments.size(), 0);\n    int remaining = (int)shipments.size();\n\n    int curR = 0, curC = 0;\n    vector<string> ops;\n    ops.reserve(40000);\n\n    while (remaining > 0) {\n        int best = -1;\n        int bestDist = INT_MAX;\n        int bestTransport = INT_MAX;\n\n        for (int i = 0; i < (int)shipments.size(); i++) if (!done[i]) {\n            auto &sh = shipments[i];\n            int d1 = manhattan(curR, curC, sh.sr, sh.sc);\n            int d2 = manhattan(sh.sr, sh.sc, sh.tr, sh.tc);\n            if (d1 < bestDist || (d1 == bestDist && d2 < bestTransport)) {\n                bestDist = d1;\n                bestTransport = d2;\n                best = i;\n            }\n        }\n\n        auto &sh = shipments[best];\n\n        // Move empty to source\n        movePath(curR, curC, sh.sr, sh.sc, ops);\n\n        // Load\n        ops.push_back(\"+\" + to_string(sh.amt));\n\n        // Move with load to target\n        movePath(curR, curC, sh.tr, sh.tc, ops);\n\n        // Unload\n        ops.push_back(\"-\" + to_string(sh.amt));\n\n        done[best] = 1;\n        remaining--;\n    }\n\n    // Turn limit safety (should be far below for this strategy)\n    if ((int)ops.size() > 100000) {\n        // Fallback: shouldn't happen, but in case, truncate would be illegal.\n        // Here we just output nothing to avoid WA with partial sequence.\n        return 0;\n    }\n\n    for (auto &s : ops) cout << s << \"\\n\";\n    return 0;\n}","ahc035":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\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    const int seed_count = 2 * N * (N - 1);\n    const int C = N * N;\n\n    vector<vector<int>> X(seed_count, vector<int>(M));\n    for (int k = 0; k < seed_count; k++) {\n        for (int l = 0; l < M; l++) cin >> X[k][l];\n    }\n\n    auto id = [&](int i, int j) { return i * N + j; };\n\n    // Build edge list and incident edges for local search (fixed by N).\n    vector<pair<int,int>> edges;\n    edges.reserve(seed_count);\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (i + 1 < N) edges.push_back({id(i,j), id(i+1,j)});\n            if (j + 1 < N) edges.push_back({id(i,j), id(i,j+1)});\n        }\n    }\n    // edges.size() should equal seed_count.\n    // incident edge indices per cell\n    vector<vector<int>> incident(C);\n    for (int ei = 0; ei < (int)edges.size(); ei++) {\n        auto [u,v] = edges[ei];\n        incident[u].push_back(ei);\n        incident[v].push_back(ei);\n    }\n\n    mt19937_64 rng((uint64_t)chrono::high_resolution_clock::now().time_since_epoch().count());\n\n    auto solve_one_turn = [&]() -> vector<int> {\n        // Compute V and per-component maxima indices.\n        vector<int> V(seed_count, 0);\n        vector<int> maxIdx(M, 0);\n        vector<int> maxVal(M, -1);\n\n        for (int k = 0; k < seed_count; k++) {\n            int sum = 0;\n            for (int l = 0; l < M; l++) sum += X[k][l];\n            V[k] = sum;\n        }\n        for (int l = 0; l < M; l++) {\n            int bestk = 0;\n            int bestv = X[0][l];\n            for (int k = 1; k < seed_count; k++) {\n                if (X[k][l] > bestv) {\n                    bestv = X[k][l];\n                    bestk = k;\n                }\n            }\n            maxVal[l] = bestv;\n            maxIdx[l] = bestk;\n        }\n\n        // Precompute UB(a,b) and UB^2(a,b).\n        vector<vector<int>> UB(seed_count, vector<int>(seed_count, 0));\n        vector<vector<ll>> UB2(seed_count, vector<ll>(seed_count, 0));\n        for (int a = 0; a < seed_count; a++) {\n            for (int b = a; b < seed_count; b++) {\n                int ub = 0;\n                for (int l = 0; l < M; l++) ub += max(X[a][l], X[b][l]);\n                UB[a][b] = UB[b][a] = ub;\n                UB2[a][b] = UB2[b][a] = (ll)ub * (ll)ub;\n            }\n        }\n\n        // Candidate seeds: top by V + per-component argmax seeds.\n        vector<int> byV(seed_count);\n        iota(byV.begin(), byV.end(), 0);\n        sort(byV.begin(), byV.end(), [&](int a, int b){ return V[a] > V[b]; });\n\n        vector<int> cand;\n        cand.reserve(seed_count);\n        {\n            int TOPV = min(seed_count, 30);\n            for (int i = 0; i < TOPV; i++) cand.push_back(byV[i]);\n        }\n        for (int l = 0; l < M; l++) cand.push_back(maxIdx[l]);\n        sort(cand.begin(), cand.end());\n        cand.erase(unique(cand.begin(), cand.end()), cand.end());\n\n        // Use top subset for pair search by V to limit O(k^2).\n        vector<int> cand2 = cand;\n        sort(cand2.begin(), cand2.end(), [&](int a, int b){ return V[a] > V[b]; });\n        int K = min<int>(25, cand2.size());\n        cand2.resize(K);\n\n        // Best UB pair (a,b)\n        int bestA = cand2[0], bestB = cand2[1];\n        ll bestPairUB = -1;\n        for (int i = 0; i < K; i++) for (int j = i+1; j < K; j++) {\n            int a = cand2[i], b = cand2[j];\n            ll ub = UB[a][b];\n            if (ub > bestPairUB || (ub == bestPairUB && V[a] + V[b] > V[bestA] + V[bestB])) {\n                bestPairUB = ub;\n                bestA = a;\n                bestB = b;\n            }\n        }\n\n        // Select 36 seeds.\n        vector<int> chosen;\n        chosen.reserve(C);\n        chosen.push_back(bestA);\n        if (bestB != bestA) chosen.push_back(bestB);\n\n        vector<char> used(seed_count, 0);\n        used[bestA] = 1;\n        used[bestB] = 1;\n\n        struct Item { int k; ll score; };\n        vector<Item> items;\n        items.reserve(seed_count);\n        for (int k = 0; k < seed_count; k++) {\n            if (used[k]) continue;\n            // Score biased toward mixing with bestA/bestB.\n            ll score = (ll)V[k] * 10 + (ll)UB[bestA][k] + (ll)UB[bestB][k];\n            items.push_back({k, score});\n        }\n        sort(items.begin(), items.end(), [&](const Item& a, const Item& b){\n            return a.score > b.score;\n        });\n\n        for (auto &it : items) {\n            if ((int)chosen.size() >= C) break;\n            chosen.push_back(it.k);\n            used[it.k] = 1;\n        }\n        // Fallback if somehow not enough (shouldn't happen)\n        for (int k = 0; (int)chosen.size() < C && k < seed_count; k++) {\n            if (!used[k]) {\n                chosen.push_back(k);\n                used[k] = 1;\n            }\n        }\n\n        // Build initial placement A (size C, entries are seed indices distinct).\n        vector<int> A(C, -1);\n        auto place = [&](int i, int j, int seed) {\n            A[id(i,j)] = seed;\n        };\n\n        // Fixed positions near top-left (for N>=3, which is true here).\n        place(0,0,bestA);\n        if (N > 1) place(0,1,bestB);\n\n        // Used seeds in placement\n        vector<char> inPlace(seed_count, 0);\n        inPlace[bestA] = 1;\n        inPlace[bestB] = 1;\n\n        auto pickMaxWith = [&](int baseSeed, const vector<int>& pool)->int{\n            int arg = -1;\n            ll best = -1;\n            for (int k : pool) {\n                ll ub = UB[baseSeed][k];\n                if (ub > best) { best = ub; arg = k; }\n            }\n            return arg;\n        };\n\n        // Remaining pool\n        vector<int> pool;\n        pool.reserve(C);\n        for (int k : chosen) if (!inPlace[k]) pool.push_back(k);\n\n        // Place neighbor maximizing UB with bestA / bestB when possible\n        if (N > 1) {\n            if (int(pool.size()) > 0) {\n                // (1,0) is adjacent to (0,0)\n                int c = pickMaxWith(bestA, pool);\n                if (c != -1) {\n                    place(1,0,c);\n                    inPlace[c] = 1;\n                    pool.erase(find(pool.begin(), pool.end(), c));\n                }\n            }\n        }\n        if (N > 2) {\n            if (!pool.empty()) {\n                // (0,2) adjacent to (0,1)=bestB\n                int d = pickMaxWith(bestB, pool);\n                place(0,2,d);\n                inPlace[d] = 1;\n                pool.erase(find(pool.begin(), pool.end(), d));\n            }\n        }\n        if (N > 1) {\n            if (!pool.empty()) {\n                // (1,1) adjacent to (0,1)=bestB\n                int e = pickMaxWith(bestB, pool);\n                place(1,1,e);\n                inPlace[e] = 1;\n                pool.erase(find(pool.begin(), pool.end(), e));\n            }\n        }\n\n        // Collect remaining unfilled positions\n        vector<int> evenPos, oddPos;\n        for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) {\n            int p = id(i,j);\n            if (A[p] != -1) continue;\n            if ((i+j)%2==0) evenPos.push_back(p);\n            else oddPos.push_back(p);\n        }\n\n        // Remaining seeds from chosen not placed.\n        vector<int> remSeeds;\n        remSeeds.reserve(C);\n        for (int k : chosen) if (!inPlace[k]) remSeeds.push_back(k);\n        sort(remSeeds.begin(), remSeeds.end(), [&](int a, int b){ return V[a] > V[b]; });\n\n        // Fill remaining by alternating parity (to spread good seeds).\n        int ie = 0, io = 0;\n        for (int idx = 0; idx < (int)remSeeds.size(); idx++) {\n            int k = remSeeds[idx];\n            bool wantEven = (idx%2==0);\n            if (wantEven) {\n                if (ie < (int)evenPos.size()) A[evenPos[ie++]] = k;\n                else A[oddPos[io++]] = k;\n            } else {\n                if (io < (int)oddPos.size()) A[oddPos[io++]] = k;\n                else A[evenPos[ie++]] = k;\n            }\n        }\n\n        // Local search: maximize sum over edges UB^2.\n        auto calcObj = [&]() -> ll {\n            ll obj = 0;\n            for (int ei = 0; ei < (int)edges.size(); ei++) {\n                auto [u,v] = edges[ei];\n                int su = A[u], sv = A[v];\n                obj += UB2[su][sv];\n            }\n            return obj;\n        };\n\n        ll obj = calcObj();\n\n        int iters = 9000;\n        double temp0 = 7e6; // tuned for UB^2 magnitudes\n        uniform_real_distribution<double> uni(0.0, 1.0);\n\n        for (int it = 0; it < iters; it++) {\n            int p = (int)(rng() % C);\n            int q = (int)(rng() % C);\n            if (p == q) continue;\n\n            int sp = A[p], sq = A[q];\n            if (sp == sq) continue;\n\n            // affected edges: union of incident[p] and incident[q]\n            // since edges are small (60), simple marking is fine.\n            bool mark[100] = {};\n            vector<int> aff;\n            aff.reserve(12);\n            for (int ei : incident[p]) {\n                if (!mark[ei]) { mark[ei] = true; aff.push_back(ei); }\n            }\n            for (int ei : incident[q]) {\n                if (!mark[ei]) { mark[ei] = true; aff.push_back(ei); }\n            }\n\n            ll delta = 0;\n            for (int ei : aff) {\n                auto [u,v] = edges[ei];\n                // old seeds\n                int su_old = (u==p ? sp : (u==q ? sq : A[u]));\n                int sv_old = (v==p ? sp : (v==q ? sq : A[v]));\n                ll oldTerm = UB2[su_old][sv_old];\n\n                // new seeds after swapping p and q\n                int su_new = (u==p ? sq : (u==q ? sp : A[u]));\n                int sv_new = (v==p ? sq : (v==q ? sp : A[v]));\n                ll newTerm = UB2[su_new][sv_new];\n\n                delta += newTerm - oldTerm;\n            }\n\n            if (delta >= 0) {\n                swap(A[p], A[q]);\n                obj += delta;\n            } else {\n                double temp = temp0 * (1.0 - (double)it / iters) * (1.0 - (double)it / iters) + 1.0;\n                double prob = exp((double)delta / temp); // delta negative\n                if (uni(rng) < prob) {\n                    swap(A[p], A[q]);\n                    obj += delta;\n                }\n            }\n        }\n\n        return A;\n    };\n\n    for (int t = 0; t < T; t++) {\n        vector<int> A = solve_one_turn();\n\n        // Output grid A[i][j]\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                if (j) cout << ' ';\n                cout << A[id(i,j)];\n            }\n            cout << '\\n';\n        }\n        cout.flush();\n\n        // Read next seeds (judge provides them after seeing our output).\n        for (int k = 0; k < seed_count; k++) {\n            for (int l = 0; l < M; l++) cin >> X[k][l];\n        }\n    }\n    return 0;\n}","ahc038":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Pt {\n    int x, y;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, V;\n    cin >> N >> M >> V;\n    vector<string> s(N), t(N);\n    for (int i = 0; i < N; i++) cin >> s[i];\n    for (int i = 0; i < N; i++) cin >> t[i];\n\n    vector<vector<int>> occ(N, vector<int>(N, 0));\n    for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) occ[i][j] = (s[i][j] == '1');\n\n    auto inRange = [&](int x, int y) {\n        return 0 <= x && x < N && 0 <= y && y < N;\n    };\n\n    vector<Pt> A, B;\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            int si = (s[i][j] == '1');\n            int ti = (t[i][j] == '1');\n            if (si == 1 && ti == 0) A.push_back({i, j});\n            if (si == 0 && ti == 1) B.push_back({i, j});\n        }\n    }\n\n    // Arm design: V' = 2, root=0, fingertip=1, length 1\n    int Vp = 2;\n    cout << Vp << \"\\n\";\n    cout << 0 << \" \" << 1 << \"\\n\";\n    // initial root\n    int rx = 0, ry = 0; \n    cout << rx << \" \" << ry << \"\\n\";\n\n    // If already done:\n    if (A.empty()) {\n        // No operations needed\n        return 0;\n    }\n\n    // State: (root x, root y, dir)\n    // dir: 0=right, 1=down, 2=left, 3=up\n    array<int,4> dx{0,1,0,-1};\n    array<int,4> dy{1,0,-1,0};\n\n    auto dirFromVec = [&](int ndx, int ndy) -> int {\n        for (int d = 0; d < 4; d++) {\n            if (dx[d] == ndx && dy[d] == ndy) return d;\n        }\n        return 0;\n    };\n\n    int S = N * N * 4;\n    auto encode = [&](int x, int y, int dir) {\n        return ((x * N + y) * 4 + dir);\n    };\n    auto decode = [&](int id, int &x, int &y, int &dir) {\n        dir = id % 4;\n        int p = id / 4;\n        x = p / N;\n        y = p % N;\n    };\n\n    // BFS to best candidate where fingertip equals target cell\n    auto bfsBest = [&](int startState, Pt target) {\n        // candidates are states where (root + offset(dir)) == target\n        vector<int> cand;\n        for (int d = 0; d < 4; d++) {\n            int crx = target.x - dx[d];\n            int cry = target.y - dy[d];\n            if (inRange(crx, cry)) {\n                cand.push_back(encode(crx, cry, d));\n            }\n        }\n\n        vector<int> dist(S, -1);\n        vector<int> prevState(S, -1);\n        vector<char> prevMv(S, '?'), prevRot(S, '?');\n\n        queue<int> q;\n        dist[startState] = 0;\n        q.push(startState);\n\n        // movement options\n        // order: '.' 'U' 'D' 'L' 'R'\n        array<char,5> mvChar{'.','U','D','L','R'};\n        array<int,5> mvX{0,-1,1,0,0};\n        array<int,5> mvY{0,0,0,-1,1};\n\n        // rotation options: '.' 'L'(CCW) 'R'(CW)\n        array<char,3> rotChar{'.','L','R'};\n        auto applyRot = [&](int dir, char rc) -> int {\n            if (rc == 'L') return (dir + 3) % 4; // CCW\n            if (rc == 'R') return (dir + 1) % 4; // CW\n            return dir;\n        };\n\n        while (!q.empty()) {\n            int v = q.front(); q.pop();\n            int vx, vy, vdir;\n            decode(v, vx, vy, vdir);\n            for (int mi = 0; mi < 5; mi++) {\n                int nx2 = vx + mvX[mi];\n                int ny2 = vy + mvY[mi];\n                if (!inRange(nx2, ny2)) continue;\n                for (int ri = 0; ri < 3; ri++) {\n                    char rc = rotChar[ri];\n                    int ndir = applyRot(vdir, rc);\n                    int u = encode(nx2, ny2, ndir);\n                    if (dist[u] != -1) continue;\n                    dist[u] = dist[v] + 1;\n                    prevState[u] = v;\n                    prevMv[u] = mvChar[mi];\n                    prevRot[u] = rc;\n                    q.push(u);\n                }\n            }\n        }\n\n        int best = -1;\n        int bestDist = INT_MAX;\n        for (int id : cand) {\n            if (dist[id] >= 0 && dist[id] < bestDist) {\n                bestDist = dist[id];\n                best = id;\n            }\n        }\n        if (best == -1) {\n            // Should never happen\n            exit(0);\n        }\n\n        // reconstruct\n        vector<pair<char,char>> steps; // (moveChar, rotChar)\n        int cur = best;\n        while (cur != startState) {\n            steps.push_back({prevMv[cur], prevRot[cur]});\n            cur = prevState[cur];\n        }\n        reverse(steps.begin(), steps.end());\n        return pair<int, vector<pair<char,char>>>{best, steps};\n    };\n\n    // current dir initial is right (0)\n    int dir = 0;\n    int startState = encode(rx, ry, dir);\n\n    vector<string> ops;\n    ops.reserve(60000);\n\n    // Greedy order: repeatedly pick a source near current fingertip position,\n    // and pair it with nearest remaining destination.\n    while (!A.empty()) {\n        // fingertip position for heuristic (may be outside; Manhattan is still ok)\n        int fx = rx + dx[dir];\n        int fy = ry + dy[dir];\n\n        int bestI = 0;\n        int bestVal = INT_MAX;\n        for (int i = 0; i < (int)A.size(); i++) {\n            int val = abs(fx - A[i].x) + abs(fy - A[i].y);\n            if (val < bestVal) {\n                bestVal = val;\n                bestI = i;\n            }\n        }\n\n        Pt src = A[bestI];\n        A[bestI] = A.back();\n        A.pop_back();\n\n        int bestJ = 0;\n        bestVal = INT_MAX;\n        for (int j = 0; j < (int)B.size(); j++) {\n            int val = abs(src.x - B[j].x) + abs(src.y - B[j].y);\n            if (val < bestVal) {\n                bestVal = val;\n                bestJ = j;\n            }\n        }\n\n        Pt dst = B[bestJ];\n        B[bestJ] = B.back();\n        B.pop_back();\n\n        // 1) Move to a state where fingertip is on src\n        int curState = encode(rx, ry, dir);\n        auto [stateOnSrc, path1] = bfsBest(curState, src);\n\n        // append bfs steps\n        for (auto [mv, rot] : path1) {\n            string st;\n            st.push_back(mv); st.push_back(rot);\n            st.push_back('.'); st.push_back('.');\n            ops.push_back(st);\n\n            // simulate update\n            if (mv == 'U') rx--;\n            else if (mv == 'D') rx++;\n            else if (mv == 'L') ry--;\n            else if (mv == 'R') ry++;\n            // '.' -> no change\n\n            if (rot == 'L') dir = (dir + 3) % 4;\n            else if (rot == 'R') dir = (dir + 1) % 4;\n        }\n        // pick (idle turn)\n        {\n            // legality check (optional but safe)\n            // if (!occ[src.x][src.y]) { exit(0); }\n            string st = \"...P\";\n            ops.push_back(st);\n            occ[src.x][src.y] = 0; // picked up\n        }\n\n        // 2) Move to a state where fingertip is on dst\n        curState = encode(rx, ry, dir);\n        auto [stateOnDst, path2] = bfsBest(curState, dst);\n\n        for (auto [mv, rot] : path2) {\n            string st;\n            st.push_back(mv); st.push_back(rot);\n            st.push_back('.'); st.push_back('.');\n            ops.push_back(st);\n\n            if (mv == 'U') rx--;\n            else if (mv == 'D') rx++;\n            else if (mv == 'L') ry--;\n            else if (mv == 'R') ry++;\n\n            if (rot == 'L') dir = (dir + 3) % 4;\n            else if (rot == 'R') dir = (dir + 1) % 4;\n        }\n        // release (idle turn)\n        {\n            // if (occ[dst.x][dst.y]) { exit(0); }\n            string st = \"...P\";\n            ops.push_back(st);\n            occ[dst.x][dst.y] = 1; // placed\n        }\n    }\n\n    if ((int)ops.size() > 100000) {\n        // Should not happen with the planned approach; if it does, truncate would break legality.\n        // Exit to avoid WA due to exceeding constraints.\n        return 0;\n    }\n\n    for (auto &st : ops) cout << st << \"\\n\";\n    return 0;\n}","ahc039":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int MAXC = 100000;\nstatic constexpr int MAXN = 10000; // 2N, N=5000\n\nstruct Pt {\n    int x, y;\n    int w; // +1 mackerel, -1 sardine\n};\n\nstruct SplitMix64 {\n    uint64_t x;\n    explicit SplitMix64(uint64_t seed) : x(seed) {}\n    uint64_t next_u64() {\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 next_int(int mod) { return (int)(next_u64() % (uint64_t)mod); }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    cin >> N;\n    vector<Pt> pts;\n    pts.reserve(2 * N);\n    for (int i = 0; i < N; i++) {\n        int x, y;\n        cin >> x >> y;\n        pts.push_back({x, y, +1});\n    }\n    for (int i = 0; i < N; i++) {\n        int x, y;\n        cin >> x >> y;\n        pts.push_back({x, y, -1});\n    }\n\n    const int G = 90; // grid resolution\n    const int SZ = MAXC + 1; // 100001\n\n    auto cellOf = [&](int v) -> int {\n        // v in [0, MAXC]\n        // maps into [0, G-1]\n        return (int)((long long)v * G / SZ);\n    };\n\n    vector<vector<int>> A(G, vector<int>(G, 0)); // A[xCell][yCell]\n\n    for (auto &p : pts) {\n        int cx = cellOf(p.x);\n        int cy = cellOf(p.y);\n        A[cx][cy] += p.w;\n    }\n\n    // Find maximum-sum sub-rectangle in A using O(G^3):\n    // Fix x0..x1, reduce to 1D array over y and run Kadane.\n    long long bestCellSum = LLONG_MIN;\n    int bestX0 = 0, bestX1 = 0, bestY0 = 0, bestY1 = 0;\n\n    vector<long long> temp(G, 0);\n\n    auto kadane = [&](const vector<long long> &arr) -> tuple<long long,int,int> {\n        // maximum subarray sum (non-empty), return (sum, l, r)\n        long long cur = arr[0];\n        long long best = arr[0];\n        int curL = 0, bestL = 0, bestR = 0;\n        for (int i = 1; i < G; i++) {\n            if (cur < 0) {\n                cur = arr[i];\n                curL = i;\n            } else {\n                cur += arr[i];\n            }\n            if (cur > best) {\n                best = cur;\n                bestL = curL;\n                bestR = i;\n            }\n        }\n        return {best, bestL, bestR};\n    };\n\n    for (int x0 = 0; x0 < G; x0++) {\n        fill(temp.begin(), temp.end(), 0LL);\n        for (int x1 = x0; x1 < G; x1++) {\n            for (int y = 0; y < G; y++) temp[y] += A[x1][y];\n            auto [s, yl, yr] = kadane(temp);\n            if (s > bestCellSum) {\n                bestCellSum = s;\n                bestX0 = x0; bestX1 = x1;\n                bestY0 = yl; bestY1 = yr;\n            }\n        }\n    }\n\n    auto lowerBoundCell = [&](int c) -> int {\n        // c in [0,G-1]\n        return (int)((long long)c * SZ / G);\n    };\n    auto upperBoundCell = [&](int c) -> int {\n        // inclusive upper bound: (c+1)*SZ/G - 1\n        long long ub = (long long)(c + 1) * SZ / G - 1;\n        if (ub < 0) ub = 0;\n        if (ub > MAXC) ub = MAXC;\n        return (int)ub;\n    };\n\n    auto clampFixRect = [&](int &xL, int &xR, int &yB, int &yT) {\n        xL = max(0, min(MAXC, xL));\n        xR = max(0, min(MAXC, xR));\n        yB = max(0, min(MAXC, yB));\n        yT = max(0, min(MAXC, yT));\n        if (xL == xR) {\n            if (xR < MAXC) xR++;\n            else xL--;\n        }\n        if (yB == yT) {\n            if (yT < MAXC) yT++;\n            else yB--;\n        }\n        xL = max(0, min(MAXC, xL));\n        xR = max(0, min(MAXC, xR));\n        yB = max(0, min(MAXC, yB));\n        yT = max(0, min(MAXC, yT));\n        if (xL > xR) swap(xL, xR);\n        if (yB > yT) swap(yB, yT);\n        // Need strictly rectangle with area > 0 to avoid degenerate polygon\n        if (xL == xR) {\n            if (xL < MAXC) xR = xL + 1;\n            else xL = xR - 1;\n        }\n        if (yB == yT) {\n            if (yB < MAXC) yT = yB + 1;\n            else yB = yT - 1;\n        }\n    };\n\n    auto exactDiff = [&](int xL, int xR, int yB, int yT) -> long long {\n        long long diff = 0;\n        for (auto &p : pts) {\n            if (xL <= p.x && p.x <= xR && yB <= p.y && p.y <= yT) diff += p.w;\n        }\n        return diff;\n    };\n\n    int xL = lowerBoundCell(bestX0);\n    int xR = upperBoundCell(bestX1);\n    int yB = lowerBoundCell(bestY0);\n    int yT = upperBoundCell(bestY1);\n    clampFixRect(xL, xR, yB, yT);\n\n    long long bestDiff = exactDiff(xL, xR, yB, yT);\n    int ansX1 = xL, ansX2 = xR, ansY1 = yB, ansY2 = yT;\n\n    // Build candidate coordinate lists for local random search\n    vector<int> xs, ys;\n    xs.reserve(2 * N);\n    ys.reserve(2 * N);\n    for (auto &p : pts) {\n        xs.push_back(p.x);\n        ys.push_back(p.y);\n    }\n    sort(xs.begin(), xs.end());\n    xs.erase(unique(xs.begin(), xs.end()), xs.end());\n    sort(ys.begin(), ys.end());\n    ys.erase(unique(ys.begin(), ys.end()), ys.end());\n\n    auto makeCandidates = [&](const vector<int> &arr, int L, int R) {\n        L = max(0, L);\n        R = min(MAXC, R);\n        vector<int> cand;\n        for (int v : arr) {\n            if (L <= v && v <= R) cand.push_back(v);\n        }\n        // Ensure boundaries are possible too\n        cand.push_back(L);\n        cand.push_back(R);\n        cand.push_back(0);\n        cand.push_back(MAXC);\n        sort(cand.begin(), cand.end());\n        cand.erase(unique(cand.begin(), cand.end()), cand.end());\n        return cand;\n    };\n\n    vector<int> candX = makeCandidates(xs, ansX1 - 5000, ansX2 + 5000);\n    vector<int> candY = makeCandidates(ys, ansY1 - 5000, ansY2 + 5000);\n\n    SplitMix64 rng(123456789ULL);\n\n    auto tryUpdate = [&](int txL, int txR, int tyB, int tyT) {\n        if (txL < 0 || txR > MAXC || tyB < 0 || tyT > MAXC) return;\n        int L = txL, R = txR, B = tyB, T = tyT;\n        clampFixRect(L, R, B, T);\n        long long d = exactDiff(L, R, B, T);\n        if (d > bestDiff) {\n            bestDiff = d;\n            ansX1 = L; ansX2 = R;\n            ansY1 = B; ansY2 = T;\n        }\n    };\n\n    // Random local search\n    for (int it = 0; it < 500; it++) {\n        int a = candX[rng.next_int((int)candX.size())];\n        int b = candX[rng.next_int((int)candX.size())];\n        int L = min(a, b), R = max(a, b);\n        int c = candY[rng.next_int((int)candY.size())];\n        int d = candY[rng.next_int((int)candY.size())];\n        int B = min(c, d), T = max(c, d);\n\n        // Ensure strict rectangle width/height by clampFixRect\n        tryUpdate(L, R, B, T);\n    }\n\n    // Final safety fallback: full box (guaranteed legal)\n    // score would be 1 because a=b=N => a-b+1=1\n    // (still keep if bestDiff somehow became negative due to extreme adjustments)\n    if (bestDiff < 0) {\n        ansX1 = 0; ansX2 = MAXC;\n        ansY1 = 0; ansY2 = MAXC;\n    }\n\n    // Output rectangle as a simple axis-aligned polygon with 4 vertices\n    cout << 4 << '\\n';\n    // CCW: (xL,yB) -> (xR,yB) -> (xR,yT) -> (xL,yT)\n    cout << ansX1 << ' ' << ansY1 << '\\n';\n    cout << ansX2 << ' ' << ansY1 << '\\n';\n    cout << ansX2 << ' ' << ansY2 << '\\n';\n    cout << ansX1 << ' ' << ansY2 << '\\n';\n\n    return 0;\n}","ahc040":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct SplitMix64 {\n    uint64_t x;\n    explicit SplitMix64(uint64_t seed) : x(seed) {}\n    uint64_t next_u64() {\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 next_int(int l, int r) {\n        return l + (int)(next_u64() % (uint64_t)(r - l + 1));\n    }\n    double next_double() {\n        // [0,1)\n        return (next_u64() >> 11) * (1.0 / 9007199254740992.0);\n    }\n};\n\nstatic inline vector<int> bestRotForRowChain(const vector<long long>& wprime,\n                                              const vector<long long>& hprime) {\n    int N = (int)wprime.size();\n    // orientation 0: (w=w', h=h')\n    // orientation 1: (w=h', h=w')\n    vector<long long> h0(N), w0(N), h1(N), w1(N);\n    for (int i = 0; i < N; i++) {\n        w0[i] = wprime[i];\n        h0[i] = hprime[i];\n        w1[i] = hprime[i];\n        h1[i] = wprime[i];\n    }\n\n    vector<long long> cand;\n    cand.reserve(2 * N);\n    for (int i = 0; i < N; i++) {\n        cand.push_back(h0[i]);\n        cand.push_back(h1[i]);\n    }\n    sort(cand.begin(), cand.end());\n    cand.erase(unique(cand.begin(), cand.end()), cand.end());\n\n    const long long INF = (1LL << 62);\n    long long bestObj = INF;\n    long long bestTh = cand[0];\n\n    for (long long th : cand) {\n        long long sumW = 0;\n        bool ok = true;\n        for (int i = 0; i < N; i++) {\n            long long bestW = INF;\n            if (h0[i] <= th) bestW = min(bestW, w0[i]);\n            if (h1[i] <= th) bestW = min(bestW, w1[i]);\n            if (bestW == INF) { ok = false; break; }\n            sumW += bestW;\n        }\n        if (!ok) continue;\n        long long obj = sumW + th; // W + H upper-bounded by this th\n        if (obj < bestObj) {\n            bestObj = obj;\n            bestTh = th;\n        }\n    }\n\n    vector<int> rot(N, 0);\n    for (int i = 0; i < N; i++) {\n        long long bestW = INF;\n        int bestR = 0;\n        if (h0[i] <= bestTh) {\n            bestW = w0[i];\n            bestR = 0;\n        }\n        if (h1[i] <= bestTh) {\n            if (w1[i] < bestW) {\n                bestW = w1[i];\n                bestR = 1;\n            }\n        }\n        rot[i] = bestR;\n    }\n    return rot;\n}\n\nstatic inline vector<int> bestRotForColChain(const vector<long long>& wprime,\n                                              const vector<long long>& hprime) {\n    int N = (int)wprime.size();\n    // orientation 0: (w=w', h=h')\n    // orientation 1: (w=h', h=w')\n    vector<long long> h0(N), w0(N), h1(N), w1(N);\n    for (int i = 0; i < N; i++) {\n        w0[i] = wprime[i];\n        h0[i] = hprime[i];\n        w1[i] = hprime[i];\n        h1[i] = wprime[i];\n    }\n\n    vector<long long> cand;\n    cand.reserve(2 * N);\n    for (int i = 0; i < N; i++) {\n        cand.push_back(w0[i]);\n        cand.push_back(w1[i]);\n    }\n    sort(cand.begin(), cand.end());\n    cand.erase(unique(cand.begin(), cand.end()), cand.end());\n\n    const long long INF = (1LL << 62);\n    long long bestObj = INF;\n    long long bestTh = cand[0];\n\n    for (long long th : cand) {\n        long long sumH = 0;\n        bool ok = true;\n        for (int i = 0; i < N; i++) {\n            long long bestH = INF;\n            if (w0[i] <= th) bestH = min(bestH, h0[i]);\n            if (w1[i] <= th) bestH = min(bestH, h1[i]);\n            if (bestH == INF) { ok = false; break; }\n            sumH += bestH;\n        }\n        if (!ok) continue;\n        long long obj = sumH + th; // H + W upper-bounded by this th\n        if (obj < bestObj) {\n            bestObj = obj;\n            bestTh = th;\n        }\n    }\n\n    vector<int> rot(N, 0);\n    for (int i = 0; i < N; i++) {\n        long long bestH = INF;\n        int bestR = 0;\n        if (w0[i] <= bestTh) {\n            bestH = h0[i];\n            bestR = 0;\n        }\n        if (w1[i] <= bestTh) {\n            if (h1[i] < bestH) {\n                bestH = h1[i];\n                bestR = 1;\n            }\n        }\n        rot[i] = bestR;\n    }\n    return rot;\n}\n\nstatic inline long long predictedRowObj(const vector<long long>& wprime,\n                                          const vector<long long>& hprime,\n                                          const vector<int>& rot) {\n    long long W = 0;\n    long long H = 0;\n    int N = (int)wprime.size();\n    for (int i = 0; i < N; i++) {\n        if (rot[i] == 0) {\n            W += wprime[i];\n            H = max(H, hprime[i]);\n        } else {\n            W += hprime[i];\n            H = max(H, wprime[i]);\n        }\n    }\n    return W + H;\n}\n\nstatic inline long long predictedColObj(const vector<long long>& wprime,\n                                          const vector<long long>& hprime,\n                                          const vector<int>& rot) {\n    long long W = 0;\n    long long H = 0;\n    int N = (int)wprime.size();\n    for (int i = 0; i < N; i++) {\n        if (rot[i] == 0) {\n            W = max(W, wprime[i]);\n            H += hprime[i];\n        } else {\n            W = max(W, hprime[i]);\n            H += wprime[i];\n        }\n    }\n    return W + H;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, T;\n    long long sigma;\n    cin >> N >> T >> sigma;\n    vector<long long> wprime(N), hprime(N);\n    for (int i = 0; i < N; i++) cin >> wprime[i] >> hprime[i];\n\n    // Seed from input content for determinism per test instance.\n    uint64_t seed = 88172645463325252ULL;\n    for (int i = 0; i < N; i++) {\n        seed ^= (uint64_t)(wprime[i] + 1000003LL * hprime[i] + (i + 1) * 10007LL);\n        seed *= 1099511628211ULL;\n    }\n    seed ^= (uint64_t)N * 10000019ULL ^ (uint64_t)T * 1000003ULL ^ (uint64_t)sigma;\n    SplitMix64 rng(seed);\n\n    auto rotRow = bestRotForRowChain(wprime, hprime);\n    auto rotCol = bestRotForColChain(wprime, hprime);\n\n    long long predRow = predictedRowObj(wprime, hprime, rotRow);\n    long long predCol = predictedColObj(wprime, hprime, rotCol);\n\n    vector<char> dirRow(N, 'U');\n    vector<char> dirCol(N, 'L');\n\n    vector<char> bestDir;\n    vector<int> bestRot;\n\n    // Candidate list for the first few turns.\n    vector<pair<vector<char>, vector<int>>> initial;\n    initial.reserve(10);\n\n    if (predRow <= predCol) initial.push_back({dirRow, rotRow});\n    else initial.push_back({dirCol, rotCol});\n    if (predRow <= predCol) initial.push_back({dirCol, rotCol});\n    else initial.push_back({dirRow, rotRow});\n\n    auto chooseRotByDir = [&](int i, char d) -> int {\n        // d='U' -> try minimize width; d='L' -> try minimize height\n        long long w0 = wprime[i], h0 = hprime[i];\n        long long w1 = hprime[i], h1 = wprime[i];\n        if (d == 'U') {\n            return (w1 < w0) ? 1 : 0;\n        } else {\n            return (h1 < h0) ? 1 : 0;\n        }\n    };\n\n    int initExtra = min(T, 6) - (int)initial.size();\n    for (int k = 0; k < initExtra; k++) {\n        vector<char> dir(N);\n        vector<int> rot(N);\n        for (int i = 0; i < N; i++) {\n            dir[i] = (rng.next_int(0, 1) == 0 ? 'U' : 'L');\n            rot[i] = chooseRotByDir(i, dir[i]);\n            if (rng.next_int(0, 99) < 25) rot[i] ^= 1; // some randomness\n        }\n        initial.push_back({dir, rot});\n    }\n\n    auto buildOutput = [&](const vector<char>& dir, const vector<int>& rot) -> string {\n        string out;\n        out.reserve((size_t)N * 20);\n        out += to_string(N);\n        out += '\\n';\n        for (int i = 0; i < N; i++) {\n            out += to_string(i);\n            out += ' ';\n            out += to_string(rot[i]);\n            out += ' ';\n            out += dir[i];\n            out += ' ';\n            out += to_string(i == 0 ? -1 : i - 1);\n            out += '\\n';\n        }\n        return out;\n    };\n\n    long long bestMeas = (1LL << 62);\n    bool hasBest = false;\n\n    vector<char> currentDir, baseDir;\n    vector<int> currentRot, baseRot;\n\n    for (int t = 0; t < T; t++) {\n        vector<char> dir;\n        vector<int> rot;\n\n        if (t < (int)initial.size()) {\n            dir = initial[t].first;\n            rot = initial[t].second;\n        } else {\n            // Mutate around best; occasional mutation around the two baselines to avoid stagnation.\n            int pick = rng.next_int(0, 9);\n            if (!hasBest) {\n                dir = dirRow;\n                rot = rotRow;\n            } else if (pick == 0) {\n                dir = dirCol;\n                rot = rotCol;\n            } else if (pick <= 2) {\n                dir = dirRow;\n                rot = rotRow;\n            } else {\n                dir = bestDir;\n                rot = bestRot;\n            }\n\n            int m = (t < T / 3 ? 2 : 1);\n            for (int rep = 0; rep < m; rep++) {\n                int i = rng.next_int(0, N - 1);\n                if (rng.next_int(0, 1) == 0) {\n                    // flip direction\n                    dir[i] = (dir[i] == 'U' ? 'L' : 'U');\n                    if (rng.next_int(0, 99) < 70) {\n                        rot[i] = chooseRotByDir(i, dir[i]);\n                    }\n                } else {\n                    // flip rotation\n                    rot[i] ^= 1;\n                    if (rng.next_int(0, 99) < 30) {\n                        rot[i] = chooseRotByDir(i, dir[i]);\n                    }\n                }\n            }\n        }\n\n        cout << buildOutput(dir, rot) << flush;\n\n        long long Wm, Hm;\n        cin >> Wm >> Hm;\n        long long meas = Wm + Hm;\n\n        if (!hasBest || meas < bestMeas) {\n            hasBest = true;\n            bestMeas = meas;\n            bestDir = dir;\n            bestRot = rot;\n        }\n    }\n\n    return 0;\n}","ahc041":"#include <bits/stdc++.h>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, H;\n    cin >> N >> M >> H;\n    vector<long long> A(N);\n    for (int i = 0; i < N; i++) cin >> A[i];\n\n    vector<vector<int>> g(N);\n    for (int i = 0; i < M; i++) {\n        int u, v;\n        cin >> u >> v;\n        g[u].push_back(v);\n        g[v].push_back(u);\n    }\n    // coordinates are irrelevant for this heuristic\n    for (int i = 0; i < N; i++) {\n        int x, y;\n        cin >> x >> y;\n    }\n\n    using Clock = chrono::steady_clock;\n    auto t0 = Clock::now();\n    const double TL = 1.85; // seconds (safety margin)\n\n    mt19937 rng((uint32_t)chrono::steady_clock::now().time_since_epoch().count());\n\n    vector<int> bestParent(N, -1);\n    long long bestScore = LLONG_MIN;\n\n    vector<char> assigned(N);\n    vector<int> parent(N), depthv(N);\n\n    // Reusable BFS helpers\n    vector<int> seen(N, 0), dist(N, 0);\n    int timer = 1;\n\n    auto eval_component_score = [&](int s) -> long long {\n        // BFS inside currently-unassigned vertices only (including s)\n        timer++;\n        queue<int> q;\n        seen[s] = timer;\n        dist[s] = 0;\n        long long score = A[s]; // (0+1)*A[s]\n        q.push(s);\n\n        while (!q.empty()) {\n            int x = q.front(); q.pop();\n            int dx = dist[x];\n            if (dx == H) continue;\n            for (int y : g[x]) {\n                if (assigned[y]) continue; // blocked by already assigned vertices\n                if (seen[y] == timer) continue;\n                seen[y] = timer;\n                dist[y] = dx + 1;\n                score += (long long)(dist[y] + 1) * A[y];\n                q.push(y);\n            }\n        }\n        return score;\n    };\n\n    auto claim_component = [&](int s) {\n        // Build BFS tree from s in the induced subgraph of unassigned vertices\n        queue<int> q;\n        assigned[s] = 1;\n        parent[s] = -1;\n        depthv[s] = 0;\n        q.push(s);\n\n        while (!q.empty()) {\n            int x = q.front(); q.pop();\n            if (depthv[x] == H) continue;\n            for (int y : g[x]) {\n                if (!assigned[y]) {\n                    assigned[y] = 1;\n                    parent[y] = x;\n                    depthv[y] = depthv[x] + 1;\n                    q.push(y);\n                }\n            }\n        }\n    };\n\n    int attempts = 8;\n    for (int it = 0; it < attempts; it++) {\n        double elapsed = chrono::duration<double>(Clock::now() - t0).count();\n        if (elapsed > TL) break;\n\n        fill(assigned.begin(), assigned.end(), 0);\n        vector<int> curParent(N, -1);\n        vector<int> curDepth(N, -1);\n\n        long long totalScore = 0;\n\n        // Greedy forest construction\n        while (true) {\n            int start = -1;\n            // collect unassigned\n            int unassigned_cnt = 0;\n            for (int i = 0; i < N; i++) if (!assigned[i]) unassigned_cnt++;\n            if (unassigned_cnt == 0) break;\n\n            // find min-A unassigned vertex (always include it)\n            long long minA = (1LL<<60);\n            int minv = -1;\n            for (int i = 0; i < N; i++) {\n                if (!assigned[i] && A[i] < minA) {\n                    minA = A[i];\n                    minv = i;\n                }\n            }\n\n            // sample candidates\n            const int KCAND = 10;\n            vector<int> unassigned_list;\n            unassigned_list.reserve(unassigned_cnt);\n            for (int i = 0; i < N; i++) if (!assigned[i]) unassigned_list.push_back(i);\n\n            int K = min(KCAND, (int)unassigned_list.size());\n            vector<int> cands;\n            cands.push_back(minv);\n\n            // random distinct samples\n            uniform_int_distribution<int> distIdx(0, (int)unassigned_list.size() - 1);\n            unordered_set<int> used;\n            used.reserve(K * 2);\n            used.insert(minv);\n\n            while ((int)cands.size() < K) {\n                int v = unassigned_list[distIdx(rng)];\n                if (!used.count(v)) {\n                    used.insert(v);\n                    cands.push_back(v);\n                }\n            }\n\n            // choose best candidate by exact component score (within remaining unassigned subgraph)\n            long long bestCandScore = LLONG_MIN;\n            int bestCand = -1;\n            for (int c : cands) {\n                long long sc = eval_component_score(c);\n                if (sc > bestCandScore) {\n                    bestCandScore = sc;\n                    bestCand = c;\n                } else if (sc == bestCandScore) {\n                    // tie-break: smaller A (shallower root for good vertices), then random\n                    if (A[c] < A[bestCand] || (A[c] == A[bestCand] && (rng() & 1))) {\n                        bestCand = c;\n                    }\n                }\n            }\n\n            // Claim that component and add its attractiveness\n            // (We can reuse eval_component_score(bestCand) for exact score as well)\n            long long compScore = eval_component_score(bestCand);\n\n            // Apply BFS claim\n            // We need to write into curParent/curDepth\n            // temporarily use global parent/depthv\n            // (to keep code simple, claim_component writes into parent/depthv/assigned)\n            // First, map global parent/depthv into cur arrays after claim.\n            claim_component(bestCand);\n\n            for (int i = 0; i < N; i++) {\n                if (assigned[i]) { // assigned can only grow; but we need to copy newly assigned nodes.\n                    // Avoid O(N) copying each iteration by copying after BFS would be better,\n                    // but N=1000, iterations are limited; still fine.\n                    curParent[i] = parent[i];\n                    curDepth[i] = depthv[i];\n                }\n            }\n            totalScore += compScore;\n        }\n\n        if (totalScore > bestScore) {\n            bestScore = totalScore;\n            // Ensure bestParent is filled from the last attempt's curParent\n            // We must output a forest for all vertices; curParent has values for assigned vertices.\n            // Copy curParent into bestParent (curParent is already for full N at end).\n            // For correctness, just rebuild by running a final claim is unnecessary;\n            // curParent is maintained for assigned vertices; by the end all vertices are assigned.\n            // So copy.\n            // Note: curParent wasn't stored outside loop scope; reconstruct by running again would be redundant.\n            // We'll just re-run the attempt? Instead, store curParent/best immediately in the loop.\n        }\n    }\n\n    // The loop above updates bestScore but doesn't store bestParent due to scope.\n    // Re-run once more but this time keep best forest explicitly.\n    // (Still fast enough.)\n    bestScore = LLONG_MIN;\n    mt19937 rng2((uint32_t)chrono::steady_clock::now().time_since_epoch().count() ^ 0x9e3779b9);\n\n    for (int it = 0; it < attempts; it++) {\n        double elapsed = chrono::duration<double>(Clock::now() - t0).count();\n        if (elapsed > TL) break;\n\n        fill(assigned.begin(), assigned.end(), 0);\n        vector<int> curParent(N, -1);\n        vector<int> curDepth(N, -1);\n\n        long long totalScore = 0;\n\n        while (true) {\n            int unassigned_cnt = 0;\n            for (int i = 0; i < N; i++) if (!assigned[i]) unassigned_cnt++;\n            if (unassigned_cnt == 0) break;\n\n            long long minA = (1LL<<60);\n            int minv = -1;\n            for (int i = 0; i < N; i++) {\n                if (!assigned[i] && A[i] < minA) {\n                    minA = A[i];\n                    minv = i;\n                }\n            }\n\n            const int KCAND = 10;\n            vector<int> unassigned_list;\n            unassigned_list.reserve(unassigned_cnt);\n            for (int i = 0; i < N; i++) if (!assigned[i]) unassigned_list.push_back(i);\n\n            int K = min(KCAND, (int)unassigned_list.size());\n            vector<int> cands;\n            cands.push_back(minv);\n\n            unordered_set<int> used;\n            used.reserve(K * 2);\n            used.insert(minv);\n\n            uniform_int_distribution<int> distIdx(0, (int)unassigned_list.size() - 1);\n            while ((int)cands.size() < K) {\n                int v = unassigned_list[distIdx(rng2)];\n                if (!used.count(v)) {\n                    used.insert(v);\n                    cands.push_back(v);\n                }\n            }\n\n            long long bestCandScore = LLONG_MIN;\n            int bestCand = -1;\n            for (int c : cands) {\n                long long sc = eval_component_score(c);\n                if (sc > bestCandScore) {\n                    bestCandScore = sc;\n                    bestCand = c;\n                } else if (sc == bestCandScore) {\n                    if (A[c] < A[bestCand] || (A[c] == A[bestCand] && (rng2() & 1))) {\n                        bestCand = c;\n                    }\n                }\n            }\n\n            long long compScore = eval_component_score(bestCand);\n            claim_component(bestCand);\n\n            // Copy newly assigned nodes into curParent/curDepth\n            for (int i = 0; i < N; i++) {\n                if (assigned[i]) {\n                    curParent[i] = parent[i];\n                    curDepth[i] = depthv[i];\n                }\n            }\n            totalScore += compScore;\n        }\n\n        if (totalScore > bestScore) {\n            bestScore = totalScore;\n            bestParent = curParent;\n        }\n    }\n\n    // Output parent pointers\n    for (int i = 0; i < N; i++) {\n        cout << bestParent[i] << (i + 1 == N ? '\\n' : ' ');\n    }\n    return 0;\n}","ahc042":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int INF = 1e9;\n\nstruct Candidate {\n    vector<int> upLen, downLen, leftLen, rightLen;\n    long long T = (1LL<<60);\n    bool covered = false;\n};\n\nstruct OniCell {\n    int r, c;\n};\n\nenum Dir { UP=0, DOWN=1, LEFT=2, RIGHT=3 };\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<vector<char>> fuku(N, vector<char>(N, 0));\n    vector<OniCell> oni;\n    oni.reserve(2*N);\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (C[i][j] == 'o') fuku[i][j] = 1;\n            else if (C[i][j] == 'x') {\n                oniId[i][j] = (int)oni.size();\n                oni.push_back({i,j});\n            }\n        }\n    }\n\n    int M = (int)oni.size(); // should be 2N\n    // Precompute max safe lengths for each line-direction.\n    // upLen[j] can be at most number of rows before first fuku in column j.\n    // downLen[j] can be at most number of rows after last fuku in column j.\n    vector<int> maxUp(N), maxDown(N), maxLeft(N), maxRight(N);\n\n    for (int j = 0; j < N; j++) {\n        int first = N, last = -1;\n        for (int i = 0; i < N; i++) {\n            if (fuku[i][j]) {\n                first = min(first, i);\n                last = max(last, i);\n            }\n        }\n        maxUp[j] = first; // L <= first\n        maxDown[j] = (last == -1 ? N : (N - 1 - last)); // L <= N-1-last\n    }\n    for (int i = 0; i < N; i++) {\n        int first = N, last = -1;\n        for (int j = 0; j < N; j++) {\n            if (fuku[i][j]) {\n                first = min(first, j);\n                last = max(last, j);\n            }\n        }\n        maxLeft[i] = first; // L <= first\n        maxRight[i] = (last == -1 ? N : (N - 1 - last)); // L <= N-1-last\n    }\n\n    auto allCovered = [&](const Candidate& cand) -> bool {\n        for (int id = 0; id < M; id++) {\n            int i = oni[id].r, j = oni[id].c;\n            bool ok =\n                (i < cand.upLen[j]) ||\n                (i >= N - cand.downLen[j]) ||\n                (j < cand.leftLen[i]) ||\n                (j >= N - cand.rightLen[i]);\n            if (!ok) return false;\n        }\n        return true;\n    };\n\n    auto computeT = [&](const Candidate& cand) -> long long {\n        long long sum = 0;\n        for (int j = 0; j < N; j++) sum += cand.upLen[j] + cand.downLen[j];\n        for (int i = 0; i < N; i++) sum += cand.leftLen[i] + cand.rightLen[i];\n        return 2LL * sum;\n    };\n\n    auto prune = [&](Candidate cand, const vector<int>& orderUpDownLeftRight) -> Candidate {\n        // Local pruning: repeatedly try to decrease each variable by 1 if coverage remains.\n        // orderUpDownLeftRight encodes which variable index to try:\n        //   0..N-1: UP col\n        //   N..2N-1: DOWN col\n        //   2N..3N-1: LEFT row\n        //   3N..4N-1: RIGHT row\n        bool changed = true;\n        while (changed) {\n            changed = false;\n            for (int idx : orderUpDownLeftRight) {\n                auto canSet = [&](int newLen) -> bool {\n                    int before = newLen + 0; (void)before;\n                    // set temporarily and check coverage\n                    Candidate tmp = cand;\n                    int d = idx / N;\n                    int pos = idx % N;\n                    if (d == 0) tmp.upLen[pos] = newLen;\n                    else if (d == 1) tmp.downLen[pos] = newLen;\n                    else if (d == 2) tmp.leftLen[pos] = newLen;\n                    else tmp.rightLen[pos] = newLen;\n                    return allCovered(tmp);\n                };\n\n                int d = idx / N;\n                int pos = idx % N;\n                int curLen = 0;\n                if (d == 0) curLen = cand.upLen[pos];\n                else if (d == 1) curLen = cand.downLen[pos];\n                else if (d == 2) curLen = cand.leftLen[pos];\n                else curLen = cand.rightLen[pos];\n\n                while (curLen > 0) {\n                    int newLen = curLen - 1;\n                    if (!canSet(newLen)) break;\n                    curLen = newLen;\n                    if (d == 0) cand.upLen[pos] = newLen;\n                    else if (d == 1) cand.downLen[pos] = newLen;\n                    else if (d == 2) cand.leftLen[pos] = newLen;\n                    else cand.rightLen[pos] = newLen;\n                    changed = true;\n                }\n            }\n        }\n        cand.T = computeT(cand);\n        cand.covered = allCovered(cand);\n        return cand;\n    };\n\n    // Baseline: for each Oni, pick cheapest safe direction; then group by maximum required length.\n    auto baselineCandidate = [&]() -> Candidate {\n        Candidate cand;\n        cand.upLen.assign(N, 0);\n        cand.downLen.assign(N, 0);\n        cand.leftLen.assign(N, 0);\n        cand.rightLen.assign(N, 0);\n\n        for (int id = 0; id < M; id++) {\n            int i = oni[id].r, j = oni[id].c;\n            // required lengths\n            int reqU = (i+1 <= maxUp[j] ? i+1 : INF);\n            int reqD = (N-i <= maxDown[j] ? (N-i) : INF);\n            int reqL = (j+1 <= maxLeft[i] ? (j+1) : INF);\n            int reqR = (N-j <= maxRight[i] ? (N-j) : INF);\n\n            int best = min({reqU, reqD, reqL, reqR});\n            if (best == INF) {\n                // Should never happen due to guarantee.\n                // Fallback: do nothing here.\n                continue;\n            }\n            // tie-break order: U, D, L, R\n            if (reqU == best) cand.upLen[j] = max(cand.upLen[j], reqU);\n            else if (reqD == best) cand.downLen[j] = max(cand.downLen[j], reqD);\n            else if (reqL == best) cand.leftLen[i] = max(cand.leftLen[i], reqL);\n            else cand.rightLen[i] = max(cand.rightLen[i], reqR);\n        }\n\n        cand.T = computeT(cand);\n        cand.covered = allCovered(cand);\n        // Prune with a fixed order\n        vector<int> order;\n        order.reserve(4*N);\n        for (int idx = 0; idx < 4*N; idx++) order.push_back(idx);\n        cand = prune(cand, order);\n        return cand;\n    };\n\n    auto greedyAttempt = [&](int variant, std::mt19937& rng) -> Candidate {\n        // variant controls evaluation; all greedy attempts end with pruning.\n        vector<int> upLen(N,0), downLen(N,0), leftLen(N,0), rightLen(N,0);\n        vector<char> covered(M, 0);\n        int uncovered = M;\n\n        auto curLen = [&](Dir dir, int line) -> int {\n            if (dir == UP) return upLen[line];\n            if (dir == DOWN) return downLen[line];\n            if (dir == LEFT) return leftLen[line];\n            return rightLen[line];\n        };\n        auto& lenRef = [&](Dir dir, int line) -> int& {\n            if (dir == UP) return upLen[line];\n            if (dir == DOWN) return downLen[line];\n            if (dir == LEFT) return leftLen[line];\n            return rightLen[line];\n        };\n\n        auto computeGain = [&](Dir dir, int line, int newLen, int cur) -> int {\n            // gain = number of uncovered Oni newly removed by increasing cur -> newLen\n            int gain = 0;\n            if (cur == newLen) return 0;\n\n            if (dir == UP) {\n                int j = line;\n                for (int r = cur; r < newLen; r++) {\n                    int id = oniId[r][j];\n                    if (id != -1 && !covered[id]) gain++;\n                }\n            } else if (dir == DOWN) {\n                int j = line;\n                // newly included rows: [N-newLen, N-cur-1]\n                for (int r = N - newLen; r < N - cur; r++) {\n                    int id = oniId[r][j];\n                    if (id != -1 && !covered[id]) gain++;\n                }\n            } else if (dir == LEFT) {\n                int i = line;\n                for (int c = cur; c < newLen; c++) {\n                    int id = oniId[i][c];\n                    if (id != -1 && !covered[id]) gain++;\n                }\n            } else { // RIGHT\n                int i = line;\n                for (int c = N - newLen; c < N - cur; c++) {\n                    int id = oniId[i][c];\n                    if (id != -1 && !covered[id]) gain++;\n                }\n            }\n            return gain;\n        };\n\n        auto applyExtend = [&](Dir dir, int line, int newLen) {\n            int cur = curLen(dir, line);\n            if (newLen <= cur) return;\n            // Mark all newly covered Oni\n            if (dir == UP) {\n                int j = line;\n                for (int r = cur; r < newLen; r++) {\n                    int id = oniId[r][j];\n                    if (id != -1 && !covered[id]) {\n                        covered[id] = 1;\n                        uncovered--;\n                    }\n                }\n            } else if (dir == DOWN) {\n                int j = line;\n                for (int r = N - newLen; r < N - cur; r++) {\n                    int id = oniId[r][j];\n                    if (id != -1 && !covered[id]) {\n                        covered[id] = 1;\n                        uncovered--;\n                    }\n                }\n            } else if (dir == LEFT) {\n                int i = line;\n                for (int c = cur; c < newLen; c++) {\n                    int id = oniId[i][c];\n                    if (id != -1 && !covered[id]) {\n                        covered[id] = 1;\n                        uncovered--;\n                    }\n                }\n            } else {\n                int i = line;\n                for (int c = N - newLen; c < N - cur; c++) {\n                    int id = oniId[i][c];\n                    if (id != -1 && !covered[id]) {\n                        covered[id] = 1;\n                        uncovered--;\n                    }\n                }\n            }\n            lenRef(dir, line) = newLen;\n        };\n\n        struct Action {\n            Dir dir;\n            int line;\n            int req;\n            int gain;\n            long long costInc;\n            long double val;\n        };\n\n        while (uncovered > 0) {\n            long double bestVal = -1e100;\n            long long bestCost = (1LL<<60);\n            vector<Action> ties;\n\n            for (int id = 0; id < M; id++) {\n                if (covered[id]) continue;\n                int i = oni[id].r, j = oni[id].c;\n\n                // UP: req = i+1\n                {\n                    int req = i + 1;\n                    int cur = upLen[j];\n                    if (req <= maxUp[j] && cur < req) {\n                        int gain = computeGain(UP, j, req, cur);\n                        long long costInc = 2LL * (req - cur);\n                        long double val;\n                        if (variant == 0) val = (long double)gain / (long double)costInc;\n                        else if (variant == 1) val = (long double)gain * 1000.0L - (long double)costInc;\n                        else val = (long double)gain * gain / (long double)costInc;\n                        Action a{UP, j, req, gain, costInc, val};\n                        if (val > bestVal + 1e-15L) {\n                            bestVal = val;\n                            bestCost = costInc;\n                            ties.clear();\n                            ties.push_back(a);\n                        } else if (fabsl(val - bestVal) <= 1e-15L) {\n                            if (costInc < bestCost) {\n                                bestCost = costInc;\n                                ties.clear();\n                                ties.push_back(a);\n                            } else if (costInc == bestCost) {\n                                ties.push_back(a);\n                            } else {\n                                ties.push_back(a); // keep; tie list will be pruned by random pick\n                            }\n                        }\n                    }\n                }\n                // DOWN: req = N-i\n                {\n                    int req = N - i;\n                    int cur = downLen[j];\n                    if (req <= maxDown[j] && cur < req) {\n                        int gain = computeGain(DOWN, j, req, cur);\n                        long long costInc = 2LL * (req - cur);\n                        long double val;\n                        if (variant == 0) val = (long double)gain / (long double)costInc;\n                        else if (variant == 1) val = (long double)gain * 1000.0L - (long double)costInc;\n                        else val = (long double)gain * gain / (long double)costInc;\n                        Action a{DOWN, j, req, gain, costInc, val};\n                        if (val > bestVal + 1e-15L) {\n                            bestVal = val;\n                            bestCost = costInc;\n                            ties.clear();\n                            ties.push_back(a);\n                        } else if (fabsl(val - bestVal) <= 1e-15L) {\n                            if (costInc < bestCost) {\n                                bestCost = costInc;\n                                ties.clear();\n                                ties.push_back(a);\n                            } else if (costInc == bestCost) {\n                                ties.push_back(a);\n                            } else {\n                                ties.push_back(a);\n                            }\n                        }\n                    }\n                }\n                // LEFT: req = j+1\n                {\n                    int req = j + 1;\n                    int cur = leftLen[i];\n                    if (req <= maxLeft[i] && cur < req) {\n                        int gain = computeGain(LEFT, i, req, cur);\n                        long long costInc = 2LL * (req - cur);\n                        long double val;\n                        if (variant == 0) val = (long double)gain / (long double)costInc;\n                        else if (variant == 1) val = (long double)gain * 1000.0L - (long double)costInc;\n                        else val = (long double)gain * gain / (long double)costInc;\n                        Action a{LEFT, i, req, gain, costInc, val};\n                        if (val > bestVal + 1e-15L) {\n                            bestVal = val;\n                            bestCost = costInc;\n                            ties.clear();\n                            ties.push_back(a);\n                        } else if (fabsl(val - bestVal) <= 1e-15L) {\n                            if (costInc < bestCost) {\n                                bestCost = costInc;\n                                ties.clear();\n                                ties.push_back(a);\n                            } else if (costInc == bestCost) {\n                                ties.push_back(a);\n                            } else {\n                                ties.push_back(a);\n                            }\n                        }\n                    }\n                }\n                // RIGHT: req = N-j\n                {\n                    int req = N - j;\n                    int cur = rightLen[i];\n                    if (req <= maxRight[i] && cur < req) {\n                        int gain = computeGain(RIGHT, i, req, cur);\n                        long long costInc = 2LL * (req - cur);\n                        long double val;\n                        if (variant == 0) val = (long double)gain / (long double)costInc;\n                        else if (variant == 1) val = (long double)gain * 1000.0L - (long double)costInc;\n                        else val = (long double)gain * gain / (long double)costInc;\n                        Action a{RIGHT, i, req, gain, costInc, val};\n                        if (val > bestVal + 1e-15L) {\n                            bestVal = val;\n                            bestCost = costInc;\n                            ties.clear();\n                            ties.push_back(a);\n                        } else if (fabsl(val - bestVal) <= 1e-15L) {\n                            if (costInc < bestCost) {\n                                bestCost = costInc;\n                                ties.clear();\n                                ties.push_back(a);\n                            } else if (costInc == bestCost) {\n                                ties.push_back(a);\n                            } else {\n                                ties.push_back(a);\n                            }\n                        }\n                    }\n                }\n            }\n\n            // Choose among ties\n            Action chosen = ties[0];\n            if (!ties.empty()) {\n                if (variant == 0) {\n                    // random among best-value ties\n                    std::uniform_int_distribution<int> dist(0, (int)ties.size()-1);\n                    chosen = ties[dist(rng)];\n                } else {\n                    // deterministic: smallest costInc then largest gain\n                    chosen = *min_element(ties.begin(), ties.end(), [&](const Action& a, const Action& b){\n                        if (a.costInc != b.costInc) return a.costInc < b.costInc;\n                        if (a.gain != b.gain) return a.gain > b.gain;\n                        return a.req < b.req;\n                    });\n                }\n            }\n            applyExtend(chosen.dir, chosen.line, chosen.req);\n        }\n\n        Candidate cand;\n        cand.upLen = upLen;\n        cand.downLen = downLen;\n        cand.leftLen = leftLen;\n        cand.rightLen = rightLen;\n        cand.T = computeT(cand);\n        cand.covered = allCovered(cand);\n\n        // prune\n        vector<int> order;\n        order.reserve(4*N);\n        // fixed order for stability\n        for (int idx = 0; idx < 4*N; idx++) order.push_back(idx);\n        cand = prune(cand, order);\n        return cand;\n    };\n\n    Candidate best = baselineCandidate();\n\n    // Greedy attempts (bounded)\n    // N=20 => T limit is 1600, baseline should already be feasible, but we still improve score.\n    auto tryGreedy = [&](int variant, int tries) {\n        std::mt19937 rng(1234567 + variant*1000);\n        for (int t = 0; t < tries; t++) {\n            Candidate cand = greedyAttempt(variant, rng);\n            long long Tlimit = 4LL * N * N;\n            if (!cand.covered) continue;\n            if (cand.T > Tlimit) continue;\n            if (cand.T < best.T) best = cand;\n            // advance RNG\n            rng();\n        }\n    };\n\n    tryGreedy(0, 18);\n    tryGreedy(1, 6);\n    tryGreedy(2, 6);\n\n    // Output operations according to best lengths.\n    // Ensure within limit\n    long long Tlimit = 4LL * N * N;\n    if (!best.covered || best.T > Tlimit) {\n        // This should not happen; baseline should always be feasible.\n        // As a last resort, just output baseline without further pruning (but we already pruned).\n        best = baselineCandidate();\n    }\n\n    vector<pair<char,int>> ops;\n    ops.reserve((size_t)best.T);\n\n    for (int j = 0; j < N; j++) {\n        int L = best.upLen[j];\n        if (L > 0) {\n            for (int k = 0; k < L; k++) ops.push_back({'U', j});\n            for (int k = 0; k < L; k++) ops.push_back({'D', j});\n        }\n        int R = best.downLen[j];\n        if (R > 0) {\n            for (int k = 0; k < R; k++) ops.push_back({'D', j});\n            for (int k = 0; k < R; k++) ops.push_back({'U', j});\n        }\n    }\n    for (int i = 0; i < N; i++) {\n        int L = best.leftLen[i];\n        if (L > 0) {\n            for (int k = 0; k < L; k++) ops.push_back({'L', i});\n            for (int k = 0; k < L; k++) ops.push_back({'R', i});\n        }\n        int R = best.rightLen[i];\n        if (R > 0) {\n            for (int k = 0; k < R; k++) ops.push_back({'R', i});\n            for (int k = 0; k < R; k++) ops.push_back({'L', i});\n        }\n    }\n\n    if ((long long)ops.size() > Tlimit) {\n        // Should not happen; but safeguard\n        ops.resize((size_t)Tlimit);\n    }\n\n    cout << ops.size() << \"\\n\";\n    for (auto &[ch, p] : ops) {\n        cout << ch << \" \" << p << \"\\n\";\n    }\n    return 0;\n}","ahc044":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic long long calcError(const vector<int>& cnt, const vector<int>& T) {\n    long long e = 0;\n    int N = (int)T.size();\n    for (int i = 0; i < N; i++) e += llabs((long long)cnt[i] - (long long)T[i]);\n    return e;\n}\n\nstatic long long simulateFixed(const vector<int>& a, const vector<int>& b,\n                                const vector<int>& T, vector<int>* cntOut) {\n    int N = (int)T.size();\n    int L = 0; // not passed; we will encode by using T sum outside if needed (not good)\n    (void)L;\n    // We'll pass L via captured globals in lambdas; but to keep function clean, we instead\n    // store L globally.\n    // (See main where we bind L as a static global.)\n    return 0;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    int L;\n    cin >> N >> L;\n    vector<int> T(N);\n    for (int i = 0; i < N; i++) cin >> T[i];\n\n    // We will use arrays to speed simulation.\n    auto simulate = [&](const vector<int>& a, const vector<int>& b, bool needCnt)\n        -> pair<long long, vector<int>> {\n        vector<int> cnt(N, 0);\n        int x = 0;\n        cnt[x] = 1;\n        for (int week = 2; week <= L; week++) {\n            if (cnt[x] & 1) x = a[x];\n            else x = b[x];\n            cnt[x]++;\n        }\n        long long err = calcError(cnt, T);\n        return {err, std::move(cnt)};\n    };\n\n    // Candidate chooser for when a[i] or b[i] is not decided yet.\n    // We pick among top K employees by current \"remaining need\" (rem),\n    // but use weighted randomness to diversify.\n    auto chooseCandidate = [&](const vector<long long>& rem, std::mt19937_64 &rng) -> int {\n        int K = 10;\n        if (K > N) K = N;\n        long long mn = rem[0];\n        for (int i = 1; i < N; i++) mn = min(mn, rem[i]);\n\n        vector<pair<long long,int>> v;\n        v.reserve(N);\n        for (int i = 0; i < N; i++) v.push_back({rem[i], i});\n        nth_element(v.begin(), v.begin() + K, v.end(),\n                    [&](auto &p, auto &q){ return p.first > q.first; });\n        v.resize(K);\n        sort(v.begin(), v.end(), [&](auto &p, auto &q){ return p.first > q.first; });\n\n        long long offset = -mn + 1; // so all weights >= 1\n        long long sumw = 0;\n        for (auto &p : v) sumw += (p.first + offset);\n\n        uniform_int_distribution<long long> dist(1, sumw);\n        long long r = dist(rng);\n        for (auto &p : v) {\n            long long w = p.first + offset;\n            if (r <= w) return p.second;\n            r -= w;\n        }\n        return v.back().second;\n    };\n\n    // Online randomized construction:\n    // - Maintain rem = T - (current used counts)\n    // - During simulation, when we need to leave x on odd/even parity but a[x]/b[x] is unset,\n    //   choose it using rem.\n    auto buildMapping = [&](std::mt19937_64 &rng) -> tuple<long long, vector<int>, vector<int>> {\n        vector<int> a(N, -1), b(N, -1);\n        vector<long long> rem(N);\n        for (int i = 0; i < N; i++) rem[i] = T[i];\n\n        vector<int> cnt(N, 0);\n        int x = 0;\n        cnt[x] = 1;\n        rem[x]--;\n\n        for (int week = 2; week <= L; week++) {\n            if (cnt[x] & 1) { // use a[x]\n                if (a[x] == -1) {\n                    int y = chooseCandidate(rem, rng);\n                    a[x] = y;\n                }\n                x = a[x];\n            } else { // use b[x]\n                if (b[x] == -1) {\n                    int y = chooseCandidate(rem, rng);\n                    b[x] = y;\n                }\n                x = b[x];\n            }\n            cnt[x]++;\n            rem[x]--;\n        }\n\n        for (int i = 0; i < N; i++) {\n            if (a[i] == -1) a[i] = 0;\n            if (b[i] == -1) b[i] = 0;\n        }\n        long long err = calcError(cnt, T);\n        return {err, std::move(a), std::move(b)};\n    };\n\n    // Time control\n    using Clock = std::chrono::steady_clock;\n    auto st = Clock::now();\n    double TIME_LIMIT = 1.85; // seconds\n    auto elapsed = [&]() {\n        return std::chrono::duration<double>(Clock::now() - st).count();\n    };\n\n    std::mt19937_64 rng((uint64_t)chrono::high_resolution_clock::now().time_since_epoch().count());\n\n    long long bestErr = (1LL<<60);\n    vector<int> bestA(N, 0), bestB(N, 0);\n\n    // Multiple randomized builds\n    int tries = 0;\n    while (elapsed() < TIME_LIMIT && tries < 30) {\n        auto [err, a, b] = buildMapping(rng);\n        if (err < bestErr) {\n            bestErr = err;\n            bestA = a;\n            bestB = b;\n        }\n        tries++;\n    }\n\n    // Local search: try changing one edge at a time\n    auto [curErr, curCnt] = simulate(bestA, bestB, true);\n\n    vector<int> idx(N);\n    iota(idx.begin(), idx.end(), 0);\n\n    int saTries = 0;\n    while (elapsed() < TIME_LIMIT * 1.02 && saTries < 40 && bestErr > 0) {\n        // pick i with largest under/over\n        vector<pair<int,int>> dif;\n        dif.reserve(N);\n        for (int i = 0; i < N; i++) dif.push_back({(int)llabs((long long)T[i] - (long long)curCnt[i]), i});\n        sort(dif.begin(), dif.end(), [&](auto &p, auto &q){ return p.first > q.first; });\n        int pickPos = min(10, N-1);\n        int i = dif[uniform_int_distribution<int>(0, pickPos)(rng)].second;\n\n        // residual need\n        vector<pair<int,int>> need; // (residual, j)\n        need.reserve(N);\n        for (int j = 0; j < N; j++) need.push_back({T[j] - curCnt[j], j});\n        sort(need.begin(), need.end(), [&](auto &p, auto &q){ return p.first > q.first; });\n\n        bool changeA = uniform_int_distribution<int>(0,1)(rng) == 0;\n\n        // candidates for new destination: those with largest positive residual\n        vector<int> cand;\n        for (int k = 0; k < min(12, N); k++) cand.push_back(need[k].second);\n\n        vector<int> a2 = bestA, b2 = bestB;\n        // try a few random candidates\n        long long bestLocal = bestErr;\n        int bestNewDest = -1;\n        bool bestLocalIsA = changeA;\n\n        for (int t = 0; t < 4; t++) {\n            int j = cand[uniform_int_distribution<int>(0, (int)cand.size()-1)(rng)];\n            if (changeA) a2[i] = j;\n            else b2[i] = j;\n\n            auto [e2, cnt2] = simulate(a2, b2, true);\n            if (e2 < bestLocal) {\n                bestLocal = e2;\n                bestNewDest = j;\n                bestLocalIsA = changeA;\n                // keep bestA/bestB updates immediately\n                bestA = a2;\n                bestB = b2;\n                curErr = e2;\n                curCnt = std::move(cnt2);\n            }\n\n            // revert for next candidate trial\n            a2 = bestA; b2 = bestB;\n        }\n\n        // if no improvement, just keep going\n        bestErr = min(bestErr, curErr);\n        saTries++;\n    }\n\n    // Output\n    // (We must print N lines of a_i b_i.)\n    for (int i = 0; i < N; i++) {\n        cout << bestA[i] << ' ' << bestB[i] << \"\\n\";\n    }\n    return 0;\n}","ahc045":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\n\nstatic inline uint64_t morton2d(uint32_t x, uint32_t y) {\n    // x,y in [0, 2^14)\n    uint64_t z = 0;\n    for (uint32_t i = 0; i < 14; i++) {\n        z |= (uint64_t)((x >> i) & 1u) << (2 * i + 1);\n        z |= (uint64_t)((y >> i) & 1u) << (2 * i);\n    }\n    return z;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, Q, L, W;\n    cin >> N >> M >> Q >> L >> W;\n    vector<int> G(M);\n    for (int i = 0; i < M; i++) cin >> G[i];\n\n    vector<int> lx(N), rx(N), ly(N), ry(N);\n    for (int i = 0; i < N; i++) {\n        cin >> lx[i] >> rx[i] >> ly[i] >> ry[i];\n    }\n\n    vector<double> cx(N), cy(N);\n    vector<int> cx_i(N), cy_i(N);\n    for (int i = 0; i < N; i++) {\n        cx_i[i] = (lx[i] + rx[i]) / 2;\n        cy_i[i] = (ly[i] + ry[i]) / 2;\n        cx[i] = 0.5 * (lx[i] + rx[i]);\n        cy[i] = 0.5 * (ly[i] + ry[i]);\n    }\n\n    vector<uint64_t> key(N);\n    for (int i = 0; i < N; i++) key[i] = morton2d((uint32_t)cx_i[i], (uint32_t)cy_i[i]);\n\n    vector<int> cities(N);\n    iota(cities.begin(), cities.end(), 0);\n    sort(cities.begin(), cities.end(), [&](int a, int b) {\n        if (key[a] != key[b]) return key[a] < key[b];\n        return a < b;\n    });\n\n    // Assign consecutive segments, but permute group indices (larger groups get longer contiguous segments).\n    vector<int> orderGroups(M);\n    iota(orderGroups.begin(), orderGroups.end(), 0);\n    sort(orderGroups.begin(), orderGroups.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>> groupCities(M);\n    int ptr = 0;\n    for (int gi : orderGroups) {\n        int sz = G[gi];\n        groupCities[gi].insert(groupCities[gi].end(), cities.begin() + ptr, cities.begin() + ptr + sz);\n        ptr += sz;\n    }\n\n    // Reorder within each group by greedy nearest-neighbor path using midpoint distances.\n    auto dist2 = [&](int a, int b) -> double {\n        double dx = cx[a] - cx[b];\n        double dy = cy[a] - cy[b];\n        return dx * dx + dy * dy;\n    };\n\n    for (int gi = 0; gi < M; gi++) {\n        auto &vec = groupCities[gi];\n        int sz = (int)vec.size();\n        if (sz <= 2) continue;\n\n        // start at smallest morton key in the group\n        int startIdx = 0;\n        for (int i = 1; i < sz; i++) {\n            if (key[vec[i]] < key[vec[startIdx]]) startIdx = i;\n        }\n        vector<char> used(N, 0);\n        vector<int> newOrder;\n        newOrder.reserve(sz);\n\n        int cur = vec[startIdx];\n        for (int it = 0; it < sz; it++) {\n            newOrder.push_back(cur);\n            used[cur] = 1;\n            if (it == sz - 1) break;\n            int best = -1;\n            double bestD = 1e100;\n            for (int v : vec) {\n                if (used[v]) continue;\n                double d = dist2(cur, v);\n                if (d < bestD) {\n                    bestD = d;\n                    best = v;\n                }\n            }\n            cur = best;\n        }\n        vec.swap(newOrder);\n    }\n\n    // Count how many triple queries we'd like to do.\n    vector<int> needTriple(M, 0);\n    long long totalNeed = 0;\n    for (int gi = 0; gi < M; gi++) {\n        int sz = (int)groupCities[gi].size();\n        if (sz >= 3) {\n            needTriple[gi] = (sz - 1) / 2;\n            totalNeed += needTriple[gi];\n        }\n    }\n\n    long long remainingQ = Q;\n\n    vector<vector<pair<int,int>>> roads(M);\n\n    auto addChainEdges = [&](int gi) {\n        auto &vec = groupCities[gi];\n        int sz = (int)vec.size();\n        roads[gi].clear();\n        for (int i = 1; i < sz; i++) {\n            int u = vec[i-1], v = vec[i];\n            if (u > v) swap(u, v);\n            roads[gi].push_back({u, v});\n        }\n        // roads[gi].size() == sz-1\n    };\n\n    // Interactive queries (only if we still have budget).\n    for (int gi = 0; gi < M; gi++) {\n        int sz = (int)groupCities[gi].size();\n        if (sz <= 1) {\n            roads[gi].clear();\n            continue;\n        }\n        if (sz == 2) {\n            int u = groupCities[gi][0], v = groupCities[gi][1];\n            if (u > v) swap(u, v);\n            roads[gi] = {{u, v}};\n            continue;\n        }\n\n        if (needTriple[gi] > 0 && remainingQ < needTriple[gi]) {\n            // Fallback: build a chain without oracle.\n            addChainEdges(gi);\n            continue;\n        }\n\n        auto &vec = groupCities[gi];\n        roads[gi].clear();\n        int i = 0;\n        while (i + 2 < sz) {\n            int a = vec[i], b = vec[i+1], c = vec[i+2];\n\n            // query triple\n            cout << \"? 3 \" << a << \" \" << b << \" \" << c << '\\n' << flush;\n\n            // receive 2 edges\n            for (int t = 0; t < 2; t++) {\n                int u, v;\n                cin >> u >> v;\n                if (u > v) swap(u, v);\n                roads[gi].push_back({u, v});\n            }\n\n            remainingQ--;\n            i += 2;\n        }\n        if (sz % 2 == 0) {\n            int u = vec[sz-2], v = vec[sz-1];\n            if (u > v) swap(u, v);\n            roads[gi].push_back({u, v});\n        }\n        // roads[gi].size() should be sz-1\n    }\n\n    cout << \"!\" << '\\n' << flush;\n\n    for (int gi = 0; gi < M; gi++) {\n        auto &vec = groupCities[gi];\n        for (int i = 0; i < (int)vec.size(); i++) {\n            if (i) cout << ' ';\n            cout << vec[i];\n        }\n        cout << '\\n';\n        for (auto [u, v] : roads[gi]) {\n            cout << u << ' ' << v << '\\n';\n        }\n    }\n    cout << flush;\n    return 0;\n}","ahc046":"#include <bits/stdc++.h>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M;\n    cin >> N >> M;\n    vector<pair<int,int>> p(M);\n    for (int k = 0; k < M; k++) {\n        cin >> p[k].first >> p[k].second;\n    }\n\n    auto dirMove = [&](int fromi, int fromj, int toi, int toj) -> char {\n        if (toi > fromi) return 'D'; // down\n        if (toi < fromi) return 'U'; // up\n        if (toj > fromj) return 'R'; // right\n        return 'L';                  // left\n    };\n\n    struct Act { char a, d; };\n    vector<Act> acts;\n    acts.reserve(2000);\n\n    auto addMove = [&](int &x, int &y, int nx, int ny) {\n        // assumes adjacent\n        int cx = x, cy = y;\n        char d = dirMove(cx, cy, nx, ny);\n        acts.push_back({'M', d});\n        x = nx; y = ny;\n    };\n\n    auto addSlide = [&](int &x, int &y, char d) {\n        acts.push_back({'S', d});\n        if (d == 'U') x = 0;\n        else if (d == 'D') x = N - 1;\n        else if (d == 'L') y = 0;\n        else if (d == 'R') y = N - 1;\n    };\n\n    int x = p[0].first, y = p[0].second;\n\n    // Transition types:\n    // 0: base moves\n    // 1: slide up to row 0 (target must have tx==0)\n    // 2: slide down to row N-1\n    // 3: slide left to col 0\n    // 4: slide right to col N-1\n    for (int k = 1; k < M; k++) {\n        int tx = p[k].first, ty = p[k].second;\n        int dx = tx - x, dy = ty - y;\n\n        int bestType = 0;\n        int bestCost = abs(dx) + abs(dy);\n\n        // slide up: target at top row, and we need to move up at least once (x>0)\n        if (tx == 0 && x > 0) {\n            int cost = abs(dy) + 1; // align col with ty, then slide up\n            if (cost < bestCost) { bestCost = cost; bestType = 1; }\n        }\n        // slide down\n        if (tx == N - 1 && x < N - 1) {\n            int cost = abs(dy) + 1;\n            if (cost < bestCost) { bestCost = cost; bestType = 2; }\n        }\n        // slide left\n        if (ty == 0 && y > 0) {\n            int cost = abs(dx) + 1; // align row with tx, then slide left\n            if (cost < bestCost) { bestCost = cost; bestType = 3; }\n        }\n        // slide right\n        if (ty == N - 1 && y < N - 1) {\n            int cost = abs(dx) + 1;\n            if (cost < bestCost) { bestCost = cost; bestType = 4; }\n        }\n\n        if (bestType == 0) {\n            // Move vertically then horizontally\n            while (x != tx) {\n                int nx = x + (tx > x ? 1 : -1);\n                addMove(x, y, nx, y);\n            }\n            while (y != ty) {\n                int ny = y + (ty > y ? 1 : -1);\n                addMove(x, y, x, ny);\n            }\n        } else if (bestType == 1) {\n            // Slide up to (0, ty)\n            while (y != ty) {\n                int ny = y + (ty > y ? 1 : -1);\n                addMove(x, y, x, ny);\n            }\n            addSlide(x, y, 'U');\n        } else if (bestType == 2) {\n            // Slide down to (N-1, ty)\n            while (y != ty) {\n                int ny = y + (ty > y ? 1 : -1);\n                addMove(x, y, x, ny);\n            }\n            addSlide(x, y, 'D');\n        } else if (bestType == 3) {\n            // Slide left to (tx, 0)\n            while (x != tx) {\n                int nx = x + (tx > x ? 1 : -1);\n                addMove(x, y, nx, y);\n            }\n            addSlide(x, y, 'L');\n        } else { // bestType == 4\n            // Slide right to (tx, N-1)\n            while (x != tx) {\n                int nx = x + (tx > x ? 1 : -1);\n                addMove(x, y, nx, y);\n            }\n            addSlide(x, y, 'R');\n        }\n\n        // Now we should be exactly at target\n        // (Safe-assert for development; remove if desired)\n        // assert(x == tx && y == ty);\n    }\n\n    int limit = 2 * N * M;\n    if ((int)acts.size() > limit) {\n        // Should not happen with this strategy.\n        // Fallback: still output something legal-ish (but better to be safe).\n        // Here we just truncate (not guaranteed legal), so better to abort.\n        cerr << \"Internal error: exceeded action limit\\n\";\n        return 0;\n    }\n\n    for (auto &ac : acts) {\n        cout << ac.a << ' ' << ac.d << \"\\n\";\n    }\n    return 0;\n}"},"2":{"ahc001":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\n\nstruct Company {\n    int x, y;\n    ll r;\n};\n\nstruct Rect {\n    int a, b, c, d; // [a,c) x [b,d)\n};\n\nstruct Cand {\n    int k;\n    ll costAbs; // |areaChild - sumRChild|\n};\n\nstatic double evalScore(const vector<Company>& comp, const vector<Rect>& rects) {\n    int n = (int)comp.size();\n    long double total = 0;\n    for (int i = 0; i < n; i++) {\n        ll s = 1LL * (rects[i].c - rects[i].a) * (rects[i].d - rects[i].b);\n        ll ri = comp[i].r;\n        ll mn = min(ri, s), mx = max(ri, s);\n        long double t = (long double)mn / (long double)mx;\n        long double p = 1.0L - (1.0L - t) * (1.0L - t); // 1-(1-t)^2\n        total += p;\n    }\n    return (double)total;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int n;\n    cin >> n;\n    vector<Company> comp(n);\n    for (int i = 0; i < n; i++) {\n        cin >> comp[i].x >> comp[i].y >> comp[i].r;\n    }\n\n    constexpr int N = 10000;\n    vector<Rect> bestRects(n);\n    double bestScore = -1e100;\n\n    auto startTime = chrono::steady_clock::now();\n\n    uint64_t baseSeed = chrono::steady_clock::now().time_since_epoch().count();\n    std::mt19937_64 rng(baseSeed);\n\n    // Heuristic parameters\n    const int TIME_LIMIT_MS = 4700;\n    const int TOPK = 10;\n    const long double ORI_ALPHA = 6.0L;  // orientation softmax strength\n    const long double K_BETA = 10.0L;    // cut-choice softmax strength\n\n    auto getCandidates = [&](const vector<int>& ids, int lx, int rx, int ly, int ry, bool vertical) -> vector<Cand> {\n        int m = (int)ids.size();\n        vector<Cand> cand;\n        if (m <= 1) return cand;\n\n        ll areaParent = 1LL * (rx - lx) * (ry - ly);\n        if (areaParent <= 0) return cand;\n\n        if (vertical) {\n            if (rx - lx <= 1) return cand;\n\n            vector<int> v = ids;\n            sort(v.begin(), v.end(), [&](int a, int b) { return comp[a].x < comp[b].x; });\n\n            // group by x, store xvals and sumR per group\n            vector<int> xs;\n            vector<ll> sumR;\n            xs.reserve(m);\n            sumR.reserve(m);\n\n            for (int i = 0; i < m; ) {\n                int j = i;\n                int xval = comp[v[i]].x;\n                ll s = 0;\n                while (j < m && comp[v[j]].x == xval) {\n                    s += comp[v[j]].r;\n                    j++;\n                }\n                xs.push_back(xval);\n                sumR.push_back(s);\n                i = j;\n            }\n\n            int G = (int)xs.size();\n            if (G <= 1) return cand;\n\n            // prefix sums by groups\n            vector<ll> pref(G + 1, 0);\n            for (int i = 0; i < G; i++) pref[i + 1] = pref[i] + sumR[i];\n\n            ll height = 1LL * (ry - ly);\n\n            for (int g = 0; g < G - 1; g++) {\n                int uL = xs[g];\n                int uR = xs[g + 1];\n\n                // k integer in [uL+1, uR] gives same split by x<k\n                int k_low = max(lx + 1, uL + 1);\n                int k_high = min(rx - 1, uR);\n                if (k_low > k_high) continue;\n\n                ll leftSum = pref[g + 1]; // groups [0..g]\n                // areaL(k) = (k-lx)*height\n                long double targetWidth = (long double)leftSum / (long double)height;\n                int k_opt = (int)llround((long double)lx + targetWidth);\n\n                auto addK = [&](int k) {\n                    if (k < k_low || k > k_high) return;\n                    ll areaL = 1LL * (k - lx) * height;\n                    ll diff = llabs(areaL - leftSum);\n                    cand.push_back({k, diff});\n                };\n\n                addK(k_opt);\n                addK(k_opt - 1);\n                addK(k_opt + 1);\n                addK(k_low);\n                addK(k_high);\n            }\n\n        } else {\n            if (ry - ly <= 1) return cand;\n\n            vector<int> v = ids;\n            sort(v.begin(), v.end(), [&](int a, int b) { return comp[a].y < comp[b].y; });\n\n            // group by y, store yvals and sumR per group\n            vector<int> ys;\n            vector<ll> sumR;\n            ys.reserve(m);\n            sumR.reserve(m);\n\n            for (int i = 0; i < m; ) {\n                int j = i;\n                int yval = comp[v[i]].y;\n                ll s = 0;\n                while (j < m && comp[v[j]].y == yval) {\n                    s += comp[v[j]].r;\n                    j++;\n                }\n                ys.push_back(yval);\n                sumR.push_back(s);\n                i = j;\n            }\n\n            int G = (int)ys.size();\n            if (G <= 1) return cand;\n\n            // prefix sums by groups\n            vector<ll> pref(G + 1, 0);\n            for (int i = 0; i < G; i++) pref[i + 1] = pref[i] + sumR[i];\n\n            ll width = 1LL * (rx - lx);\n\n            for (int g = 0; g < G - 1; g++) {\n                int uL = ys[g];\n                int uR = ys[g + 1];\n\n                // k integer in [uL+1, uR] gives same split by y<k\n                int k_low = max(ly + 1, uL + 1);\n                int k_high = min(ry - 1, uR);\n                if (k_low > k_high) continue;\n\n                ll bottomSum = pref[g + 1]; // groups [0..g]\n                // areaB(k) = (k-ly)*width\n                long double targetH = (long double)bottomSum / (long double)width;\n                int k_opt = (int)llround((long double)ly + targetH);\n\n                auto addK = [&](int k) {\n                    if (k < k_low || k > k_high) return;\n                    ll areaB = 1LL * (k - ly) * width;\n                    ll diff = llabs(areaB - bottomSum);\n                    cand.push_back({k, diff});\n                };\n\n                addK(k_opt);\n                addK(k_opt - 1);\n                addK(k_opt + 1);\n                addK(k_low);\n                addK(k_high);\n            }\n        }\n\n        if (cand.empty()) return cand;\n        sort(cand.begin(), cand.end(), [&](const Cand& A, const Cand& B) {\n            if (A.costAbs != B.costAbs) return A.costAbs < B.costAbs;\n            return A.k < B.k;\n        });\n\n        // Dedup by k keeping smallest cost\n        vector<Cand> ded;\n        ded.reserve(cand.size());\n        for (auto &c : cand) {\n            if (ded.empty() || ded.back().k != c.k) ded.push_back(c);\n        }\n        return ded;\n    };\n\n    // Main time-based restart loop\n    int it = 0;\n    while (true) {\n        auto now = chrono::steady_clock::now();\n        int elapsed = (int)chrono::duration_cast<chrono::milliseconds>(now - startTime).count();\n        if (elapsed >= TIME_LIMIT_MS) break;\n        it++;\n\n        // per-iteration RNG\n        uint64_t seed = baseSeed ^ (uint64_t)it * 0x9e3779b97f4a7c15ULL;\n        std::mt19937_64 rng2(seed);\n\n        vector<Rect> rects(n);\n\n        function<void(int,int,int,int,const vector<int>&)> build =\n            [&](int lx, int rx, int ly, int ry, const vector<int>& ids) {\n                if ((int)ids.size() == 1) {\n                    int id = ids[0];\n                    rects[id] = Rect{lx, ly, rx, ry};\n                    return;\n                }\n\n                ll areaParent = 1LL * (rx - lx) * (ry - ly);\n\n                auto candV = getCandidates(ids, lx, rx, ly, ry, true);\n                auto candH = getCandidates(ids, lx, rx, ly, ry, false);\n\n                bool chooseV;\n                if (candV.empty()) chooseV = false;\n                else if (candH.empty()) chooseV = true;\n                else {\n                    ll bestV = candV.front().costAbs;\n                    ll bestH = candH.front().costAbs;\n                    long double pV = expl(- (long double)bestV / (long double)(areaParent + 1) * ORI_ALPHA);\n                    long double pH = expl(- (long double)bestH / (long double)(areaParent + 1) * ORI_ALPHA);\n                    long double sum = pV + pH;\n                    if (sum <= 0) chooseV = (bestV <= bestH);\n                    else {\n                        long double u = (long double)(rng2() % 1000000) / 1000000.0L;\n                        chooseV = (u < pV / sum);\n                    }\n                }\n\n                if (chooseV) {\n                    // pick k among top candidates\n                    int top = min<int>(TOPK, (int)candV.size());\n                    vector<Cand> sub(candV.begin(), candV.begin() + top);\n\n                    // softmax over costs\n                    long double sumW = 0;\n                    vector<long double> w(top);\n                    for (int i = 0; i < top; i++) {\n                        w[i] = expl(- (long double)sub[i].costAbs / (long double)(areaParent + 1) * K_BETA);\n                        sumW += w[i];\n                    }\n                    int pick = 0;\n                    if (sumW <= 0) pick = 0;\n                    else {\n                        long double u = (long double)(rng2() % 1000000) / 1000000.0L * sumW;\n                        long double acc = 0;\n                        for (int i = 0; i < top; i++) {\n                            acc += w[i];\n                            if (u <= acc) { pick = i; break; }\n                        }\n                    }\n                    int k = sub[pick].k;\n\n                    vector<int> L, R;\n                    L.reserve(ids.size());\n                    R.reserve(ids.size());\n                    for (int id : ids) (comp[id].x < k ? L : R).push_back(id);\n\n                    if (L.empty() || R.empty()) {\n                        // fallback: median x split\n                        vector<int> v = ids;\n                        sort(v.begin(), v.end(), [&](int a, int b){ return comp[a].x < comp[b].x; });\n                        int mid = (int)v.size() / 2;\n                        k = comp[v[mid]].x;\n                        L.clear(); R.clear();\n                        for (int id : ids) (comp[id].x < k ? L : R).push_back(id);\n                        if (L.empty() || R.empty()) {\n                            // last resort: simple y split\n                            vector<int> v2 = ids;\n                            sort(v2.begin(), v2.end(), [&](int a, int b){ return comp[a].y < comp[b].y; });\n                            int mid2 = (int)v2.size()/2;\n                            int k2 = comp[v2[mid2]].y;\n                            vector<int> B, T;\n                            for (int id : ids) (comp[id].y < k2 ? B : T).push_back(id);\n                            if (!B.empty() && !T.empty()) {\n                                build(lx, rx, ly, k2, B);\n                                build(lx, rx, k2, ry, T);\n                                return;\n                            }\n                            // should not happen\n                            int id = ids[0];\n                            rects[id] = Rect{lx, ly, rx, ry};\n                            return;\n                        }\n                    }\n\n                    build(lx, k, ly, ry, L);\n                    build(k, rx, ly, ry, R);\n\n                } else {\n                    // horizontal cut\n                    int top = min<int>(TOPK, (int)candH.size());\n                    vector<Cand> sub(candH.begin(), candH.begin() + top);\n\n                    long double sumW = 0;\n                    vector<long double> w(top);\n                    for (int i = 0; i < top; i++) {\n                        w[i] = expl(- (long double)sub[i].costAbs / (long double)(areaParent + 1) * K_BETA);\n                        sumW += w[i];\n                    }\n                    int pick = 0;\n                    if (sumW <= 0) pick = 0;\n                    else {\n                        long double u = (long double)(rng2() % 1000000) / 1000000.0L * sumW;\n                        long double acc = 0;\n                        for (int i = 0; i < top; i++) {\n                            acc += w[i];\n                            if (u <= acc) { pick = i; break; }\n                        }\n                    }\n                    int k = sub[pick].k;\n\n                    vector<int> B, T;\n                    B.reserve(ids.size());\n                    T.reserve(ids.size());\n                    for (int id : ids) (comp[id].y < k ? B : T).push_back(id);\n\n                    if (B.empty() || T.empty()) {\n                        // fallback: median y split\n                        vector<int> v = ids;\n                        sort(v.begin(), v.end(), [&](int a, int b){ return comp[a].y < comp[b].y; });\n                        int mid = (int)v.size() / 2;\n                        k = comp[v[mid]].y;\n                        B.clear(); T.clear();\n                        for (int id : ids) (comp[id].y < k ? B : T).push_back(id);\n                        if (B.empty() || T.empty()) {\n                            // last resort: median x split\n                            vector<int> v2 = ids;\n                            sort(v2.begin(), v2.end(), [&](int a, int b){ return comp[a].x < comp[b].x; });\n                            int mid2 = (int)v2.size()/2;\n                            int k2 = comp[v2[mid2]].x;\n                            vector<int> L, R;\n                            for (int id : ids) (comp[id].x < k2 ? L : R).push_back(id);\n                            if (!L.empty() && !R.empty()) {\n                                build(lx, k2, ly, ry, L);\n                                build(k2, rx, ly, ry, R);\n                                return;\n                            }\n                            int id = ids[0];\n                            rects[id] = Rect{lx, ly, rx, ry};\n                            return;\n                        }\n                    }\n\n                    build(lx, rx, ly, k, B);\n                    build(lx, rx, k, ry, T);\n                }\n            };\n\n        vector<int> ids(n);\n        iota(ids.begin(), ids.end(), 0);\n        build(0, N, 0, N, ids);\n\n        double sc = evalScore(comp, rects);\n        if (sc > bestScore) {\n            bestScore = sc;\n            bestRects = rects;\n        }\n    }\n\n    for (int i = 0; i < n; i++) {\n        cout << bestRects[i].a << ' ' << bestRects[i].b << ' '\n             << bestRects[i].c << ' ' << bestRects[i].d << '\\n';\n    }\n    return 0;\n}","ahc002":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const int H = 50, W = 50;\nstatic const int N = H * W;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int si, sj;\n    cin >> si >> sj;\n    vector<int> tile(N);\n    for (int i = 0; i < H; i++) {\n        for (int j = 0; j < W; j++) {\n            cin >> tile[i * W + j];\n        }\n    }\n    vector<int> p(N);\n    for (int i = 0; i < H; i++) {\n        for (int j = 0; j < W; j++) {\n            cin >> p[i * W + j];\n        }\n    }\n\n    int M = 0;\n    for (int x : tile) M = max(M, x + 1);\n\n    int start = si * W + sj;\n\n    // Neighbors (4-neighborhood) on squares\n    vector<array<int, 4>> neigh(N);\n    vector<int> deg(N, 0);\n    for (int i = 0; i < H; i++) {\n        for (int j = 0; j < W; j++) {\n            int id = i * W + j;\n            array<int,4> arr;\n            arr.fill(-1);\n            int d = 0;\n            auto add = [&](int ni, int nj) {\n                if (0 <= ni && ni < H && 0 <= nj && nj < W) arr[d++] = ni * W + nj;\n            };\n            add(i-1, j);\n            add(i+1, j);\n            add(i, j-1);\n            add(i, j+1);\n            neigh[id] = arr;\n            deg[id] = d;\n        }\n    }\n\n    // Precompute for each square: how many distinct tile-ids appear among its neighbor squares (excluding same tile).\n    vector<int> cntAdjDistinct(N, 0);\n    for (int id = 0; id < N; id++) {\n        int ti = tile[id];\n        int seen[4]; int sc = 0;\n        for (int k = 0; k < 4; k++) {\n            int nb = neigh[id][k];\n            if (nb < 0) continue;\n            int tb = tile[nb];\n            if (tb == ti) continue;\n            bool ok = true;\n            for (int q = 0; q < sc; q++) if (seen[q] == tb) ok = false;\n            if (ok) seen[sc++] = tb;\n        }\n        cntAdjDistinct[id] = sc;\n    }\n\n    auto coordOf = [&](int id) -> pair<int,int> {\n        return {id / W, id % W};\n    };\n\n    auto dirBetween = [&](int a, int b) -> char {\n        int ai = a / W, aj = a % W;\n        int bi = b / W, bj = b % W;\n        if (bi == ai - 1 && bj == aj) return 'U';\n        if (bi == ai + 1 && bj == aj) return 'D';\n        if (bi == ai && bj == aj - 1) return 'L';\n        if (bi == ai && bj == aj + 1) return 'R';\n        // Should not happen if b is a 4-neighbor of a\n        return '?';\n    };\n\n    // One random stochastic greedy walk.\n    auto runWalk = [&](mt19937_64 &rng, bool storePath) {\n        vector<char> used(M, 0);\n        vector<int> curPath;\n        curPath.reserve(M);\n\n        used[tile[start]] = 1;\n        int cur = start;\n        long long score = p[cur];\n        curPath.push_back(cur);\n\n        const double beta = 0.85;   // lookahead weight\n        const double gamma = 0.35;  // distinct-neighbor bias\n        while (true) {\n            vector<pair<int,double>> cand; // (next, value)\n            cand.reserve(4);\n            for (int k = 0; k < 4; k++) {\n                int nb = neigh[cur][k];\n                if (nb < 0) continue;\n                int tnb = tile[nb];\n                if (used[tnb]) continue;\n                int futureMax = 0;\n                // one-step lookahead from nb\n                for (int kk = 0; kk < 4; kk++) {\n                    int nn = neigh[nb][kk];\n                    if (nn < 0) continue;\n                    int tnn = tile[nn];\n                    if (used[tnn]) continue;\n                    futureMax = max(futureMax, p[nn]);\n                }\n                double val = (double)p[nb] + beta * (double)futureMax + gamma * (double)cntAdjDistinct[nb];\n                // small noise to diversify\n                val += (double)(uniform_int_distribution<int>(0, 999)(rng)) * 1e-6; // up to ~0.001\n                cand.push_back({nb, val});\n            }\n            if (cand.empty()) break;\n\n            sort(cand.begin(), cand.end(), [&](auto &x, auto &y){ return x.second > y.second; });\n            int K = min<int>(3, (int)cand.size());\n\n            if (K == 1) {\n                int nxt = cand[0].first;\n                used[tile[nxt]] = 1;\n                cur = nxt;\n                score += p[cur];\n                curPath.push_back(cur);\n            } else {\n                double base = cand[K-1].second;\n                vector<double> w(K);\n                double sumw = 0;\n                for (int i = 0; i < K; i++) {\n                    w[i] = (cand[i].second - base) + 1.0; // positive\n                    sumw += w[i];\n                }\n                double r = uniform_real_distribution<double>(0.0, sumw)(rng);\n                int pick = 0;\n                while (pick < K && r >= w[pick]) {\n                    r -= w[pick];\n                    pick++;\n                }\n                if (pick >= K) pick = K - 1;\n                int nxt = cand[pick].first;\n                used[tile[nxt]] = 1;\n                cur = nxt;\n                score += p[cur];\n                curPath.push_back(cur);\n            }\n        }\n\n        if (storePath) {\n            return pair<long long, vector<int>>(score, curPath);\n        } else {\n            return pair<long long, vector<int>>(score, {});\n        }\n    };\n\n    // Time control\n    auto t0 = chrono::steady_clock::now();\n    double TIME_LIMIT = 1.88; // seconds\n\n    mt19937_64 rng((uint64_t)chrono::steady_clock::now().time_since_epoch().count());\n\n    long long bestScore = -1;\n    vector<int> bestPath;\n\n    // Multi-start stochastic greedy\n    while (true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - t0).count();\n        if (elapsed > TIME_LIMIT) break;\n\n        bool store = false;\n        // only store path if it might improve, to reduce copying\n        // We'll quickly estimate by running without storing? (but then path missing)\n        // Simpler: always store; with small sizes it\u2019s okay. Keep it conditional:\n        // run twice? too much. We'll store every time.\n        auto [sc, path] = runWalk(rng, true);\n        if (sc > bestScore) {\n            bestScore = sc;\n            bestPath = std::move(path);\n        }\n    }\n\n    // Tail extension from best prefix (a few tries)\n    // Use remaining time.\n    auto now = chrono::steady_clock::now();\n    double elapsed = chrono::duration<double>(now - t0).count();\n    int tries = 0;\n    while (elapsed < TIME_LIMIT && tries < 60) {\n        tries++;\n\n        int L = (int)bestPath.size();\n        if (L <= 1) break;\n\n        uniform_int_distribution<int> distCut(0, max(0, L - 1));\n        // Prefer cutting near the end\n        int cut = max(0, L - 1 - (int)uniform_int_distribution<int>(0, min(120, L - 1))(rng));\n        if (cut < 0) cut = 0;\n\n        vector<char> used(M, 0);\n        long long score = 0;\n        for (int i = 0; i <= cut; i++) {\n            int sq = bestPath[i];\n            used[tile[sq]] = 1;\n            score += p[sq];\n        }\n        int cur = bestPath[cut];\n\n        vector<int> newPart;\n        newPart.reserve(M - cut);\n\n        // run extension with current used/cur\n        const double beta = 0.85, gamma = 0.35;\n        vector<int> curPath2;\n        curPath2.reserve(M);\n        curPath2.push_back(cur); // starting at cur\n\n        long long sc2 = score;\n\n        while (true) {\n            vector<pair<int,double>> cand;\n            for (int k = 0; k < 4; k++) {\n                int nb = neigh[cur][k];\n                if (nb < 0) continue;\n                if (used[tile[nb]]) continue;\n                int futureMax = 0;\n                for (int kk = 0; kk < 4; kk++) {\n                    int nn = neigh[nb][kk];\n                    if (nn < 0) continue;\n                    if (used[tile[nn]]) continue;\n                    futureMax = max(futureMax, p[nn]);\n                }\n                double val = (double)p[nb] + beta * (double)futureMax + gamma * (double)cntAdjDistinct[nb];\n                val += (double)(uniform_int_distribution<int>(0, 999)(rng)) * 1e-6;\n                cand.push_back({nb, val});\n            }\n            if (cand.empty()) break;\n\n            sort(cand.begin(), cand.end(), [&](auto &x, auto &y){ return x.second > y.second; });\n            int K = min<int>(3, (int)cand.size());\n            int nxt;\n            if (K == 1) nxt = cand[0].first;\n            else {\n                double base = cand[K-1].second;\n                vector<double> w(K);\n                double sumw = 0;\n                for (int i = 0; i < K; i++) {\n                    w[i] = (cand[i].second - base) + 1.0;\n                    sumw += w[i];\n                }\n                double r = uniform_real_distribution<double>(0.0, sumw)(rng);\n                int pick = 0;\n                while (pick < K && r >= w[pick]) {\n                    r -= w[pick];\n                    pick++;\n                }\n                if (pick >= K) pick = K - 1;\n                nxt = cand[pick].first;\n            }\n\n            used[tile[nxt]] = 1;\n            cur = nxt;\n            sc2 += p[cur];\n            curPath2.push_back(cur);\n        }\n\n        if (sc2 > bestScore) {\n            vector<int> merged;\n            merged.reserve(L - (cut + 1) + (int)curPath2.size());\n            for (int i = 0; i <= cut; i++) merged.push_back(bestPath[i]);\n            // append curPath2 excluding the first element (it equals bestPath[cut])\n            for (int i = 1; i < (int)curPath2.size(); i++) merged.push_back(curPath2[i]);\n            bestScore = sc2;\n            bestPath = std::move(merged);\n        }\n\n        now = chrono::steady_clock::now();\n        elapsed = chrono::duration<double>(now - t0).count();\n    }\n\n    // Output directions string\n    string ans;\n    if (!bestPath.empty()) {\n        ans.reserve(max(0, (int)bestPath.size() - 1));\n        for (int i = 1; i < (int)bestPath.size(); i++) {\n            ans.push_back(dirBetween(bestPath[i-1], bestPath[i]));\n        }\n    }\n    cout << ans << \"\\n\";\n    return 0;\n}","ahc003":"#include <bits/stdc++.h>\nusing namespace std;\n\n// Grid size\nstatic constexpr int H = 30;\nstatic constexpr int W = 30;\nstatic constexpr int N = H * W;\n\n// Edge indexing\n// Horizontal edges: between (i,j) and (i,j+1), i in [0,29], j in [0,28]\nstatic constexpr int HOR = H * (W - 1); // 30*29 = 870\n// Vertical edges: between (i,j) and (i+1,j), i in [0,28], j in [0,29]\nstatic constexpr int VER = (H - 1) * W; // 29*30 = 870\nstatic constexpr int ECOUNT = HOR + VER;\n\nstatic inline int idx_node(int i, int j) { return i * W + j; }\nstatic inline pair<int,int> coord_node(int v) { return {v / W, v % W}; }\n\nstatic inline int idx_horizontal_edge(int i, int j /*0..28*/) {\n    // between (i,j) and (i,j+1)\n    return i * (W - 1) + j;\n}\nstatic inline int idx_vertical_edge(int i, int j /*0..29*/) {\n    // between (i,j) and (i+1,j)\n    return HOR + i * W + j;\n}\n\nstruct PathResult {\n    string moves;\n    vector<int> usedEdges;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // Build adjacency\n    vector<vector<pair<int,int>>> adj(N); // (to, edgeIdx)\n\n    for (int i = 0; i < H; i++) {\n        for (int j = 0; j < W; j++) {\n            int u = idx_node(i, j);\n            // Right\n            if (j + 1 < W) {\n                int v = idx_node(i, j + 1);\n                int e = idx_horizontal_edge(i, j);\n                adj[u].push_back({v, e});\n                adj[v].push_back({u, e});\n            }\n            // Down\n            if (i + 1 < H) {\n                int v = idx_node(i + 1, j);\n                int e = idx_vertical_edge(i, j);\n                adj[u].push_back({v, e});\n                adj[v].push_back({u, e});\n            }\n        }\n    }\n\n    // Weight estimates\n    vector<double> w_hat(ECOUNT, 5000.0);\n\n    // RNG for exploration and tie-breaking\n    std::mt19937_64 rng(712367821ULL);\n    auto rand01 = [&]() -> double {\n        return (rng() >> 11) * (1.0 / 9007199254740992.0);\n    };\n\n    const double LO = 1.0;\n    const double HI = 15000.0;\n\n    auto build_path_from_parents = [&](int s, int t,\n                                        const vector<int>& parent,\n                                        const vector<int>& parentEdge) -> PathResult {\n        PathResult res;\n        if (s == t) return res;\n\n        vector<char> revMoves;\n        vector<int> revEdges;\n\n        int cur = t;\n        while (cur != s) {\n            int p = parent[cur];\n            int e = parentEdge[cur];\n            revEdges.push_back(e);\n\n            auto [pi, pj] = coord_node(p);\n            auto [ci, cj] = coord_node(cur);\n\n            char mv;\n            if (ci == pi - 1 && cj == pj) mv = 'U';\n            else if (ci == pi + 1 && cj == pj) mv = 'D';\n            else if (ci == pi && cj == pj - 1) mv = 'L';\n            else if (ci == pi && cj == pj + 1) mv = 'R';\n            else {\n                // Should never happen if parents define a valid grid step\n                mv = '?';\n            }\n\n            revMoves.push_back(mv);\n            cur = p;\n        }\n\n        reverse(revMoves.begin(), revMoves.end());\n        reverse(revEdges.begin(), revEdges.end());\n\n        res.moves.assign(revMoves.begin(), revMoves.end());\n        res.usedEdges = std::move(revEdges);\n        return res;\n    };\n\n    auto dijkstra_path = [&](int s, int t) -> PathResult {\n        // Dijkstra on w_hat\n        vector<long double> dist(N, numeric_limits<long double>::infinity());\n        vector<int> parent(N, -1);\n        vector<int> parentEdge(N, -1);\n        vector<long long> choiceKey(N, (1LL<<62));\n\n        struct State {\n            long double d;\n            int v;\n            long long key;\n            bool operator>(State const& other) const {\n                if (d != other.d) return d > other.d;\n                return key > other.key;\n            }\n        };\n\n        priority_queue<State, vector<State>, greater<State>> pq;\n        dist[s] = 0;\n        parent[s] = s;\n\n        pq.push({0.0L, s, 0});\n\n        const long double EPS = 1e-12;\n\n        while (!pq.empty()) {\n            auto st = pq.top(); pq.pop();\n            int u = st.v;\n            if (st.d != dist[u]) continue;\n            if (u == t) break;\n\n            for (auto [to, e] : adj[u]) {\n                long double nd = dist[u] + (long double)w_hat[e];\n                long long nkey = (long long)u * (long long)(ECOUNT + 7) + (long long)e;\n\n                if (nd + EPS < dist[to]) {\n                    dist[to] = nd;\n                    parent[to] = u;\n                    parentEdge[to] = e;\n                    choiceKey[to] = nkey;\n                    pq.push({nd, to, nkey});\n                } else if (fabsl(nd - dist[to]) <= EPS) {\n                    if (nkey < choiceKey[to]) {\n                        parent[to] = u;\n                        parentEdge[to] = e;\n                        choiceKey[to] = nkey;\n                        pq.push({nd, to, nkey});\n                    }\n                }\n            }\n        }\n\n        return build_path_from_parents(s, t, parent, parentEdge);\n    };\n\n    auto random_monotone_path = [&](int s, int t) -> PathResult {\n        auto [si, sj] = coord_node(s);\n        auto [ti, tj] = coord_node(t);\n\n        int i = si, j = sj;\n        PathResult res;\n        while (i != ti || j != tj) {\n            bool canV = (i != ti);\n            bool canH = (j != tj);\n\n            bool doV;\n            if (canV && canH) {\n                doV = (rand01() < 0.5);\n            } else {\n                doV = canV;\n            }\n\n            if (doV) {\n                if (ti > i) {\n                    // move down\n                    int e = idx_vertical_edge(i, j);\n                    res.usedEdges.push_back(e);\n                    res.moves.push_back('D');\n                    i++;\n                } else {\n                    // move up\n                    int e = idx_vertical_edge(i - 1, j);\n                    res.usedEdges.push_back(e);\n                    res.moves.push_back('U');\n                    i--;\n                }\n            } else {\n                if (tj > j) {\n                    // move right\n                    int e = idx_horizontal_edge(i, j);\n                    res.usedEdges.push_back(e);\n                    res.moves.push_back('R');\n                    j++;\n                } else {\n                    // move left\n                    int e = idx_horizontal_edge(i, j - 1);\n                    res.usedEdges.push_back(e);\n                    res.moves.push_back('L');\n                    j--;\n                }\n            }\n        }\n        return res;\n    };\n\n    for (int k = 0; k < 1000; k++) {\n        int si, sj, ti, tj;\n        if (!(cin >> si >> sj >> ti >> tj)) break;\n        int s = idx_node(si, sj);\n        int t = idx_node(ti, tj);\n\n        // Exploration probability schedule\n        double pExpl;\n        if (k < 120) pExpl = 0.18;\n        else if (k < 400) pExpl = 0.08;\n        else pExpl = 0.03;\n\n        PathResult pr;\n        if (rand01() < pExpl) pr = random_monotone_path(s, t);\n        else pr = dijkstra_path(s, t);\n\n        // Safety: if something went wrong, fallback to monotone\n        if ((int)pr.moves.size() == 0 || (int)pr.usedEdges.size() != (int)pr.moves.size()) {\n            pr = random_monotone_path(s, t);\n        }\n\n        cout << pr.moves << '\\n' << flush;\n\n        long long y_int;\n        if (!(cin >> y_int)) break;\n        long double y = (long double)y_int;\n\n        int m = (int)pr.usedEdges.size();\n        if (m == 0) continue;\n\n        long double pred = 0.0L;\n        for (int e : pr.usedEdges) pred += (long double)w_hat[e];\n\n        long double err = y - pred;\n\n        // Learning rate decay\n        long double eta = 0.30L / sqrt((long double)(k + 1));\n        eta = max((long double)0.005, eta);\n\n        long double delta = eta * err / (long double)m;\n\n        for (int e : pr.usedEdges) {\n            long double nw = (long double)w_hat[e] + delta;\n            if (nw < LO) nw = LO;\n            if (nw > HI) nw = HI;\n            w_hat[e] = (double)nw;\n        }\n    }\n\n    return 0;\n}","ahc004":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 20;\nstatic constexpr int ALPHA = 8; // A..H\n\n// SplitMix64 hash\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 uint64_t keyOfString(const vector<uint8_t>& v) {\n    int len = (int)v.size();\n    uint64_t enc = 0;\n    for (uint8_t x : v) enc = (enc << 3) | (uint64_t)x; // base 8 packing\n    return (uint64_t(len) << 48) | enc;\n}\n\nstruct Solver {\n    int M;\n    vector<string> S;\n    vector<vector<uint8_t>> scodes;\n    vector<int> slen;\n    vector<uint64_t> skey;\n\n    // distinct string keys (exact sequences by length+content)\n    int K;\n    vector<int> mult;     // multiplicity per key id\n    vector<int> occ;      // occurrence count per key in current grid\n    long long curC = 0;   // sum mult[id] where occ[id] > 0\n    int bestC = -1;\n    array<array<uint8_t, N>, N> g{};\n    array<array<uint8_t, N>, N> bestG{};\n\n    unordered_map<uint64_t, int, decltype(&splitmix64)> idByKey;\n\n    bool needLen[13]{};\n    vector<int> neededLens;\n    uint64_t maskLower[13]{};\n\n    // overlap maps for greedy construction\n    // prefixCand[ov][prefEnc] -> list of indices whose prefix of length ov equals prefEnc\n    // suffixCand[ov][sufEnc] -> list of indices whose suffix of length ov equals sufEnc\n    vector<unordered_map<uint64_t, vector<int>, decltype(&splitmix64)>> prefixCand, suffixCand;\n\n    mt19937_64 rng;\n\n    Solver() : rng((uint64_t)chrono::steady_clock::now().time_since_epoch().count()),\n               idByKey(1024, splitmix64) {}\n\n    uint8_t charToCode(char c) { return (uint8_t)(c - 'A'); }\n\n    uint64_t encFromSeq(const vector<uint8_t>& v, int l, int r) {\n        uint64_t enc = 0;\n        for (int i = l; i < r; i++) enc = (enc << 3) | v[i];\n        return enc;\n    }\n\n    void buildObjectiveStructures() {\n        idByKey.clear();\n        mult.clear();\n\n        for (int k = 0; k <= 12; k++) needLen[k] = false;\n\n        K = 0;\n        for (int i = 0; i < M; i++) {\n            uint64_t key = skey[i];\n            auto it = idByKey.find(key);\n            if (it == idByKey.end()) {\n                int id = K++;\n                idByKey.emplace(key, id);\n                mult.push_back(1);\n            } else {\n                mult[it->second]++;\n            }\n            needLen[slen[i]] = true;\n        }\n        neededLens.clear();\n        for (int k = 2; k <= 12; k++) if (needLen[k]) neededLens.push_back(k);\n\n        // Precompute masks for sliding\n        for (int k = 2; k <= 12; k++) {\n            int bits = 3 * (k - 1);\n            maskLower[k] = (bits >= 64) ? ~0ULL : ((1ULL << bits) - 1ULL);\n        }\n        occ.assign(K, 0);\n    }\n\n    void buildOverlapMaps() {\n        prefixCand.assign(13, unordered_map<uint64_t, vector<int>, decltype(&splitmix64)>(0, splitmix64));\n        suffixCand.assign(13, unordered_map<uint64_t, vector<int>, decltype(&splitmix64)>(0, splitmix64));\n\n        for (int i = 0; i < M; i++) {\n            int L = slen[i];\n            for (int ov = 2; ov <= L - 1; ov++) {\n                uint64_t pref = encFromSeq(scodes[i], 0, ov);\n                uint64_t suf  = encFromSeq(scodes[i], L - ov, L);\n                prefixCand[ov][pref].push_back(i);\n                suffixCand[ov][suf].push_back(i);\n            }\n        }\n    }\n\n    inline void updateLine(bool isRow, int idx, int delta) {\n        // delta: +1 (add contributions) or -1 (remove contributions) for that line only\n        uint8_t ext[2 * N];\n        if (isRow) {\n            for (int t = 0; t < 2 * N; t++) ext[t] = g[idx][t % N];\n        } else {\n            for (int t = 0; t < 2 * N; t++) ext[t] = g[t % N][idx];\n        }\n\n        for (int k : neededLens) {\n            uint64_t enc = 0;\n            for (int t = 0; t < k; t++) enc = (enc << 3) | (uint64_t)ext[t];\n\n            for (int start = 0; start < N; start++) {\n                uint64_t key = (uint64_t(k) << 48) | enc;\n                auto it = idByKey.find(key);\n                if (it != idByKey.end()) {\n                    int id = it->second;\n                    int before = occ[id];\n                    if (delta == +1) {\n                        occ[id] = before + 1;\n                        if (before == 0) curC += mult[id];\n                    } else {\n                        occ[id] = before - 1;\n                        if (before == 1) curC -= mult[id];\n                    }\n                }\n                if (start == N - 1) break;\n                enc = ((enc & maskLower[k]) << 3) | (uint64_t)ext[start + k];\n            }\n        }\n    }\n\n    void computeInitialCounts() {\n        fill(occ.begin(), occ.end(), 0);\n        curC = 0;\n\n        // rows\n        for (int i = 0; i < N; i++) updateLine(true, i, +1);\n        // columns\n        for (int j = 0; j < N; j++) updateLine(false, j, +1);\n\n        // IMPORTANT FIX:\n        // do NOT overwrite global bestC/bestG here.\n    }\n\n    inline void setCell(int i, int j, uint8_t nv) {\n        uint8_t old = g[i][j];\n        if (old == nv) return;\n\n        updateLine(true, i, -1);\n        updateLine(false, j, -1);\n\n        g[i][j] = nv;\n\n        updateLine(true, i, +1);\n        updateLine(false, j, +1);\n    }\n\n    void randomFillRow(array<uint8_t, N>& row) {\n        for (int j = 0; j < N; j++) row[j] = (uint8_t)(rng() % ALPHA);\n    }\n\n    void buildInitialGridGreedy() {\n        // Build a decent starting point by row assembly.\n        // coveredKeys[k] stores cyclic horizontal substrings of length k already present.\n        vector<unordered_set<uint64_t, decltype(&splitmix64)>> coveredKeys(13, unordered_set<uint64_t, decltype(&splitmix64)>(0, splitmix64));\n        vector<char> coveredInput(M, 0);\n\n        for (int k = 2; k <= 12; k++) if (needLen[k]) {\n            coveredKeys[k] = unordered_set<uint64_t, decltype(&splitmix64)>(0, splitmix64);\n            coveredKeys[k].reserve(1 << 12);\n        }\n\n        auto addRowToCovered = [&](int rowIdx, const array<uint8_t, N>& row) {\n            for (int k : neededLens) {\n                uint64_t enc = 0;\n                for (int t = 0; t < k; t++) enc = (enc << 3) | row[t];\n                for (int start = 0; start < N; start++) {\n                    uint64_t key = (uint64_t(k) << 48) | enc;\n                    coveredKeys[k].insert(key);\n                    if (start == N - 1) break;\n                    enc = ((enc & maskLower[k]) << 3) | row[(start + k) % N];\n                }\n            }\n        };\n\n        auto updateCoveredInputFromRowSets = [&]() {\n            for (int i = 0; i < M; i++) {\n                if (coveredInput[i]) continue;\n                int k = slen[i];\n                uint64_t key = skey[i];\n                if (coveredKeys[k].find(key) != coveredKeys[k].end()) coveredInput[i] = 1;\n            }\n        };\n\n        int minOverlap = 2;\n\n        for (int i = 0; i < N; i++) {\n            // choose seed string not yet horizontally covered, prefer longer\n            int bestL = -1;\n            vector<int> bestIdx;\n            for (int idx = 0; idx < M; idx++) {\n                if (coveredInput[idx]) continue;\n                if (slen[idx] > bestL) {\n                    bestL = slen[idx];\n                    bestIdx.clear();\n                    bestIdx.push_back(idx);\n                } else if (slen[idx] == bestL) {\n                    bestIdx.push_back(idx);\n                }\n            }\n\n            array<uint8_t, N> row{};\n            if (bestL < 0) {\n                randomFillRow(row);\n                for (int j = 0; j < N; j++) g[i][j] = row[j];\n                addRowToCovered(i, row);\n                updateCoveredInputFromRowSets();\n                continue;\n            }\n\n            int seed = bestIdx[rng() % (int)bestIdx.size()];\n            vector<uint8_t> seq = scodes[seed];\n\n            // Expand to length N by overlapping with input strings\n            while ((int)seq.size() < N) {\n                int curLen = (int)seq.size();\n                int maxOv = min(curLen - 1, 11);\n\n                int bestRightLen = curLen, bestRightIdx = -1, bestRightOv = -1;\n                for (int ov = maxOv; ov >= minOverlap; ov--) {\n                    uint64_t sufEnc = 0;\n                    for (int t = curLen - ov; t < curLen; t++) sufEnc = (sufEnc << 3) | seq[t];\n                    auto it = prefixCand[ov].find(sufEnc);\n                    if (it == prefixCand[ov].end()) continue;\n                    for (int candIdx : it->second) {\n                        if (slen[candIdx] <= ov) continue;\n                        int newLen = curLen + slen[candIdx] - ov;\n                        if (newLen <= N && newLen > bestRightLen) {\n                            bestRightLen = newLen;\n                            bestRightIdx = candIdx;\n                            bestRightOv = ov;\n                        }\n                    }\n                }\n\n                int bestLeftLen = curLen, bestLeftIdx = -1, bestLeftOv = -1;\n                for (int ov = maxOv; ov >= minOverlap; ov--) {\n                    uint64_t prefEnc = 0;\n                    for (int t = 0; t < ov; t++) prefEnc = (prefEnc << 3) | seq[t];\n                    auto it = suffixCand[ov].find(prefEnc);\n                    if (it == suffixCand[ov].end()) continue;\n                    for (int candIdx : it->second) {\n                        if (slen[candIdx] <= ov) continue;\n                        int newLen = curLen + slen[candIdx] - ov;\n                        if (newLen <= N && newLen > bestLeftLen) {\n                            bestLeftLen = newLen;\n                            bestLeftIdx = candIdx;\n                            bestLeftOv = ov;\n                        }\n                    }\n                }\n\n                int finalLen = max(bestRightLen, bestLeftLen);\n                if (finalLen == curLen) break;\n\n                bool takeRight;\n                if (bestRightLen > bestLeftLen) takeRight = true;\n                else if (bestLeftLen > bestRightLen) takeRight = false;\n                else takeRight = (rng() & 1);\n\n                if (takeRight) {\n                    auto& cv = scodes[bestRightIdx];\n                    int ov = bestRightOv;\n                    for (int t = ov; t < (int)cv.size() && (int)seq.size() < N; t++) seq.push_back(cv[t]);\n                } else {\n                    auto& cv = scodes[bestLeftIdx];\n                    int ov = bestLeftOv;\n                    vector<uint8_t> nseq;\n                    nseq.reserve(N);\n                    for (int t = 0; t < (int)cv.size() - ov && (int)nseq.size() < N; t++) nseq.push_back(cv[t]);\n                    for (uint8_t x : seq) {\n                        if ((int)nseq.size() >= N) break;\n                        nseq.push_back(x);\n                    }\n                    seq.swap(nseq);\n                }\n            }\n\n            while ((int)seq.size() < N) seq.push_back((uint8_t)(rng() % ALPHA));\n            for (int j = 0; j < N; j++) {\n                row[j] = seq[j];\n                g[i][j] = row[j];\n            }\n\n            addRowToCovered(i, row);\n            updateCoveredInputFromRowSets();\n        }\n    }\n\n    void solveOneRun(int steps, long double Tstart, long double Tmin, chrono::steady_clock::time_point deadline) {\n        long double T = Tstart;\n        long double alpha = pow((double)(Tmin / Tstart), 1.0L / (long double)steps);\n\n        for (int it = 0; it < steps; it++) {\n            if (chrono::steady_clock::now() >= deadline) break;\n\n            int i = (int)(rng() % N);\n            int j = (int)(rng() % N);\n\n            uint8_t old = g[i][j];\n            uint8_t nv = old;\n            while (nv == old) nv = (uint8_t)(rng() % ALPHA);\n\n            long long beforeC = curC;\n            setCell(i, j, nv);\n            long long afterC = curC;\n\n            bool accept = false;\n            if (afterC >= beforeC) {\n                accept = true;\n            } else {\n                long double prob = expl((long double)(afterC - beforeC) / T);\n                long double r = (long double)(rng() % 1000000) / 1000000.0L;\n                if (r < prob) accept = true;\n            }\n\n            if (accept) {\n                if (afterC > bestC) {\n                    bestC = (int)afterC;\n                    bestG = g;\n                }\n            } else {\n                // revert\n                setCell(i, j, old);\n            }\n\n            T *= alpha;\n            if (T < 1e-7L) T = 1e-7L;\n        }\n    }\n\n    void run() {\n        ios::sync_with_stdio(false);\n        cin.tie(nullptr);\n\n        int Nread;\n        cin >> Nread >> M; // N fixed to 20 but read anyway\n\n        S.resize(M);\n        for (int i = 0; i < M; i++) cin >> S[i];\n\n        scodes.assign(M, {});\n        slen.assign(M, 0);\n        skey.assign(M, 0);\n\n        for (int i = 0; i < M; i++) {\n            const string& s = S[i];\n            slen[i] = (int)s.size();\n            vector<uint8_t> v(s.size());\n            for (int t = 0; t < (int)s.size(); t++) v[t] = charToCode(s[t]);\n            scodes[i] = std::move(v);\n            skey[i] = keyOfString(scodes[i]);\n        }\n\n        buildObjectiveStructures();\n        buildOverlapMaps();\n\n        // Initialize grid\n        buildInitialGridGreedy();\n        auto baseG = g;\n\n        // improve expected performance: reserve more buckets\n        idByKey.reserve((size_t)K * 2);\n\n        bestC = -1;\n        bestG = g;\n\n        const auto globalStart = chrono::steady_clock::now();\n        const auto deadline = globalStart + chrono::milliseconds(2850); // keep margin\n\n        int restarts = 6;\n        for (int r = 0; r < restarts; r++) {\n            if (chrono::steady_clock::now() >= deadline) break;\n\n            g = baseG;\n\n            int perturb = (r == 0 ? 0 : 30 + 15 * r);\n            for (int t = 0; t < perturb; t++) {\n                int i = (int)(rng() % N);\n                int j = (int)(rng() % N);\n                uint8_t nv = (uint8_t)(rng() % ALPHA);\n                if (nv == g[i][j]) nv = (nv + 1) % ALPHA;\n                g[i][j] = nv;\n            }\n\n            computeInitialCounts();\n            if (curC > bestC) {\n                bestC = (int)curC;\n                bestG = g;\n            }\n\n            // Remaining steps adapt to time\n            int steps = 120000 + 20000 * r;\n            solveOneRun(steps, 4.0L, 0.10L, deadline);\n        }\n\n        for (int i = 0; i < N; i++) {\n            string row;\n            row.reserve(N);\n            for (int j = 0; j < N; j++) row.push_back(char('A' + bestG[i][j]));\n            cout << row << '\\n';\n        }\n    }\n};\n\nint main() {\n    Solver s;\n    s.run();\n    return 0;\n}","ahc005":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct DSU {\n    int n;\n    vector<int> p, r;\n    DSU(int n=0): n(n), p(n), r(n,0) { iota(p.begin(), p.end(), 0); }\n    int find(int x){ return p[x]==x? x : p[x]=find(p[x]); }\n    bool unite(int a,int b){\n        a=find(a); b=find(b);\n        if(a==b) return false;\n        if(r[a]<r[b]) swap(a,b);\n        p[b]=a;\n        if(r[a]==r[b]) r[a]++;\n        return true;\n    }\n};\n\nstruct Edge {\n    int u, v;\n    int baseCost; // w[u]+w[v]\n    int id;        // undirected edge id in the component graph\n};\n\nstatic inline char dirChar(pair<int,int> a, pair<int,int> b){\n    int ar=a.first, ac=a.second, br=b.first, bc=b.second;\n    if(br==ar-1 && bc==ac) return 'U';\n    if(br==ar+1 && bc==ac) return 'D';\n    if(br==ar && bc==ac-1) return 'L';\n    return 'R'; // br==ar && bc==ac+1\n}\n\nstruct TourResult{\n    bool ok=false;\n    long long t = (1LL<<62);\n    string route;\n};\n\nstatic TourResult doubledTreeTour(\n    int m, int sidx,\n    const vector<vector<int>>& treeAdj,\n    const vector<pair<int,int>>& cells,\n    const vector<int>& wts\n){\n    if(m==1){\n        TourResult res; res.ok=true; res.t=0; res.route=\"\"; return res;\n    }\n\n    // Build route by DFS doubling edges: parent->child then return.\n    string route;\n    route.reserve(2*(m-1));\n\n    struct Frame{ int u,p; int it; };\n    vector<Frame> st;\n    st.reserve(m);\n    st.push_back({sidx, -1, 0});\n\n    vector<int> iters(m,0);\n\n    // For speed compute t via formula:\n    // doubled-tree tour uses both directions of each tree edge exactly once:\n    // t = sum_{(u,v) in treeEdges} (w[u] + w[v])\n    // We'll compute by summing degrees/2 edges via iterating adj with u<v.\n    // But we don't have list of edges here; still can compute from adjacency: sum w[u]*deg?:\n    // Each vertex u participates in cost proportional to w[u]*deg(u) in tree.\n    // In doubled tour, each undirected tree edge contributes entering both endpoints once.\n    // So total t = sum_u w[u] * deg_tree(u).\n    long long t = 0;\n    for(int u=0;u<m;u++) t += 1LL*wts[u] * (long long)treeAdj[u].size();\n\n    while(!st.empty()){\n        auto &top = st.back();\n        int u = top.u;\n\n        if(top.it < (int)treeAdj[u].size()){\n            int v = treeAdj[u][top.it++];\n            if(v==top.p) continue;\n            route.push_back(dirChar(cells[u], cells[v]));\n            st.push_back({v, u, 0});\n        }else{\n            int p = top.p;\n            st.pop_back();\n            if(!st.empty()){\n                // return to parent p (which is current stack top)\n                int parent = st.back().u;\n                route.push_back(dirChar(cells[u], cells[parent]));\n            }\n        }\n    }\n\n    // Basic sanity: closed walk\n    // (For doubled DFS on tree it must start/end at sidx)\n    return TourResult{true, t, route};\n}\n\nstatic TourResult augmentedEulerTour(\n    int m, int sidx,\n    const vector<pair<int,int>>& cells,\n    const vector<int>& wts,\n    const vector<vector<pair<int,int>>>& adj2, // (neighbor, edgeId)\n    const vector<int>& eu,\n    const vector<int>& ev,\n    const vector<Edge>& allEdges, // undirected edges with ids\n    const vector<int>& mstEdgeIds, // tree edges selected in this attempt\n    const vector<int>& mstDeg // degrees in MST\n){\n    // Build list of odd vertices in MST\n    vector<int> odd;\n    odd.reserve(m);\n    for(int u=0;u<m;u++){\n        if(mstDeg[u] % 2 == 1) odd.push_back(u);\n    }\n    if(odd.empty()){\n        // impossible for a tree with m>1, but handle\n        TourResult res;\n        res.ok = true;\n        res.route = \"\";\n        res.t = 0;\n        return res;\n    }\n\n    int E = (int)eu.size();\n    // Multi-source Dijkstra on symmetric costs baseCost = w[u]+w[v]\n    const long long INF = (1LL<<60);\n    vector<long long> dist(m, INF);\n    vector<int> src(m, -1);\n    vector<int> parent(m, -1);\n\n    // PQ entries: (dist, node)\n    using P = pair<long long,int>;\n    priority_queue<P, vector<P>, greater<P>> pq;\n    for(int s : odd){\n        dist[s] = 0;\n        src[s] = s;\n        parent[s] = -1;\n        pq.push({0, s});\n    }\n\n    while(!pq.empty()){\n        auto [d,u] = pq.top(); pq.pop();\n        if(d != dist[u]) continue;\n        for(auto [v, eid] : adj2[u]){\n            (void)eid;\n            long long nd = d + (long long)wts[u] + (long long)wts[v];\n            if(nd < dist[v]){\n                dist[v] = nd;\n                src[v] = src[u];\n                parent[v] = u;\n                pq.push({nd, v});\n            }\n        }\n    }\n\n    for(int u=0;u<m;u++){\n        if(src[u]==-1) return TourResult(); // should not happen\n    }\n\n    // Candidate pairs from edges crossing different source regions\n    struct Cand {\n        long long cost;\n        int a,b;\n        int meetX, meetY;\n        bool operator<(Cand const& other) const{\n            if(cost != other.cost) return cost < other.cost;\n            if(a != other.a) return a < other.a;\n            if(b != other.b) return b < other.b;\n            return meetX < other.meetX;\n        }\n    };\n    vector<Cand> cands;\n    cands.reserve(E);\n\n    for(int eid=0; eid<E; eid++){\n        int a0 = eu[eid], b0 = ev[eid];\n        int sa = src[a0], sb = src[b0];\n        if(sa==-1 || sb==-1 || sa==sb) continue;\n        // candidate path using edge (a0,b0)\n        long long cost = dist[a0] + dist[b0] + (long long)wts[a0] + (long long)wts[b0];\n        cands.push_back({cost, sa, sb, a0, b0});\n    }\n    sort(cands.begin(), cands.end());\n\n    vector<char> matched(m, 0);\n    vector<int> partner(m, -1);\n\n    struct PairInfo{ int a,b; int meetX, meetY; };\n    vector<PairInfo> pairs;\n    pairs.reserve(odd.size()/2);\n\n    for(auto &cd : cands){\n        int a = cd.a, b = cd.b;\n        if(a<0 || b<0) continue;\n        if(!matched[a] && !matched[b]){\n            matched[a]=matched[b]=1;\n            partner[a]=b;\n            partner[b]=a;\n            pairs.push_back({a,b,cd.meetX,cd.meetY});\n        }\n    }\n\n    // Fallback matching for any remaining unmatched odds\n    vector<int> rem;\n    rem.reserve(odd.size());\n    for(int u : odd) if(!matched[u]) rem.push_back(u);\n\n    auto addMul = [&](vector<long long>& cnt, int x, int y){\n        // find edgeId between x and y by scanning small degree list\n        for(auto [to, eid] : adj2[x]){\n            if(to==y){\n                cnt[eid]++;\n                return;\n            }\n        }\n        // should never happen\n        assert(false);\n    };\n\n    vector<long long> cnt(E, 0);\n    // base: include each MST edge once\n    for(int eid : mstEdgeIds) cnt[eid] = 1;\n\n    // Add paths for matched pairs using multi-source parent chains + the meeting edge\n    for(auto &pr : pairs){\n        int a = pr.a, b = pr.b;\n        int x = pr.meetX, y = pr.meetY;\n\n        // Ensure src[x]=a and src[y]=b (by construction). Still safe to use parent chains.\n        int cur = x;\n        while(cur != a){\n            int p = parent[cur];\n            assert(p!=-1);\n            addMul(cnt, cur, p);\n            cur = p;\n        }\n        addMul(cnt, x, y);\n        cur = y;\n        while(cur != b){\n            int p = parent[cur];\n            assert(p!=-1);\n            addMul(cnt, cur, p);\n            cur = p;\n        }\n    }\n\n    // Now handle remaining odds\n    // Pair them greedily by closest odd via single-source Dijkstra\n    while(rem.size() >= 2){\n        int a = rem.back(); rem.pop_back();\n\n        // Dijkstra from a (symmetric costs) to compute distances + parent\n        vector<long long> d2(m, INF);\n        vector<int> par2(m, -1);\n        priority_queue<P, vector<P>, greater<P>> pq2;\n        d2[a]=0; par2[a]=-1; pq2.push({0,a});\n\n        vector<char> isOddRem(m,0);\n        for(int u : rem) isOddRem[u]=1;\n\n        int bestB = -1;\n        long long bestD = INF;\n\n        while(!pq2.empty()){\n            auto [d,u]=pq2.top(); pq2.pop();\n            if(d!=d2[u]) continue;\n            if(d >= bestD) continue;\n            if(isOddRem[u]){\n                bestD = d;\n                bestB = u;\n                // we can break because PQ gives increasing dist\n                break;\n            }\n            for(auto [v, eid] : adj2[u]){\n                (void)eid;\n                long long nd = d + (long long)wts[u] + (long long)wts[v];\n                if(nd < d2[v]){\n                    d2[v]=nd;\n                    par2[v]=u;\n                    pq2.push({nd, v});\n                }\n            }\n        }\n        if(bestB==-1) return TourResult(); // should not happen in connected component\n\n        // Remove bestB from rem\n        {\n            int idx = -1;\n            for(int i=0;i<(int)rem.size();i++){\n                if(rem[i]==bestB){ idx=i; break; }\n            }\n            assert(idx!=-1);\n            rem[idx] = rem.back();\n            rem.pop_back();\n        }\n\n        // Add shortest path from bestB to a using par2 chain\n        int cur = bestB;\n        while(cur != a){\n            int p = par2[cur];\n            assert(p!=-1);\n            addMul(cnt, cur, p);\n            cur = p;\n        }\n    }\n\n    if(!rem.empty()){\n        // Odd count must be even; should never leave one unmatched\n        return TourResult();\n    }\n\n    // Build incidence list for Euler with edge IDs\n    vector<vector<int>> inc(m);\n    inc.assign(m, {});\n    for(int eid=0; eid<E; eid++){\n        inc[eu[eid]].push_back(eid);\n        inc[ev[eid]].push_back(eid);\n    }\n\n    // Ensure Euler circuit exists: all degrees even in multigraph\n    // We'll just check parity quickly\n    vector<int> deg(m,0);\n    for(int eid=0; eid<E; eid++){\n        if(cnt[eid]==0) continue;\n        long long k = cnt[eid];\n        // Each of the two endpoints degree += k (each parallel edge adds 1 incident degree)\n        deg[eu[eid]] += (int)(k % 2);\n        deg[ev[eid]] += (int)(k % 2);\n    }\n    for(int u=0;u<m;u++){\n        if(deg[u]%2 != 0) return TourResult();\n    }\n\n    // Hierholzer with multiplicities\n    vector<int> ptr(m,0);\n    vector<int> stackV;\n    vector<int> circuitRev;\n    stackV.reserve(1);\n    circuitRev.reserve(1);\n\n    stackV.push_back(sidx);\n\n    auto otherEnd = [&](int eid, int u)->int{\n        return (u==eu[eid]? ev[eid] : eu[eid]);\n    };\n\n    while(!stackV.empty()){\n        int u = stackV.back();\n        auto &vec = inc[u];\n        while(ptr[u] < (int)vec.size() && cnt[vec[ptr[u]]] == 0) ptr[u]++;\n        if(ptr[u] == (int)vec.size()){\n            circuitRev.push_back(u);\n            stackV.pop_back();\n        }else{\n            int eid = vec[ptr[u]];\n            // use one unit of this edge\n            cnt[eid]--;\n            int v = otherEnd(eid, u);\n            stackV.push_back(v);\n        }\n    }\n\n    if(circuitRev.empty()) return TourResult();\n    reverse(circuitRev.begin(), circuitRev.end());\n\n    if(circuitRev.front() != sidx || circuitRev.back() != sidx) return TourResult();\n\n    // compute time t = sum w[nextVertex]\n    long long t = 0;\n    for(int i=1;i<(int)circuitRev.size();i++){\n        int v = circuitRev[i];\n        t += wts[v];\n    }\n\n    // build route string\n    string route;\n    route.reserve(max(0, (int)circuitRev.size()-1));\n    for(int i=0;i+1<(int)circuitRev.size();i++){\n        int a = circuitRev[i], b = circuitRev[i+1];\n        route.push_back(dirChar(cells[a], cells[b]));\n    }\n\n    return TourResult{true, t, route};\n}\n\nint main(){\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, si, sj;\n    cin >> N >> si >> sj;\n    vector<string> g(N);\n    for(int i=0;i<N;i++) cin >> g[i];\n\n    auto inside = [&](int r,int c){ return 0<=r && r<N && 0<=c && c<N; };\n\n    // Build road component reachable from (si,sj)\n    vector<vector<int>> idx(N, vector<int>(N, -1));\n    vector<pair<int,int>> cells;\n    vector<int> wts;\n\n    queue<pair<int,int>> q;\n    vector<vector<char>> vis(N, vector<char>(N, 0));\n    q.push({si,sj});\n    vis[si][sj]=1;\n\n    int dr[4]={-1,1,0,0};\n    int dc[4]={0,0,-1,1};\n\n    while(!q.empty()){\n        auto [r,c]=q.front(); q.pop();\n        int id = (int)cells.size();\n        idx[r][c]=id;\n        cells.push_back({r,c});\n        wts.push_back(g[r][c]-'0');\n\n        for(int k=0;k<4;k++){\n            int nr=r+dr[k], nc=c+dc[k];\n            if(!inside(nr,nc)) continue;\n            if(vis[nr][nc]) continue;\n            if(g[nr][nc]=='#') continue;\n            vis[nr][nc]=1;\n            q.push({nr,nc});\n        }\n    }\n\n    int m = (int)cells.size();\n    int sidx = idx[si][sj];\n\n    if(m==1){\n        cout << \"\\n\";\n        return 0;\n    }\n\n    // Build component graph adjacency with edge IDs\n    vector<vector<pair<int,int>>> adj2(m); // (neighbor, edgeId)\n    vector<int> eu, ev;\n    eu.reserve(2*m);\n    ev.reserve(2*m);\n\n    auto addAdjEdge = [&](int u,int v){\n        // create undirected edge id once (only call with u<v)\n        int eid = (int)eu.size();\n        eu.push_back(u);\n        ev.push_back(v);\n        adj2[u].push_back({v,eid});\n        adj2[v].push_back({u,eid});\n    };\n\n    for(int u=0;u<m;u++){\n        auto [r,c]=cells[u];\n        const int rr[4]={r-1,r+1,r,r};\n        const int cc[4]={c,c,c-1,c+1};\n        for(int k=0;k<4;k++){\n            int nr=rr[k], nc=cc[k];\n            if(!inside(nr,nc)) continue;\n            int v = idx[nr][nc];\n            if(v==-1) continue;\n            if(u < v) addAdjEdge(u,v);\n        }\n    }\n\n    int E = (int)eu.size();\n    // Build edge list for MST Kruskal\n    vector<Edge> allEdges;\n    allEdges.reserve(E);\n    for(int eid=0; eid<E; eid++){\n        int a=eu[eid], b=ev[eid];\n        int cost = wts[a] + wts[b];\n        allEdges.push_back({a,b,cost,eid});\n    }\n\n    // Baseline: choose an MST (deterministic) and do doubled-tree tour\n    auto buildMST = [&](mt19937_64 &rng, bool randomTies)->pair<vector<int>, vector<int>>{\n        // returns (mstEdgeIds, mstDeg)\n        vector<int> ord(allEdges.size());\n        iota(ord.begin(), ord.end(), 0);\n\n        vector<int> noise(allEdges.size(),0);\n        if(randomTies){\n            for(int i=0;i<(int)allEdges.size();i++){\n                noise[i] = (int)(rng()%3); // small tie perturb\n            }\n        }\n\n        sort(ord.begin(), ord.end(), [&](int i, int j){\n            const auto &ei = allEdges[i];\n            const auto &ej = allEdges[j];\n            if(ei.baseCost != ej.baseCost) return ei.baseCost < ej.baseCost;\n            if(randomTies) return noise[i] < noise[j];\n            return ei.id < ej.id;\n        });\n\n        DSU dsu(m);\n        vector<int> mstEdgeIds;\n        mstEdgeIds.reserve(m-1);\n        vector<int> mstDeg(m,0);\n\n        for(int idxE : ord){\n            auto &e = allEdges[idxE];\n            if(dsu.unite(e.u, e.v)){\n                mstEdgeIds.push_back(e.id);\n                mstDeg[e.u]++; mstDeg[e.v]++;\n                if((int)mstEdgeIds.size()==m-1) break;\n            }\n        }\n        if((int)mstEdgeIds.size()!=m-1){\n            // should not happen (component connected)\n            // return empty invalid\n            return {vector<int>(), vector<int>()};\n        }\n        return {mstEdgeIds, mstDeg};\n    };\n\n    auto buildTreeAdjFromEdges = [&](const vector<int>& mstEdgeIds){\n        vector<vector<int>> treeAdj(m);\n        for(int eid : mstEdgeIds){\n            int a=eu[eid], b=ev[eid];\n            treeAdj[a].push_back(b);\n            treeAdj[b].push_back(a);\n        }\n        return treeAdj;\n    };\n\n    mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());\n\n    // baseline MST\n    {\n        auto [mstEdgeIds, mstDeg] = buildMST(rng, false);\n        auto treeAdj = buildTreeAdjFromEdges(mstEdgeIds);\n        TourResult base = doubledTreeTour(m, sidx, treeAdj, cells, wts);\n        // We'll still attempt augmented and take best.\n        TourResult best = base;\n\n        int attempts = 7; // baseline + attempts\n        for(int it=0; it<attempts; it++){\n            auto [mstEdgeIds2, mstDeg2] = buildMST(rng, true);\n            if(mstEdgeIds2.empty()) continue;\n\n            TourResult aug = augmentedEulerTour(\n                m, sidx, cells, wts, adj2, eu, ev,\n                allEdges, mstEdgeIds2, mstDeg2\n            );\n            if(aug.ok && aug.t < best.t){\n                best = std::move(aug);\n            }\n        }\n        cout << best.route << \"\\n\";\n        return 0;\n    }\n}","future-contest-2022-qual":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct ReadyComp {\n    // Larger critical first; then smaller s2 first; then smaller id first.\n    const vector<int>* crit;\n    const vector<long long>* s2;\n    bool operator()(int a, int b) const {\n        if ((*crit)[a] != (*crit)[b]) return (*crit)[a] > (*crit)[b];\n        if ((*s2)[a] != (*s2)[b]) return (*s2)[a] < (*s2)[b];\n        return a < b;\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, K, R;\n    cin >> N >> M >> K >> R;\n\n    vector<long long> s2(N, 0);\n    vector<double> p(N, 0.0);\n    for (int i = 0; i < N; i++) {\n        long long sum = 0;\n        for (int k = 0; k < K; k++) {\n            long long x;\n            cin >> x;\n            sum += x * x;\n        }\n        s2[i] = sum;\n        p[i] = sqrt((double)sum);\n    }\n\n    vector<vector<int>> out(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        out[u].push_back(v);\n        indeg[v]++;\n    }\n\n    // Criticality: longest path length from i (in nodes).\n    vector<int> crit(N, 1);\n    for (int i = N - 1; i >= 0; i--) {\n        int best = 1;\n        for (int v : out[i]) best = max(best, 1 + crit[v]);\n        crit[i] = best;\n    }\n\n    // Ready set\n    ReadyComp comp{&crit, &s2};\n    set<int, ReadyComp> ready(comp);\n    for (int i = 0; i < N; i++) if (indeg[i] == 0) ready.insert(i);\n\n    vector<int> state(N, 0); // 0=unstarted, 1=in progress, 2=done\n\n    vector<int> curTask(M, -1);\n    vector<int> startDay(M, -1);\n\n    const double INF = 1e100;\n    vector<double> LB(M, -INF), UB(M, INF);\n    vector<double> param(M, 40.0); // initial guess\n\n    auto recomputeParam = [&](int j) {\n        double lb = LB[j], ub = UB[j];\n        double x;\n        if (lb <= -INF/2 && ub >= INF/2) x = 40.0;\n        else if (lb <= -INF/2) x = ub - 5.0;\n        else if (ub >= INF/2) x = lb + 5.0;\n        else x = 0.5 * (lb + ub);\n\n        x = min(100.0, max(5.0, x));\n        param[j] = x;\n    };\n\n    auto estimateScore = [&](int j, int task) -> double {\n        // Estimated time increases with (p[task] - param[j])_+\n        double diff = p[task] - param[j];\n        double time_est = 1.0;\n        if (diff > 0) time_est += diff; // linear monotone proxy\n        // Prefer critical tasks\n        const double alpha = 0.01;\n        double denom = 1.0 + alpha * (double)crit[task];\n        return time_est / denom;\n    };\n\n    mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());\n\n    int day = 1;\n    while (day <= 2000) {\n        vector<pair<int,int>> assign; // (member, task)\n        int idleCount = 0;\n        for (int j = 0; j < M; j++) if (curTask[j] == -1) idleCount++;\n\n        // Greedy: strongest members first\n        vector<int> idleMembers;\n        idleMembers.reserve(idleCount);\n        for (int j = 0; j < M; j++) if (curTask[j] == -1) idleMembers.push_back(j);\n        sort(idleMembers.begin(), idleMembers.end(), [&](int a, int b){\n            if (param[a] != param[b]) return param[a] > param[b];\n            return a < b;\n        });\n\n        const int LCAND = 60;\n\n        for (int j : idleMembers) {\n            if (ready.empty()) break;\n\n            // Scan first LCAND tasks in static ready priority, choose best for this member.\n            double bestScore = 1e100;\n            int bestTask = -1;\n            auto bestIt = ready.end();\n\n            int cnt = 0;\n            for (auto it = ready.begin(); it != ready.end() && cnt < LCAND; ++it, ++cnt) {\n                int t = *it;\n                double sc = estimateScore(j, t);\n\n                // Tiny random tie-breaker\n                sc += uniform_real_distribution<double>(0.0, 1e-7)(rng);\n\n                if (sc < bestScore) {\n                    bestScore = sc;\n                    bestTask = t;\n                    bestIt = it;\n                } else if (fabs(sc - bestScore) <= 1e-12) {\n                    // tie: higher critical, then smaller difficulty\n                    if (bestTask != -1) {\n                        if (crit[t] > crit[bestTask]) {\n                            bestScore = sc;\n                            bestTask = t;\n                            bestIt = it;\n                        } else if (crit[t] == crit[bestTask] && s2[t] < s2[bestTask]) {\n                            bestScore = sc;\n                            bestTask = t;\n                            bestIt = it;\n                        }\n                    }\n                }\n            }\n\n            if (bestTask == -1) break;\n            // assign\n            ready.erase(bestIt);\n            state[bestTask] = 1;\n            curTask[j] = bestTask;\n            startDay[j] = day;\n            assign.emplace_back(j + 1, bestTask + 1);\n        }\n\n        // Output\n        cout << assign.size();\n        for (auto [a, b] : assign) cout << ' ' << a << ' ' << b;\n        cout << '\\n' << flush;\n\n        // Read completion info\n        int n;\n        if (!(cin >> n)) return 0;\n        if (n == -1) return 0;\n\n        for (int i = 0; i < n; i++) {\n            int f;\n            cin >> f;\n            int j = f - 1;\n            int task = curTask[j];\n            if (task < 0) continue; // should not happen\n\n            curTask[j] = -1;\n            state[task] = 2;\n            int dur = day - startDay[j] + 1;\n\n            // Update bounds from duration signal\n            if (dur == 1) {\n                LB[j] = max(LB[j], p[task]);\n            } else if (dur >= 4) {\n                UB[j] = min(UB[j], p[task]);\n            }\n            recomputeParam(j);\n\n            // Update indegrees\n            for (int v : out[task]) {\n                indeg[v]--;\n                if (indeg[v] == 0 && state[v] == 0) ready.insert(v);\n            }\n        }\n\n        day++;\n    }\n\n    return 0;\n}","ahc006":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic inline int manhattan(int x1, int y1, int x2, int y2) {\n    return abs(x1 - x2) + abs(y1 - y2);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    const int NORD = 1000;\n    const int W = 1000; // matrix stride\n    const int XOFF = 400, YOFF = 400;\n    const int M = 50;\n\n    vector<int> px(NORD), py(NORD), dx(NORD), dy(NORD);\n    for (int i = 0; i < NORD; i++) {\n        int a, b, c, d;\n        cin >> a >> b >> c >> d;\n        px[i] = a; py[i] = b;\n        dx[i] = c; dy[i] = d;\n    }\n\n    // Precompute distances needed\n    vector<int> internal(NORD), startDist(NORD), endDist(NORD);\n    // trans[i][j] = dist(drop_i, pick_j)\n    vector<int> trans(NORD * W);\n    // pickDist[i][j] = dist(pick_i, pick_j)\n    vector<int> pickDist(NORD * W);\n    // dropDist[i][j] = dist(drop_i, drop_j)\n    vector<int> dropDist(NORD * W);\n\n    for (int i = 0; i < NORD; i++) {\n        internal[i] = manhattan(px[i], py[i], dx[i], dy[i]);\n        startDist[i] = manhattan(XOFF, YOFF, px[i], py[i]);\n        endDist[i] = manhattan(dx[i], dy[i], XOFF, YOFF);\n    }\n\n    for (int i = 0; i < NORD; i++) {\n        int dix = dx[i], diy = dy[i];\n        for (int j = 0; j < NORD; j++) {\n            trans[i * W + j] = manhattan(dix, diy, px[j], py[j]);\n            pickDist[i * W + j] = manhattan(px[i], py[i], px[j], py[j]);\n            dropDist[i * W + j] = manhattan(dix, diy, dx[j], dy[j]);\n        }\n    }\n\n    auto getTrans = [&](int i, int j) -> int { return trans[i * W + j]; };\n    auto getPickDist = [&](int i, int j) -> int { return pickDist[i * W + j]; };\n    auto getDropDist = [&](int i, int j) -> int { return dropDist[i * W + j]; };\n\n    vector<long long> weight(NORD);\n    for (int i = 0; i < NORD; i++) {\n        weight[i] = (long long)internal[i] + startDist[i] + endDist[i];\n    }\n\n    auto computeMacroTotal = [&](const vector<int>& orderSeq, long long internalSum) -> long long {\n        long long cost = startDist[orderSeq[0]];\n        cost += endDist[orderSeq.back()];\n        for (int i = 0; i + 1 < (int)orderSeq.size(); i++) {\n            cost += getTrans(orderSeq[i], orderSeq[i + 1]); // drop_i -> pick_next\n        }\n        return internalSum + cost;\n    };\n\n    auto buildMacroRoute = [&](const vector<int>& orderSeq) -> vector<pair<int,int>> {\n        vector<pair<int,int>> route;\n        route.reserve(2 * M + 2);\n        route.push_back({XOFF, YOFF});\n        for (int ord : orderSeq) {\n            route.push_back({px[ord], py[ord]});\n            route.push_back({dx[ord], dy[ord]});\n        }\n        route.push_back({XOFF, YOFF});\n        return route;\n    };\n\n    auto nearestNeighborMacroForward = [&](const vector<int>& subset, long long internalSum) -> pair<long long, vector<int>> {\n        vector<char> used(NORD, 0);\n        vector<int> orderSeq;\n        orderSeq.reserve(M);\n\n        int first = subset[0];\n        for (int v : subset) if (startDist[v] < startDist[first]) first = v;\n        orderSeq.push_back(first);\n        used[first] = 1;\n\n        while ((int)orderSeq.size() < M) {\n            int cur = orderSeq.back();\n            int best = -1;\n            int bestCost = INT_MAX;\n            for (int cand : subset) if (!used[cand]) {\n                int cst = getTrans(cur, cand); // drop_cur -> pick_cand\n                if (cst < bestCost) {\n                    bestCost = cst;\n                    best = cand;\n                }\n            }\n            used[best] = 1;\n            orderSeq.push_back(best);\n        }\n\n        long long t = computeMacroTotal(orderSeq, internalSum);\n        return {t, orderSeq};\n    };\n\n    auto nearestNeighborMacroBackward = [&](const vector<int>& subset, long long internalSum) -> pair<long long, vector<int>> {\n        vector<char> used(NORD, 0);\n        vector<int> orderSeq(M);\n\n        int last = subset[0];\n        for (int v : subset) if (endDist[v] < endDist[last]) last = v;\n        orderSeq[M - 1] = last;\n        used[last] = 1;\n\n        for (int pos = M - 2; pos >= 0; pos--) {\n            int cur = orderSeq[pos + 1]; // in forward order: prev -> cur\n            int best = -1;\n            int bestCost = INT_MAX;\n            for (int cand : subset) if (!used[cand]) {\n                int cst = getTrans(cand, cur); // drop_cand -> pick_cur\n                if (cst < bestCost) {\n                    bestCost = cst;\n                    best = cand;\n                }\n            }\n            used[best] = 1;\n            orderSeq[pos] = best;\n        }\n\n        long long t = computeMacroTotal(orderSeq, internalSum);\n        return {t, orderSeq};\n    };\n\n    auto optimizeMacroForSubset = [&](const vector<int>& subset) -> pair<long long, vector<pair<int,int>>> {\n        long long internalSum = 0;\n        for (int v : subset) internalSum += internal[v];\n\n        auto fwd = nearestNeighborMacroForward(subset, internalSum);\n        auto bwd = nearestNeighborMacroBackward(subset, internalSum);\n\n        vector<int> bestSeq = (fwd.first <= bwd.first) ? fwd.second : bwd.second;\n        long long bestT = min(fwd.first, bwd.first);\n\n        // Local search: swap best-improvement sweeps\n        const int SWAP_SWEEPS = 2;\n        for (int sweep = 0; sweep < SWAP_SWEEPS; sweep++) {\n            bool improved = false;\n            long long curT = bestT;\n            int bi = -1, bj = -1;\n\n            for (int i = 0; i < M; i++) {\n                for (int j = i + 1; j < M; j++) {\n                    swap(bestSeq[i], bestSeq[j]);\n                    long long t = computeMacroTotal(bestSeq, internalSum);\n                    if (t < curT) {\n                        curT = t;\n                        bi = i; bj = j;\n                        improved = true;\n                    }\n                    swap(bestSeq[i], bestSeq[j]);\n                }\n            }\n            if (!improved) break;\n            swap(bestSeq[bi], bestSeq[bj]);\n            bestT = curT;\n        }\n\n        // Local search: insertion (best-improvement) one sweep\n        {\n            long long curT = bestT;\n            int bestI = -1, bestJ = -1;\n            for (int i = 0; i < M; i++) {\n                for (int j = 0; j < M; j++) if (j != i) {\n                    vector<int> tmp = bestSeq;\n                    int val = tmp[i];\n                    tmp.erase(tmp.begin() + i);\n                    tmp.insert(tmp.begin() + j, val);\n                    long long t = computeMacroTotal(tmp, internalSum);\n                    if (t < curT) {\n                        curT = t;\n                        bestI = i; bestJ = j;\n                    }\n                }\n            }\n            if (bestI != -1) {\n                int val = bestSeq[bestI];\n                bestSeq.erase(bestSeq.begin() + bestI);\n                bestSeq.insert(bestSeq.begin() + bestJ, val);\n                bestT = curT;\n            }\n        }\n\n        return {bestT, buildMacroRoute(bestSeq)};\n    };\n\n    auto computeTwoStageTotal = [&](const vector<int>& pickupOrder, const vector<int>& destOrder) -> long long {\n        long long cost = startDist[pickupOrder[0]];\n        for (int i = 0; i + 1 < M; i++) {\n            cost += getPickDist(pickupOrder[i], pickupOrder[i + 1]);\n        }\n        // pickup_last -> drop_first\n        cost += getTrans(destOrder[0], pickupOrder.back()); // dist(pick_last, drop_first)\n        for (int i = 0; i + 1 < M; i++) {\n            cost += getDropDist(destOrder[i], destOrder[i + 1]);\n        }\n        cost += endDist[destOrder.back()];\n        return cost;\n    };\n\n    auto buildTwoStageRouteGreedy = [&](const vector<int>& subset) -> pair<long long, vector<pair<int,int>>> {\n        // Greedy pickup order by nearest neighbor on pickDist\n        vector<char> used(NORD, 0);\n        vector<int> pickupOrder;\n        pickupOrder.reserve(M);\n\n        int first = subset[0];\n        for (int v : subset) if (startDist[v] < startDist[first]) first = v;\n        pickupOrder.push_back(first);\n        used[first] = 1;\n\n        while ((int)pickupOrder.size() < M) {\n            int cur = pickupOrder.back();\n            int best = -1, bestC = INT_MAX;\n            for (int cand : subset) if (!used[cand]) {\n                int cst = getPickDist(cur, cand);\n                if (cst < bestC) { bestC = cst; best = cand; }\n            }\n            used[best] = 1;\n            pickupOrder.push_back(best);\n        }\n\n        // Greedy destination order by nearest neighbor on dropDist, starting from last pickup\n        vector<char> used2(NORD, 0);\n        vector<int> destOrder;\n        destOrder.reserve(M);\n\n        int lastPick = pickupOrder.back();\n        int firstDest = -1, bestC = INT_MAX;\n        for (int v : subset) if (!used2[v]) {\n            int cst = getTrans(v, lastPick); // dist(drop_v, pick_last) == dist(pick_last, drop_v)\n            if (cst < bestC) { bestC = cst; firstDest = v; }\n        }\n        destOrder.push_back(firstDest);\n        used2[firstDest] = 1;\n\n        while ((int)destOrder.size() < M) {\n            int cur = destOrder.back();\n            int best = -1, bestD = INT_MAX;\n            for (int cand : subset) if (!used2[cand]) {\n                int cst = getDropDist(cur, cand);\n                if (cst < bestD) { bestD = cst; best = cand; }\n            }\n            used2[best] = 1;\n            destOrder.push_back(best);\n        }\n\n        long long total = computeTwoStageTotal(pickupOrder, destOrder);\n\n        vector<pair<int,int>> route;\n        route.reserve(2 * M + 2);\n        route.push_back({XOFF, YOFF});\n        for (int ord : pickupOrder) route.push_back({px[ord], py[ord]});\n        for (int ord : destOrder) route.push_back({dx[ord], dy[ord]});\n        route.push_back({XOFF, YOFF});\n        return {total, route};\n    };\n\n    // Candidate subset pools\n    vector<int> ids(NORD);\n    iota(ids.begin(), ids.end(), 0);\n    sort(ids.begin(), ids.end(), [&](int i, int j){ return weight[i] < weight[j]; });\n\n    vector<int> pool;\n    int TOP = 350;\n    for (int i = 0; i < TOP; i++) pool.push_back(ids[i]);\n\n    // Add randomness from the remainder\n    mt19937 rng((uint32_t)chrono::steady_clock::now().time_since_epoch().count());\n    uniform_int_distribution<int> uniAll(0, NORD - 1);\n    while ((int)pool.size() < 500) {\n        int v = uniAll(rng);\n        if (find(pool.begin(), pool.end(), v) == pool.end()) pool.push_back(v);\n    }\n\n    sort(pool.begin(), pool.end());\n    pool.erase(unique(pool.begin(), pool.end()), pool.end());\n\n    auto sampleSubsetWeightedNoReplace = [&](int k) -> vector<int> {\n        // Exponential race sampling without replacement:\n        // key = -log(u) / rate, choose smallest k keys.\n        // We want smaller weight more likely => rate = 1/(weight+1).\n        vector<pair<long double,int>> keys;\n        keys.reserve(pool.size());\n        uniform_real_distribution<long double> ur(1e-12L, 1.0L);\n        for (int v : pool) {\n            long double u = ur(rng);\n            long double rate = 1.0L / ( (long double)weight[v] + 1.0L );\n            long double key = -log(u) / rate;\n            keys.push_back({key, v});\n        }\n        nth_element(keys.begin(), keys.begin() + k, keys.end(),\n                    [](auto &p1, auto &p2){ return p1.first < p2.first; });\n        vector<int> subset;\n        subset.reserve(k);\n        for (int i = 0; i < k; i++) subset.push_back(keys[i].second);\n        return subset;\n    };\n\n    // Global best\n    long long bestT = (1LL<<62);\n    vector<int> bestSubset;\n    vector<pair<int,int>> bestRoute;\n\n    auto trySubset = [&](const vector<int>& subset) {\n        if ((int)subset.size() != M) return;\n\n        auto macro = optimizeMacroForSubset(subset);\n        if (macro.first < bestT) {\n            bestT = macro.first;\n            bestSubset = subset;\n            bestRoute = move(macro.second);\n        }\n\n        auto twoStage = buildTwoStageRouteGreedy(subset);\n        if (twoStage.first < bestT) {\n            bestT = twoStage.first;\n            bestSubset = subset;\n            bestRoute = move(twoStage.second);\n        }\n    };\n\n    // Try a few deterministic subsets first\n    auto pickTopKBy = [&](auto getter) -> vector<int> {\n        vector<int> v = ids;\n        sort(v.begin(), v.end(), [&](int i, int j){ return getter(i) < getter(j); });\n        v.resize(M);\n        return v;\n    };\n\n    trySubset(pickTopKBy([&](int i){ return (long long)internal[i]; }));\n    trySubset(pickTopKBy([&](int i){ return (long long)startDist[i]; }));\n    trySubset(pickTopKBy([&](int i){ return (long long)endDist[i]; }));\n    trySubset(pickTopKBy([&](int i){ return weight[i]; }));\n\n    // Multi-start random subsets\n    auto t0 = chrono::steady_clock::now();\n    int iter = 0;\n    while (true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - t0).count();\n        if (elapsed > 1.75) break;\n        if (iter++ > 90) break;\n\n        vector<int> subset = sampleSubsetWeightedNoReplace(M);\n        // small chance to ensure diversity: occasionally replace one element with a nearby-best one\n        if (iter % 7 == 0) {\n            // Replace the worst-weight element inside subset by something better from top ids (if not present).\n            int wi = -1, worst = -1;\n            for (int t = 0; t < M; t++) {\n                int v = subset[t];\n                if (worst == -1 || weight[v] > weight[subset[wi]]) wi = t;\n            }\n            // find better not in subset\n            sort(subset.begin(), subset.end());\n            vector<char> in(NORD, 0);\n            for (int v : subset) in[v] = 1;\n            int repl = -1;\n            for (int u : ids) {\n                if (!in[u]) { repl = u; break; }\n            }\n            if (repl != -1) subset[wi] = repl;\n            // restore permutation size still M\n        }\n\n        trySubset(subset);\n    }\n\n    // Output best result\n    // Header: chosen order indices\n    cout << M << \"\\n\";\n    // bestSubset may be empty if something went wrong; but should not.\n    if ((int)bestSubset.size() != M) {\n        // fallback: just output first M ids by weight and a trivial macro route ordering\n        vector<int> fallback = ids;\n        fallback.resize(M);\n        bestSubset = fallback;\n        vector<int> seq = fallback;\n        // trivial order: by increasing startDist\n        sort(seq.begin(), seq.end(), [&](int i, int j){ return startDist[i] < startDist[j]; });\n        bestRoute = buildMacroRoute(seq);\n    }\n    for (int i = 0; i < M; i++) {\n        if (i) cout << ' ';\n        cout << (bestSubset[i] + 1);\n    }\n    cout << \"\\n\";\n\n    cout << bestRoute.size() << \"\\n\";\n    for (auto [x, y] : bestRoute) {\n        cout << x << \" \" << y << \" \";\n    }\n    cout << \"\\n\";\n    return 0;\n}","ahc007":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct DSU {\n    int n;\n    vector<int> p, sz;\n    int comps;\n    DSU() : n(0), comps(0) {}\n    DSU(int n_) { init(n_); }\n    void init(int n_) {\n        n = n_;\n        p.resize(n);\n        sz.assign(n, 1);\n        iota(p.begin(), p.end(), 0);\n        comps = n;\n    }\n    int find(int x) {\n        while (p[x] != x) {\n            p[x] = p[p[x]];\n            x = p[x];\n        }\n        return x;\n    }\n    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        comps--;\n        return true;\n    }\n};\n\nstatic inline int distRound(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    double d = std::sqrt((double)dx * dx + (double)dy * dy);\n    return (int)llround(d);\n}\n\n// Check if (DSU_cur accepted edges) + (all remaining edges from remIdx..M-1) is connected.\n// This uses precomputed sufRoot[remIdx][v] = root of v in DSU built with only suffix edges.\nstatic bool feasibleSkip(int N, int remIdx, const DSU &curDSU,\n                          const vector<vector<uint16_t>> &sufRoot) {\n    if (curDSU.comps == 1) return true;\n\n    // Compress current DSU components to ids 0..k-1\n    vector<int> idOfRoot(N, -1);\n    vector<int> compId(N);\n    int k = 0;\n    for (int v = 0; v < N; v++) {\n        int r = curDSU.find(v);\n        int &id = idOfRoot[r];\n        if (id == -1) id = k++;\n        compId[v] = id;\n    }\n    if (k == 1) return true;\n\n    // Build DSU over current components, union components that share a suffix DSU root.\n    DSU comb(k);\n    vector<int> firstA(N, -1); // suffix-root is in [0..N-1]\n    for (int v = 0; v < N; v++) {\n        int a = compId[v];\n        int bRoot = (int)sufRoot[remIdx][v];\n        int &f = firstA[bRoot];\n        if (f == -1) f = a;\n        else comb.unite(a, f);\n    }\n    return comb.comps == 1;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M;\n    while ( (cin >> N >> M) ) {\n        vector<int> x(N), y(N);\n        for (int i = 0; i < N; i++) cin >> x[i] >> y[i];\n\n        vector<int> U(M), V(M);\n        for (int i = 0; i < M; i++) {\n            cin >> U[i] >> V[i];\n        }\n\n        vector<int> d(M);\n        for (int i = 0; i < M; i++) {\n            d[i] = distRound(x[U[i]], y[U[i]], x[V[i]], y[V[i]]);\n            if (d[i] == 0) d[i] = 1; // just in case (shouldn't happen in given generator)\n        }\n\n        // Compute MST on proxy weights d_i (offline) to bias heuristic\n        vector<int> ord(M);\n        iota(ord.begin(), ord.end(), 0);\n        sort(ord.begin(), ord.end(), [&](int a, int b){\n            if (d[a] != d[b]) return d[a] < d[b];\n            return a < b;\n        });\n        DSU dsuTmp(N);\n        vector<char> inMST(M, 0);\n        for (int idx : ord) {\n            if (dsuTmp.unite(U[idx], V[idx])) inMST[idx] = 1;\n        }\n\n        // Precompute suffix connectivity roots:\n        // sufRoot[i][v] = DSU root of v using all edges from i..M-1\n        vector<vector<uint16_t>> sufRoot(M + 1, vector<uint16_t>(N));\n        DSU sufDSU(N);\n        for (int v = 0; v < N; v++) sufRoot[M][v] = (uint16_t)v;\n        for (int i = M - 1; i >= 0; i--) {\n            sufDSU.unite(U[i], V[i]);\n            for (int v = 0; v < N; v++) sufRoot[i][v] = (uint16_t)sufDSU.find(v);\n        }\n\n        // Online decisions\n        DSU curDSU(N);\n\n        for (int i = 0; i < M; i++) {\n            long long li;\n            cin >> li;\n\n            int ru = curDSU.find(U[i]);\n            int rv = curDSU.find(V[i]);\n            if (ru == rv) {\n                cout << 0 << \"\\n\" << flush;\n                continue;\n            }\n\n            // Heuristic acceptance threshold based on progress and (optional) MST-bias.\n            double progress = (M <= 1 ? 1.0 : (double)i / (double)(M - 1));\n            double lambda = 1.6 + 1.4 * progress;   // in [1.6, 3.0]\n            if (inMST[i]) lambda += 0.2;          // accept MST-d edges slightly easier\n            else lambda -= 0.1;                   // accept non-tree edges slightly harder\n            lambda = max(1.0, min(3.0, lambda));\n\n            bool accept = false;\n            // accept if li <= lambda * d[i]\n            long double rhs = (long double)lambda * (long double)d[i];\n            if ((long double)li <= rhs) accept = true;\n\n            if (!accept) {\n                // Only skip if still feasible to finish connected.\n                // If we skip edge i, remaining edges start at i+1.\n                bool ok = feasibleSkip(N, i + 1, curDSU, sufRoot);\n                if (!ok) accept = true;\n            }\n\n            if (accept) {\n                curDSU.unite(ru, rv);\n                cout << 1 << \"\\n\" << flush;\n            } else {\n                cout << 0 << \"\\n\" << flush;\n            }\n        }\n\n        // If the judge checks connectivity, the feasibility invariant should guarantee it.\n        // (No extra output here.)\n    }\n    return 0;\n}","ahc008":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const int H = 30, W = 30;\nstatic const int V = H * W;\nstatic const long long INFLL = (1LL << 60);\n\nstatic inline int id(int x, int y) { return x * W + y; }\nstatic inline bool inb(int x, int y) { return (0 <= x && x < H && 0 <= y && y < W); }\n\nstatic const int dx4[4] = {-1, 1, 0, 0};\nstatic const int dy4[4] = {0, 0, -1, 1};\n\nstatic char moveChar(int from, int to) {\n    int fx = from / W, fy = from % W;\n    int tx = to / W, ty = to % W;\n    if (tx == fx - 1 && ty == fy) return 'U';\n    if (tx == fx + 1 && ty == fy) return 'D';\n    if (tx == fx && ty == fy - 1) return 'L';\n    if (tx == fx && ty == fy + 1) return 'R';\n    return '.'; // should not happen\n}\n\nstatic char blockChar(int from, int to) {\n    // to is adjacent to from, and we block 'to'\n    int fx = from / W, fy = from % W;\n    int tx = to / W, ty = to % W;\n    if (tx == fx - 1 && ty == fy) return 'u';\n    if (tx == fx + 1 && ty == fy) return 'd';\n    if (tx == fx && ty == fy - 1) return 'l';\n    if (tx == fx && ty == fy + 1) return 'r';\n    return '.'; // should not happen\n}\n\nstatic bool isAdj(int a, int b) {\n    int ax = a / W, ay = a % W;\n    int bx = b / W, by = b % W;\n    return abs(ax - bx) + abs(ay - by) == 1;\n}\n\nstatic vector<int> reconstructPath(int start, int goal, const vector<int>& parent) {\n    vector<int> path;\n    int cur = goal;\n    if (parent[cur] == -1 && cur != start) return path;\n    while (cur != start) {\n        path.push_back(cur);\n        cur = parent[cur];\n    }\n    path.push_back(start);\n    reverse(path.begin(), path.end());\n    return path;\n}\n\n// Compute a single wall path from boundary A to boundary B (4-neighbor).\n// vertical=true: top(row 0) -> bottom(row H-1)\n// vertical=false: left(col0) -> right(col W-1)\nstatic vector<int> computeWallPath(\n    bool vertical,\n    const vector<char>& humanInitAt,\n    const vector<char>& petInitAt,\n    const vector<pair<int,int>>& petPosList // (pos, type not needed)\n) {\n    // Cell cost: forbid initial humans, penalize pets and pet adjacency strongly.\n    const int INF = 1e9;\n    vector<int> cellCost(V, 1);\n\n    for (int x = 0; x < H; x++) for (int y = 0; y < W; y++) {\n        int c = id(x,y);\n        if (humanInitAt[c]) { cellCost[c] = INF; continue; }\n        int cost = 1;\n        if (petInitAt[c]) cost += 500;\n        int petAdj = 0;\n        for (int k = 0; k < 4; k++) {\n            int nx = x + dx4[k], ny = y + dy4[k];\n            if (!inb(nx, ny)) continue;\n            if (petInitAt[id(nx,ny)]) petAdj++;\n        }\n        cost += petAdj * 120;\n        cellCost[c] = cost;\n    }\n\n    using P = pair<long long,int>;\n    vector<long long> dist(V, INFLL);\n    vector<int> parent(V, -1);\n\n    priority_queue<P, vector<P>, greater<P>> pq;\n\n    if (vertical) {\n        // top to bottom\n        for (int y = 0; y < W; y++) {\n            int s = id(0, y);\n            if (cellCost[s] >= INF) continue;\n            dist[s] = cellCost[s];\n            parent[s] = -2;\n            pq.push({dist[s], s});\n        }\n        int bestGoal = -1;\n        long long bestDist = INFLL;\n        while (!pq.empty()) {\n            auto [d,u] = pq.top(); pq.pop();\n            if (d != dist[u]) continue;\n            int ux = u / W;\n            if (ux == H-1) {\n                if (d < bestDist) { bestDist = d; bestGoal = u; }\n                // keep exploring; but we can prune a bit\n            }\n            int ux2 = u / W, uy = u % W;\n            for (int k = 0; k < 4; k++) {\n                int vx = ux2 + dx4[k], vy = uy + dy4[k];\n                if (!inb(vx,vy)) continue;\n                int v = id(vx,vy);\n                if (cellCost[v] >= INF) continue;\n                long long nd = d + cellCost[v];\n                if (nd < dist[v]) {\n                    dist[v] = nd;\n                    parent[v] = u;\n                    pq.push({nd,v});\n                }\n            }\n        }\n        if (bestGoal == -1) {\n            // fallback: simple middle column\n            int ymid = W/2;\n            vector<int> path;\n            for (int x = 0; x < H; x++) path.push_back(id(x, ymid));\n            return path;\n        }\n        // find start for reconstruct: parent[start] == -2\n        // We can reconstruct backwards until parent == -2.\n        vector<int> path;\n        int cur = bestGoal;\n        while (true) {\n            path.push_back(cur);\n            int p = parent[cur];\n            if (p == -2) break;\n            if (p < 0) break;\n            cur = p;\n        }\n        reverse(path.begin(), path.end());\n        return path;\n    } else {\n        // left to right\n        for (int x = 0; x < H; x++) {\n            int s = id(x, 0);\n            if (cellCost[s] >= INF) continue;\n            dist[s] = cellCost[s];\n            parent[s] = -2;\n            pq.push({dist[s], s});\n        }\n        int bestGoal = -1;\n        long long bestDist = INFLL;\n        while (!pq.empty()) {\n            auto [d,u] = pq.top(); pq.pop();\n            if (d != dist[u]) continue;\n            int uy = u % W;\n            if (uy == W-1) {\n                if (d < bestDist) { bestDist = d; bestGoal = u; }\n            }\n            int ux = u / W, uy2 = u % W;\n            for (int k = 0; k < 4; k++) {\n                int vx = ux + dx4[k], vy = uy2 + dy4[k];\n                if (!inb(vx,vy)) continue;\n                int v = id(vx,vy);\n                if (cellCost[v] >= INF) continue;\n                long long nd = d + cellCost[v];\n                if (nd < dist[v]) {\n                    dist[v] = nd;\n                    parent[v] = u;\n                    pq.push({nd,v});\n                }\n            }\n        }\n        if (bestGoal == -1) {\n            int xmid = H/2;\n            vector<int> path;\n            for (int y = 0; y < W; y++) path.push_back(id(xmid, y));\n            return path;\n        }\n        vector<int> path;\n        int cur = bestGoal;\n        while (true) {\n            path.push_back(cur);\n            int p = parent[cur];\n            if (p == -2) break;\n            if (p < 0) break;\n            cur = p;\n        }\n        reverse(path.begin(), path.end());\n        return path;\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> petPos(N);\n    vector<int> petType(N);\n    vector<char> petInitAt(V, 0);\n\n    for (int i = 0; i < N; i++) {\n        int px, py, pt;\n        cin >> px >> py >> pt;\n        --px; --py;\n        petPos[i] = id(px, py);\n        petType[i] = pt;\n        petInitAt[petPos[i]] = 1;\n    }\n\n    int M;\n    cin >> M;\n    vector<int> humanPos(M);\n    vector<char> humanInitAt(V, 0);\n    for (int i = 0; i < M; i++) {\n        int hx, hy;\n        cin >> hx >> hy;\n        --hx; --hy;\n        humanPos[i] = id(hx, hy);\n        humanInitAt[humanPos[i]] = 1;\n    }\n\n    // Choose wall orientation by initial heuristic evaluation.\n    auto evalWall = [&](const vector<int>& wallPath) -> double {\n        vector<char> wallSet(V,0);\n        for (int c: wallPath) wallSet[c]=1;\n\n        vector<int> comp(V, -1);\n        int compCnt = 0;\n        vector<int> compSize;\n        queue<int> q;\n        for (int s = 0; s < V; s++) {\n            if (wallSet[s] || comp[s]!=-1) continue;\n            comp[s] = compCnt;\n            int sz=0;\n            q.push(s);\n            while(!q.empty()){\n                int u=q.front();q.pop();\n                sz++;\n                int ux=u/W, uy=u%W;\n                for(int k=0;k<4;k++){\n                    int vx=ux+dx4[k], vy=uy+dy4[k];\n                    if(!inb(vx,vy)) continue;\n                    int v=id(vx,vy);\n                    if(wallSet[v]||comp[v]!=-1) continue;\n                    comp[v]=compCnt;\n                    q.push(v);\n                }\n            }\n            compSize.push_back(sz);\n            compCnt++;\n        }\n\n        vector<int> petCnt(compCnt,0);\n        for (int i=0;i<N;i++){\n            int p=petPos[i];\n            if(wallSet[p]) continue;\n            int c=comp[p];\n            if(c>=0) petCnt[c]++;\n        }\n\n        vector<double> scores(compCnt,0.0);\n        for(int c=0;c<compCnt;c++){\n            scores[c] = (double)compSize[c] / 900.0 * pow(0.5, petCnt[c]);\n        }\n        sort(scores.begin(), scores.end(), greater<double>());\n\n        // Approx: top components can receive humans.\n        int take = min(M, (int)scores.size());\n        double best = 0;\n        if (take==0) return 0;\n        for(int i=0;i<take;i++) best += scores[i];\n        if (M > take) best += (M-take) * scores[0];\n        return best / M;\n    };\n\n    vector<pair<int,int>> dummyPets;\n    vector<int> wallV = computeWallPath(true, humanInitAt, petInitAt, dummyPets);\n    vector<int> wallH = computeWallPath(false, humanInitAt, petInitAt, dummyPets);\n\n    double scoreV = evalWall(wallV);\n    double scoreH = evalWall(wallH);\n    vector<int> wall = (scoreV >= scoreH ? wallV : wallH);\n\n    vector<int> wallIndex(V, -1);\n    vector<char> wallSet(V, 0);\n    for (int i = 0; i < (int)wall.size(); i++) {\n        wallSet[wall[i]] = 1;\n        wallIndex[wall[i]] = i;\n    }\n    int L = (int)wall.size();\n    int mid = L / 2;\n\n    // Precompute components assuming the whole wall path is an obstacle for non-builders.\n    // This gives stable connectivity for choosing targets.\n    vector<int> compId(V, -1);\n    vector<vector<int>> compCells;\n    vector<int> compSize;\n\n    {\n        queue<int> q;\n        int compCnt = 0;\n        for (int s = 0; s < V; s++) {\n            if (wallSet[s] || compId[s] != -1) continue;\n            compId[s] = compCnt;\n            int sz = 0;\n            q.push(s);\n            compCells.push_back({});\n            while (!q.empty()) {\n                int u = q.front(); q.pop();\n                compCells.back().push_back(u);\n                sz++;\n                int ux = u / W, uy = u % W;\n                for (int k = 0; k < 4; k++) {\n                    int vx = ux + dx4[k], vy = uy + dy4[k];\n                    if (!inb(vx,vy)) continue;\n                    int v = id(vx,vy);\n                    if (wallSet[v] || compId[v] != -1) continue;\n                    compId[v] = compCnt;\n                    q.push(v);\n                }\n            }\n            compSize.push_back(sz);\n            compCnt++;\n        }\n    }\n    int compCnt = (int)compCells.size();\n\n    // Interior depth: distance to nearest wall cell in the wall-obstacle world.\n    vector<int> distInterior(V, -1);\n    {\n        queue<int> q;\n        for (int c = 0; c < V; c++) {\n            if (wallSet[c]) {\n                distInterior[c] = 0;\n                q.push(c);\n            }\n        }\n        while (!q.empty()) {\n            int u = q.front(); q.pop();\n            int ux = u / W, uy = u % W;\n            for (int k = 0; k < 4; k++) {\n                int vx = ux + dx4[k], vy = uy + dy4[k];\n                if (!inb(vx,vy)) continue;\n                int v = id(vx,vy);\n                if (wallSet[v]) continue; // keep sources as 0 but don't assign further through wall\n                if (distInterior[v] != -1) continue;\n                distInterior[v] = distInterior[u] + 1;\n                q.push(v);\n            }\n        }\n    }\n\n    // For each component, store top deepest cells to target.\n    int TOP_DEEP = 3;\n    vector<vector<int>> topCells(compCnt);\n    for (int c = 0; c < compCnt; c++) {\n        auto &cells = compCells[c];\n        vector<pair<int,int>> v;\n        v.reserve(cells.size());\n        for (int cell : cells) v.push_back({distInterior[cell], cell});\n        sort(v.begin(), v.end(), [&](auto& a, auto& b){ return a.first > b.first; });\n        for (int i = 0; i < (int)v.size() && i < TOP_DEEP; i++) topCells[c].push_back(v[i].second);\n        if (topCells[c].empty() && !cells.empty()) topCells[c].push_back(cells[0]);\n    }\n\n    // Choose builders: one on the component touching top boundary, another touching bottom boundary.\n    int topComp = -1, bottomComp = -1;\n    {\n        // find a component among passable cells on top/bottom rows\n        for (int y = 0; y < W; y++) {\n            int c = id(0,y);\n            if (!wallSet[c] && compId[c] != -1) { topComp = compId[c]; break; }\n        }\n        for (int y = 0; y < W; y++) {\n            int c = id(H-1,y);\n            if (!wallSet[c] && compId[c] != -1) { bottomComp = compId[c]; break; }\n        }\n        if (topComp == -1 || bottomComp == -1) {\n            // fallback: any two different components from humans\n            topComp = compId[humanPos[0]];\n            bottomComp = (compCnt >=2 ? (topComp==0?1:0) : topComp);\n        }\n    }\n\n    int builderA = -1, builderB = -1;\n    int bestA = INT_MAX, bestB = INT_MAX;\n    // choose closest to wall ends within those comps\n    int endTopCell = wall.front();\n    int endBottomCell = wall.back();\n    for (int i = 0; i < M; i++) {\n        int c = compId[humanPos[i]];\n        if (c == topComp) {\n            int d = abs(humanPos[i]/W - endTopCell/W) + abs(humanPos[i]%W - endTopCell%W);\n            if (d < bestA) { bestA = d; builderA = i; }\n        }\n        if (c == bottomComp) {\n            int d = abs(humanPos[i]/W - endBottomCell/W) + abs(humanPos[i]%W - endBottomCell%W);\n            if (d < bestB) { bestB = d; builderB = i; }\n        }\n    }\n    if (builderA == -1) builderA = 0;\n    if (builderB == -1 || builderB == builderA) {\n        builderB = (builderA==0 ? 1 : 0);\n    }\n\n    vector<int> builderPtr(2, 0);\n    builderPtr[1] = mid;\n\n    vector<int> waitCnt(L, 0);\n    const int MAX_WAIT = 120;\n\n    // Helpers for movement BFS to get next step.\n    auto bfsNextStep = [&](int start, int target, const vector<char>& blockedNow, const vector<char>& forbiddenNow) -> int {\n        if (start == target) return start;\n        vector<int> dist(V, -1);\n        vector<int> parent(V, -1);\n        queue<int> q;\n        if (blockedNow[start]) return start;\n        dist[start] = 0;\n        q.push(start);\n        while (!q.empty()) {\n            int u = q.front(); q.pop();\n            int ux = u / W, uy = u % W;\n            for (int k = 0; k < 4; k++) {\n                int vx = ux + dx4[k], vy = uy + dy4[k];\n                if (!inb(vx,vy)) continue;\n                int v = id(vx,vy);\n                if (blockedNow[v]) continue;\n                if (forbiddenNow[v]) continue;\n                if (dist[v] != -1) continue;\n                dist[v] = dist[u] + 1;\n                parent[v] = u;\n                if (v == target) {\n                    int cur = target;\n                    while (parent[cur] != start) cur = parent[cur];\n                    return cur;\n                }\n                q.push(v);\n            }\n        }\n        return start;\n    };\n\n    auto bfsDistAll = [&](int start, const vector<char>& blockedNow) -> vector<int> {\n        vector<int> dist(V, -1);\n        queue<int> q;\n        if (blockedNow[start]) return dist;\n        dist[start] = 0;\n        q.push(start);\n        while (!q.empty()) {\n            int u = q.front(); q.pop();\n            int ux = u / W, uy = u % W;\n            for (int k = 0; k < 4; k++) {\n                int vx = ux + dx4[k], vy = uy + dy4[k];\n                if (!inb(vx,vy)) continue;\n                int v = id(vx,vy);\n                if (blockedNow[v]) continue;\n                if (dist[v] != -1) continue;\n                dist[v] = dist[u] + 1;\n                q.push(v);\n            }\n        }\n        return dist;\n    };\n\n    auto canBlockNow = [&](int targetCell, const vector<char>& petAtNow, const vector<char>& humanAtNow, const vector<char>& blockedNow) -> bool {\n        if (blockedNow[targetCell]) return false;\n        if (petAtNow[targetCell]) return false;\n        if (humanAtNow[targetCell]) return false;\n        int x = targetCell / W, y = targetCell % W;\n        for (int k = 0; k < 4; k++) {\n            int nx = x + dx4[k], ny = y + dy4[k];\n            if (!inb(nx,ny)) continue;\n            if (petAtNow[id(nx,ny)]) return false; // adjacent contains a pet -> cannot block\n        }\n        return true;\n    };\n\n    // Actual blocked partitions (placed by builders).\n    vector<char> blockedActual(V, 0);\n\n    // Non-builders treat full wall path as obstacle always.\n    vector<char> blockedNonBuilder(V, 0);\n    for (int c = 0; c < V; c++) if (wallSet[c]) blockedNonBuilder[c] = 1;\n\n    // Target maintenance for non-builders.\n    vector<int> targetPos(M, -1);\n\n    auto updateTargets = [&](int turn, const vector<char>& petAtNow, const vector<char>& humanAtNow) {\n        // Count pets per component under wall-obstacle model.\n        vector<int> petCnt(compCnt, 0);\n        for (int i = 0; i < N; i++) {\n            int p = petPos[i];\n            int c = (p >= 0 ? compId[p] : -1);\n            if (c >= 0) petCnt[c]++;\n        }\n\n        vector<double> compScore(compCnt, 0.0);\n        for (int c = 0; c < compCnt; c++) {\n            compScore[c] = (double)compSize[c] / 900.0 * pow(0.5, petCnt[c]);\n        }\n\n        vector<int> comps(compCnt);\n        iota(comps.begin(), comps.end(), 0);\n        sort(comps.begin(), comps.end(), [&](int a, int b){\n            if (compScore[a] != compScore[b]) return compScore[a] > compScore[b];\n            return compSize[a] > compSize[b];\n        });\n\n        int TOP_COMP = min(4, compCnt);\n        vector<int> useComps(comps.begin(), comps.begin() + TOP_COMP);\n\n        // Precompute BFS distance for each non-builder to speed selection.\n        int A = builderA, B = builderB;\n        vector<int> nonBuilders;\n        for (int i = 0; i < M; i++) {\n            if (i == A || i == B) continue;\n            nonBuilders.push_back(i);\n        }\n\n        // We\u2019ll build a preference list of candidate cells and select greedily.\n        unordered_set<int> usedCells;\n        for (int i : nonBuilders) {\n            vector<int> dist = bfsDistAll(humanPos[i], blockedNonBuilder);\n            // select among candidates\n            double bestVal = -1e100;\n            int bestCell = humanPos[i];\n\n            for (int c : useComps) {\n                for (int cell : topCells[c]) {\n                    if (blockedNonBuilder[cell]) continue;\n                    if (dist[cell] < 0) continue; // unreachable within wall-separated side\n                    // Value: component score + prefer shorter distance and deeper interior\n                    int d = dist[cell];\n                    int depth = distInterior[cell];\n                    double val = compScore[c]\n                               + 0.0005 * (double)depth\n                               - 0.0002 * (double)d;\n                    if (val > bestVal) {\n                        bestVal = val;\n                        bestCell = cell;\n                    }\n                }\n            }\n\n            if (usedCells.count(bestCell)) {\n                // fallback: keep old target / don't move too aggressively\n                // (we can allow conflicts sometimes, but spread slightly)\n                // try another candidate\n                double bestVal2 = -1e100;\n                int bestCell2 = bestCell;\n                vector<int> dist = bfsDistAll(humanPos[i], blockedNonBuilder);\n                for (int c : useComps) {\n                    for (int cell : topCells[c]) {\n                        if (blockedNonBuilder[cell]) continue;\n                        if (dist[cell] < 0) continue;\n                        if (usedCells.count(cell)) continue;\n                        int d = dist[cell];\n                        int depth = distInterior[cell];\n                        double val = compScore[c]\n                                   + 0.0005 * (double)depth\n                                   - 0.0002 * (double)d;\n                        if (val > bestVal2) {\n                            bestVal2 = val;\n                            bestCell2 = cell;\n                        }\n                    }\n                }\n                if (bestVal2 > -1e50) bestCell = bestCell2;\n            }\n\n            usedCells.insert(bestCell);\n            targetPos[i] = bestCell;\n        }\n    };\n\n    const int UPDATE_INTERVAL = 6;\n\n    vector<char> petAt(V, 0), humanAt(V, 0);\n    for (int i = 0; i < N; i++) petAt[petPos[i]] = 1;\n    for (int i = 0; i < M; i++) humanAt[humanPos[i]] = 1;\n\n    updateTargets(0, petAt, humanAt);\n\n    auto moveTowardTargetNonBuilder = [&](int i, int nextTarget) -> char {\n        if (humanPos[i] == nextTarget) return '.';\n        // forbid is unnecessary because non-builders treat whole wall as obstacle\n        vector<char> forbidden(V, 0);\n        vector<char> blockedNow = blockedNonBuilder;\n        int nxt = bfsNextStep(humanPos[i], nextTarget, blockedNow, forbidden);\n        if (nxt == humanPos[i]) return '.';\n        return moveChar(humanPos[i], nxt);\n    };\n\n    // For builders, we need to move without stepping onto cells that the other builder still needs to block.\n    auto obstaclesBuilder = [&](int builderId) -> vector<char> {\n        // builderId=0 -> works on [0, mid)\n        // builderId=1 -> works on [mid, L)\n        vector<char> obs = blockedActual; // actual partitions are obstacles\n        if (builderId == 0) {\n            for (int c = 0; c < V; c++) {\n                if (wallSet[c] && !blockedActual[c]) {\n                    int wi = wallIndex[c];\n                    if (wi >= mid) obs[c] = 1; // avoid interfering with builder 1 side\n                }\n            }\n        } else {\n            for (int c = 0; c < V; c++) {\n                if (wallSet[c] && !blockedActual[c]) {\n                    int wi = wallIndex[c];\n                    if (wi < mid) obs[c] = 1;\n                }\n            }\n        }\n        return obs;\n    };\n\n    auto builderNextAdjMove = [&](int builderId, int wcell, int bpos, const vector<char>& forbiddenNow) -> char {\n        // Choose a neighbor cell of wcell (not obstacle) and BFS to it, then move one step.\n        vector<char> obs = obstaclesBuilder(builderId);\n        // Ensure target adjacency candidate is not forbidden.\n        vector<int> cand;\n        int wx = wcell / W, wy = wcell % W;\n        for (int k = 0; k < 4; k++) {\n            int nx = wx + dx4[k], ny = wy + dy4[k];\n            if (!inb(nx, ny)) continue;\n            int v = id(nx, ny);\n            if (obs[v]) continue;\n            if (forbiddenNow[v]) continue;\n            cand.push_back(v);\n        }\n        if (cand.empty()) return '.';\n\n        // BFS from bpos to all\n        vector<int> dist(V, -1);\n        vector<int> parent(V, -1);\n        queue<int> q;\n        if (obs[bpos]) return '.';\n        dist[bpos] = 0;\n        q.push(bpos);\n\n        int best = -1;\n        int bestD = INT_MAX;\n\n        while (!q.empty()) {\n            int u = q.front(); q.pop();\n            if (dist[u] > bestD) continue;\n            // check if u is one of candidates\n            for (int v : cand) {\n                if (u == v && dist[u] < bestD) {\n                    bestD = dist[u];\n                    best = u;\n                }\n            }\n            int ux = u / W, uy = u % W;\n            for (int k = 0; k < 4; k++) {\n                int vx = ux + dx4[k], vy = uy + dy4[k];\n                if (!inb(vx,vy)) continue;\n                int v = id(vx,vy);\n                if (obs[v]) continue;\n                if (forbiddenNow[v]) continue;\n                if (dist[v] != -1) continue;\n                dist[v] = dist[u] + 1;\n                parent[v] = u;\n                q.push(v);\n            }\n        }\n        if (best == -1) return '.';\n\n        // reconstruct next step towards best\n        int cur = best;\n        while (parent[cur] != bpos && parent[cur] != -1) cur = parent[cur];\n        if (parent[cur] == -1) return '.';\n        return moveChar(bpos, cur);\n    };\n\n    // Main interactive loop\n    for (int turn = 0; turn < 300; turn++) {\n        // rebuild petAt/humanAt\n        fill(petAt.begin(), petAt.end(), 0);\n        for (int i = 0; i < N; i++) petAt[petPos[i]] = 1;\n        fill(humanAt.begin(), humanAt.end(), 0);\n        for (int i = 0; i < M; i++) humanAt[humanPos[i]] = 1;\n\n        if (turn % UPDATE_INTERVAL == 0) {\n            updateTargets(turn, petAt, humanAt);\n        }\n\n        vector<char> action(M, '.');\n\n        // Determine planned blocks this turn by builders, to respect movement legality.\n        // (Even though non-builders avoid wallSet, builders must avoid these cells if moving.)\n        vector<char> forbidden(V, 0);\n\n        // Builder 0\n        vector<pair<int,int>> builderInfo = {{builderA,0},{builderB,1}};\n        for (auto [hid,bid] : builderInfo) {\n            if (hid < 0) continue;\n            int ptr = builderPtr[bid];\n            if (ptr >= L) continue;\n            int wcell = wall[ptr];\n            int bpos = humanPos[hid];\n\n            if (isAdj(bpos, wcell)) {\n                if (canBlockNow(wcell, petAt, humanAt, blockedActual)) {\n                    action[hid] = blockChar(bpos, wcell);\n                    forbidden[wcell] = 1; // other builders (moving) must not step here\n                } else {\n                    // wait\n                    action[hid] = '.';\n                    // increase wait count for this wall cell (optional)\n                    waitCnt[ptr]++;\n                    if (waitCnt[ptr] > MAX_WAIT) {\n                        // skip trying this cell (keeps heuristic moving); gaps hurt but prevents deadlock\n                        builderPtr[bid]++;\n                        waitCnt[ptr] = 0;\n                    }\n                }\n            } else {\n                // move toward adjacency\n                action[hid] = builderNextAdjMove(bid, wcell, bpos, forbidden);\n            }\n        }\n\n        // Non-builders: move one step toward current targetPos[i].\n        for (int i = 0; i < M; i++) {\n            if (i == builderA || i == builderB) continue;\n            if (targetPos[i] == -1) targetPos[i] = humanPos[i];\n            action[i] = moveTowardTargetNonBuilder(i, targetPos[i]);\n        }\n\n        // Output\n        string out(M, '.');\n        for (int i = 0; i < M; i++) out[i] = action[i];\n        cout << out << \"\\n\" << flush;\n\n        // Apply human actions: update humanPos and blockedActual (for lowercase).\n        for (int i = 0; i < M; i++) {\n            char c = action[i];\n            if (c == '.') continue;\n            if (c >= 'A' && c <= 'Z') {\n                int x = humanPos[i] / W, y = humanPos[i] % W;\n                if (c == 'U') x--;\n                if (c == 'D') x++;\n                if (c == 'L') y--;\n                if (c == 'R') y++;\n                humanPos[i] = id(x,y);\n            } else {\n                // lowercase: block the adjacent cell in that direction\n                int x = humanPos[i] / W, y = humanPos[i] % W;\n                int bx = x, by = y;\n                if (c == 'u') bx--;\n                if (c == 'd') bx++;\n                if (c == 'l') by--;\n                if (c == 'r') by++;\n                int cell = id(bx,by);\n                if (0 <= cell && cell < V) blockedActual[cell] = 1;\n\n                // If this cell is the current target wall cell for a builder, advance its pointer.\n                // (We can identify by wallIndex.)\n                int wi = wallIndex[cell];\n                if (wi >= 0) {\n                    if (builderPtr[0] == wi) builderPtr[0]++;\n                    if (builderPtr[1] == wi) builderPtr[1]++;\n                }\n            }\n        }\n\n        // Read pet moves and update petPos accordingly.\n        for (int i = 0; i < N; i++) {\n            string mv;\n            cin >> mv;\n            int p = petPos[i];\n            int x = p / W, y = p % W;\n            if (mv != \".\") {\n                for (char ch : mv) {\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                petPos[i] = id(x,y);\n            }\n        }\n    }\n\n    return 0;\n}","ahc009":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int H = 20;\nstatic constexpr int W = 20;\nstatic constexpr int N = H * W;\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> hwall(H); // between (i,j) and (i,j+1), size 20x19\n    for (int i = 0; i < H; i++) {\n        cin >> hwall[i]; // length 19\n    }\n    vector<string> vwall(H - 1); // between (i,j) and (i+1,j), size 19x20\n    for (int i = 0; i < H - 1; i++) {\n        cin >> vwall[i]; // length 20\n    }\n\n    int start = si * W + sj;\n    int target = ti * W + tj;\n    long double P = (long double)p;\n    long double Q = 1.0L - P;\n\n    // direction indices: 0=U, 1=D, 2=L, 3=R\n    const char dirChar[4] = {'U','D','L','R'};\n    int moveTo[N][4];\n\n    auto id = [&](int r, int c) { return r * W + c; };\n\n    for (int r = 0; r < H; r++) {\n        for (int c = 0; c < W; c++) {\n            int v = id(r, c);\n\n            // U\n            if (r == 0) moveTo[v][0] = v;\n            else {\n                // wall between (r-1,c) and (r,c) is vwall[r-1][c]\n                if (vwall[r-1][c] == '1') moveTo[v][0] = v;\n                else moveTo[v][0] = id(r-1, c);\n            }\n            // D\n            if (r == H-1) moveTo[v][1] = v;\n            else {\n                if (vwall[r][c] == '1') moveTo[v][1] = v;\n                else moveTo[v][1] = id(r+1, c);\n            }\n            // L\n            if (c == 0) moveTo[v][2] = v;\n            else {\n                // wall between (r,c-1) and (r,c) is hwall[r][c-1]\n                if (hwall[r][c-1] == '1') moveTo[v][2] = v;\n                else moveTo[v][2] = id(r, c-1);\n            }\n            // R\n            if (c == W-1) moveTo[v][3] = v;\n            else {\n                // wall between (r,c) and (r,c+1) is hwall[r][c]\n                if (hwall[r][c] == '1') moveTo[v][3] = v;\n                else moveTo[v][3] = id(r, c+1);\n            }\n        }\n    }\n\n    // BFS distances from target in the static grid graph (ignoring forgetting)\n    const int INF = 1e9;\n    vector<int> dist(N, INF);\n    queue<int> q;\n    dist[target] = 0;\n    q.push(target);\n\n    while (!q.empty()) {\n        int v = q.front(); q.pop();\n        int dv = dist[v];\n        for (int a = 0; a < 4; a++) {\n            int u = moveTo[v][a];\n            if (u == v) continue; // blocked edge\n            if (dist[u] > dv + 1) {\n                dist[u] = dv + 1;\n                q.push(u);\n            }\n        }\n    }\n\n    // Horizon\n    int L = 200;\n\n    vector<long double> distOverQ(N);\n    for (int v = 0; v < N; v++) {\n        distOverQ[v] = (long double)dist[v] / Q; // Q>0 guaranteed since p<=0.5\n    }\n\n    // potential[t][v], where t is 0-indexed (meaning \"after next action at time t+1\")\n    // potential = max(0, 401 - (time_est)) if time_est<=L else 0\n    vector<long double> pot((size_t)L * N, 0.0L);\n    for (int t = 0; t < L; t++) {\n        int tNext = t + 1;\n        for (int v = 0; v < N; v++) {\n            long double te = (long double)tNext + distOverQ[v]; // expected time estimate\n            if (te <= (long double)L) {\n                long double val = 401.0L - te;\n                if (val < 0) val = 0;\n                pot[(size_t)t * N + v] = val;\n            }\n        }\n    }\n\n    auto exactExpected = [&](const string &s) -> long double {\n        vector<long double> dp(N, 0.0L), dpNext(N, 0.0L);\n        dp[start] = 1.0L;\n        long double ans = 0.0L;\n\n        for (int t = 0; t < (int)s.size(); t++) {\n            int a = -1;\n            if (s[t] == 'U') a = 0;\n            else if (s[t] == 'D') a = 1;\n            else if (s[t] == 'L') a = 2;\n            else a = 3;\n\n            fill(dpNext.begin(), dpNext.end(), 0.0L);\n            long double probReach = 0.0L;\n\n            for (int v = 0; v < N; v++) {\n                if (v == target) continue;\n                long double dv = dp[v];\n                if (dv == 0.0L) continue;\n\n                int v2 = moveTo[v][a];\n                if (v2 == target) {\n                    probReach += dv * Q;      // remembered and moved into target\n                    dpNext[v] += dv * P;     // forgotten => stay at v\n                } else {\n                    dpNext[v2] += dv * Q;    // remembered and moved\n                    dpNext[v] += dv * P;     // forgotten => stay\n                }\n            }\n\n            ans += probReach * (401.0L - (long double)(t+1));\n            dp.swap(dpNext);\n        }\n        return ans;\n    };\n\n    int K = 3; // number of diversified candidates\n    vector<string> candidates;\n    candidates.reserve(K);\n\n    for (int cand = 0; cand < K; cand++) {\n        // RNG seed\n        long long seed = 123456789LL;\n        seed ^= (long long)si * 10007 + sj * 1009;\n        seed ^= (long long)ti * 10037 + tj * 997;\n        seed ^= (long long)((p + 1e-12) * 100000.0);\n        seed ^= (long long)cand * 1000003LL;\n        std::mt19937 rng((uint32_t)seed);\n\n        long double eps = (cand == 0 ? 0.0L : 0.12L);\n\n        vector<long double> dp(N, 0.0L), dpNext(N, 0.0L);\n        vector<long double> bestBuf(N, 0.0L), secondBuf(N, 0.0L);\n\n        dp[start] = 1.0L;\n        string seq;\n        seq.reserve(L);\n\n        for (int t = 0; t < L; t++) {\n            long double bestScore = -1e100L, secondScore = -1e100L;\n            int bestA = 0, secondA = 0;\n            bool hasSecond = false;\n\n            for (int a = 0; a < 4; a++) {\n                fill(dpNext.begin(), dpNext.end(), 0.0L);\n                long double probReach = 0.0L;\n\n                for (int v = 0; v < N; v++) {\n                    if (v == target) continue;\n                    long double dv = dp[v];\n                    if (dv == 0.0L) continue;\n\n                    int v2 = moveTo[v][a];\n                    if (v2 == target) {\n                        probReach += dv * Q;\n                        dpNext[v] += dv * P;\n                    } else {\n                        dpNext[v2] += dv * Q;\n                        dpNext[v] += dv * P;\n                    }\n                }\n\n                long double score = probReach * (401.0L - (long double)(t + 1));\n                // heuristic future value\n                size_t base = (size_t)t * N;\n                for (int u = 0; u < N; u++) {\n                    if (u == target) continue;\n                    long double du = dpNext[u];\n                    if (du == 0.0L) continue;\n                    score += du * pot[base + u];\n                }\n\n                if (score > bestScore) {\n                    secondScore = bestScore;\n                    secondA = bestA;\n                    hasSecond = true;\n                    bestScore = score;\n                    bestA = a;\n                    bestBuf = dpNext;\n                } else if (!hasSecond || score > secondScore) {\n                    secondScore = score;\n                    secondA = a;\n                    hasSecond = true;\n                    secondBuf = dpNext;\n                }\n            }\n\n            int chosenA = bestA;\n            if (hasSecond && eps > 0.0L) {\n                // sometimes choose second best\n                long double r = (long double)rng() / (long double)rng.max();\n                if (r < eps) chosenA = secondA;\n            }\n\n            if (chosenA == bestA) dp = bestBuf;\n            else dp = secondBuf;\n\n            seq.push_back(dirChar[chosenA]);\n        }\n\n        candidates.push_back(seq);\n    }\n\n    // Choose best by exact expected value\n    long double bestVal = -1e100L;\n    int bestIdx = 0;\n    for (int i = 0; i < (int)candidates.size(); i++) {\n        long double val = exactExpected(candidates[i]);\n        if (val > bestVal) {\n            bestVal = val;\n            bestIdx = i;\n        }\n    }\n\n    cout << candidates[bestIdx] << \"\\n\";\n    return 0;\n}","ahc010":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 30;\nstatic constexpr int CELLS = N * N;          // 900\nstatic constexpr int DIRS = 4;\nstatic constexpr int STATES = CELLS * DIRS; // 3600\n\n// Directions: 0=left, 1=up, 2=right, 3=down\nstatic constexpr int di[4] = {0, -1, 0, 1};\nstatic constexpr int dj[4] = {-1, 0, 1, 0};\n\nstruct EvalResult {\n    long long score;\n    int best1;\n    int best2;\n    int numCycles;\n};\n\nstatic int8_t toBase[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\n// toRot[t][r][d] = exit direction (0..3) or -1\nstatic int8_t toRot[8][4][4];\n\nstatic int16_t neighCell[CELLS][4]; // neighCell[c][exitDir] = neighbor cell index or -1\n\nstatic uint8_t tileType[CELLS];     // input tile t\nstatic uint8_t rotCurr[CELLS];\nstatic uint8_t rotBest[CELLS];\n\nstatic int nextState[STATES];\nstatic int vis[STATES];\nstatic int posInPath[STATES];\nstatic int pathArr[STATES];\n\nstatic inline long long llmax0(long long x){ return x; }\n\nEvalResult evaluate(const uint8_t rot[CELLS]) {\n    // Build functional graph transitions for all states\n    for (int c = 0; c < CELLS; c++) {\n        int t = tileType[c];\n        int r = rot[c];\n        for (int d = 0; d < 4; d++) {\n            int v = c * 4 + d; // state: enter from direction d\n            int exitDir = toRot[t][r][d];\n            if (exitDir < 0) {\n                nextState[v] = -1;\n                continue;\n            }\n            int nb = neighCell[c][exitDir];\n            if (nb < 0) {\n                nextState[v] = -1;\n                continue;\n            }\n            int entryNext = (exitDir + 2) & 3;\n            nextState[v] = nb * 4 + entryNext;\n        }\n    }\n\n    // Find all directed cycles in this functional graph\n    int best1 = 0, best2 = 0, cnt1 = 0, numCycles = 0;\n    memset(vis, 0, sizeof(vis));\n\n    for (int v0 = 0; v0 < STATES; v0++) {\n        if (vis[v0] != 0) continue;\n\n        int cur = v0;\n        int pathLen = 0;\n        while (cur != -1 && vis[cur] == 0) {\n            vis[cur] = 1;              // in current traversal\n            posInPath[cur] = pathLen; // position in pathArr\n            pathArr[pathLen++] = cur;\n            cur = nextState[cur];\n        }\n\n        if (cur != -1 && vis[cur] == 1) {\n            // Found a cycle: nodes pathArr[posInPath[cur] .. pathLen-1]\n            int len = pathLen - posInPath[cur];\n            numCycles++;\n\n            if (len > best1) {\n                best2 = best1;\n                best1 = len;\n                cnt1 = 1;\n            } else if (len == best1) {\n                cnt1++;\n                if (cnt1 >= 2) best2 = best1;\n            } else if (len > best2) {\n                best2 = len;\n            }\n        }\n\n        // Mark path nodes as done\n        for (int i = 0; i < pathLen; i++) vis[pathArr[i]] = 2;\n    }\n\n    long long score = (numCycles >= 2) ? 1LL * best1 * best2 : 0LL;\n    return {score, best1, best2, numCycles};\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // Precompute rotation mapping\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                // d is global entry direction after rotation by r (CCW)\n                // original entry direction is d_orig = (d + r) mod 4\n                int d_orig = (d + r) & 3;\n                int exit_orig = toBase[t][d_orig];\n                if (exit_orig < 0) {\n                    toRot[t][r][d] = -1;\n                } else {\n                    // exit direction rotates with tile: exit_global = exit_orig - r\n                    toRot[t][r][d] = (exit_orig - r + 4) & 3;\n                }\n            }\n        }\n    }\n\n    // Read input\n    for (int i = 0; i < N; i++) {\n        string s;\n        cin >> s;\n        for (int j = 0; j < N; j++) {\n            int t = s[j] - '0';\n            tileType[i * N + j] = (uint8_t)t;\n        }\n    }\n\n    // Precompute neighbor cells\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            int c = i * N + j;\n            for (int dir = 0; dir < 4; dir++) {\n                int ni = i + di[dir], nj = j + dj[dir];\n                if (0 <= ni && ni < N && 0 <= nj && nj < N) neighCell[c][dir] = ni * N + nj;\n                else neighCell[c][dir] = -1;\n            }\n        }\n    }\n\n    // Random engine\n    mt19937_64 rng((uint64_t)chrono::steady_clock::now().time_since_epoch().count());\n    auto randInt = [&](int L, int R) -> int {\n        uniform_int_distribution<int> dist(L, R);\n        return dist(rng);\n    };\n    auto rand01 = [&]() -> double {\n        return uniform_real_distribution<double>(0.0, 1.0)(rng);\n    };\n\n    const double TIME_LIMIT = 1.85; // seconds\n    auto startTime = chrono::steady_clock::now();\n    auto elapsedSec = [&]() -> double {\n        return chrono::duration<double>(chrono::steady_clock::now() - startTime).count();\n    };\n\n    long long bestScore = -1;\n    int bestRestart = 0;\n\n    // Multi-restart SA\n    for (int restart = 0; restart < 4; restart++) {\n        if (elapsedSec() > TIME_LIMIT) break;\n\n        if (restart == 0) {\n            // deterministic init\n            for (int c = 0; c < CELLS; c++) rotCurr[c] = 0;\n        } else {\n            for (int c = 0; c < CELLS; c++) rotCurr[c] = (uint8_t)randInt(0, 3);\n        }\n\n        EvalResult curRes = evaluate(rotCurr);\n        long long curScore = curRes.score;\n\n        if (curScore > bestScore) {\n            bestScore = curScore;\n            bestRestart = restart;\n            memcpy(rotBest, rotCurr, CELLS);\n        }\n\n        const double tempStart = 1e7;\n        const double tempEnd = 1e3;\n\n        while (elapsedSec() < TIME_LIMIT) {\n            int c = rng() % CELLS;\n            uint8_t oldR = rotCurr[c];\n\n            // Local continuity estimate to bias rotation proposals\n            int t = tileType[c];\n            int local[4];\n            for (int r = 0; r < 4; r++) {\n                int cnt = 0;\n                for (int entry = 0; entry < 4; entry++) {\n                    int exitDir = toRot[t][r][entry];\n                    if (exitDir < 0) continue;\n                    int nb = neighCell[c][exitDir];\n                    if (nb < 0) continue;\n                    int entryNext = (exitDir + 2) & 3;\n                    int nbT = tileType[nb];\n                    int nbR = rotCurr[nb];\n                    if (toRot[nbT][nbR][entryNext] >= 0) cnt++;\n                }\n                local[r] = cnt;\n            }\n\n            uint8_t newR = oldR;\n\n            if (rand01() < 0.15) {\n                // exploration\n                do { newR = (uint8_t)((oldR + 1 + (rng() % 3)) & 3); } while (newR == oldR);\n            } else {\n                // pick among best local rotations excluding old\n                int best = -1;\n                for (int r = 0; r < 4; r++) if ((uint8_t)r != oldR) best = max(best, local[r]);\n                if (best < 0) continue;\n\n                int threshold = best - 1;\n                vector<int> cand;\n                for (int r = 0; r < 4; r++) {\n                    if ((uint8_t)r == oldR) continue;\n                    if (local[r] >= threshold) cand.push_back(r);\n                }\n                if (cand.empty()) {\n                    for (int r = 0; r < 4; r++) if ((uint8_t)r != oldR) cand.push_back(r);\n                }\n                newR = (uint8_t)cand[rng() % cand.size()];\n            }\n\n            if (newR == oldR) continue;\n\n            rotCurr[c] = newR;\n            EvalResult nres = evaluate(rotCurr);\n            long long newScore = nres.score;\n\n            long long delta = newScore - curScore;\n\n            double prog = elapsedSec() / TIME_LIMIT;\n            double temp = tempEnd + (tempStart - tempEnd) * (1.0 - prog);\n            temp = max(temp, 1e-9);\n\n            bool accept = false;\n            if (delta >= 0) {\n                accept = true;\n            } else {\n                double prob = exp((double)delta / temp);\n                if (rand01() < prob) accept = true;\n            }\n\n            if (accept) {\n                curScore = newScore;\n                if (curScore > bestScore) {\n                    bestScore = curScore;\n                    memcpy(rotBest, rotCurr, CELLS);\n                }\n            } else {\n                rotCurr[c] = oldR;\n            }\n        }\n    }\n\n    // Output rotations as a 900-char string\n    string out;\n    out.reserve(CELLS);\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            int c = i * N + j;\n            out.push_back(char('0' + (int)rotBest[c]));\n        }\n    }\n    cout << out << \"\\n\";\n    return 0;\n}","ahc011":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct DSU {\n    int n;\n    vector<int> p, sz;\n    DSU(int n_=0){ init(n_); }\n    void init(int n_) {\n        n = n_;\n        p.resize(n);\n        sz.resize(n);\n        reset();\n    }\n    void reset() {\n        for(int i=0;i<n;i++){\n            p[i]=i;\n            sz[i]=1;\n        }\n    }\n    int find(int x){\n        while(p[x]!=x){\n            p[x]=p[p[x]];\n            x=p[x];\n        }\n        return x;\n    }\n    void unite(int a,int b){\n        a=find(a); b=find(b);\n        if(a==b) return;\n        if(sz[a]<sz[b]) swap(a,b);\n        p[b]=a;\n        sz[a]+=sz[b];\n    }\n};\n\nstruct EvalRes {\n    int bestTree;   // exact: max component that is a tree (connected acyclic)\n    int bestFitness; // smoother: max over components of (verts - alpha*extraCycles)\n};\n\nstruct Evaluator {\n    int N, M;\n    vector<pair<int,int>> vertEdges; // (top,bottom)\n    vector<pair<int,int>> horEdges;  // (left,right)\n    DSU dsu;\n    vector<int> compVerts, compEdges;\n\n    static constexpr int DOWN = 8;\n    static constexpr int UP   = 2;\n    static constexpr int RIGHT= 4;\n    static constexpr int LEFT = 1;\n\n    Evaluator(int N_): N(N_), M(N_*N_), dsu(M) {\n        vertEdges.reserve((N-1)*N);\n        horEdges.reserve(N*(N-1));\n        for(int i=0;i<N-1;i++){\n            for(int j=0;j<N;j++){\n                int top = i*N+j;\n                int bot = (i+1)*N+j;\n                vertEdges.push_back({top, bot});\n            }\n        }\n        for(int i=0;i<N;i++){\n            for(int j=0;j<N-1;j++){\n                int L = i*N+j;\n                int R = i*N+(j+1);\n                horEdges.push_back({L, R});\n            }\n        }\n        compVerts.assign(M,0);\n        compEdges.assign(M,0);\n    }\n\n    inline bool edgeExists(uint8_t aMask, uint8_t bMask, bool vertical) const {\n        if(aMask==0 || bMask==0) return false;\n        if(vertical){\n            // a is top: needs down, b is bottom: needs up\n            return (aMask & DOWN) && (bMask & UP);\n        }else{\n            // a is left: needs right, b is right: needs left\n            return (aMask & RIGHT) && (bMask & LEFT);\n        }\n    }\n\n    EvalRes eval(const vector<uint8_t>& b) {\n        dsu.reset();\n\n        // Build DSU from existing edges\n        for(auto [top, bot] : vertEdges){\n            uint8_t mt = b[top], mb = b[bot];\n            if(edgeExists(mt, mb, true)) dsu.unite(top, bot);\n        }\n        for(auto [L, R] : horEdges){\n            uint8_t mL = b[L], mR = b[R];\n            if(edgeExists(mL, mR, false)) dsu.unite(L, R);\n        }\n\n        fill(compVerts.begin(), compVerts.end(), 0);\n        for(int v=0; v<M; v++){\n            if(b[v]==0) continue; // empty not a vertex\n            compVerts[dsu.find(v)]++;\n        }\n\n        fill(compEdges.begin(), compEdges.end(), 0);\n        // Count edges per component\n        for(auto [top, bot] : vertEdges){\n            uint8_t mt = b[top], mb = b[bot];\n            if(edgeExists(mt, mb, true)){\n                compEdges[dsu.find(top)]++;\n            }\n        }\n        for(auto [L, R] : horEdges){\n            uint8_t mL = b[L], mR = b[R];\n            if(edgeExists(mL, mR, false)){\n                compEdges[dsu.find(L)]++;\n            }\n        }\n\n        int bestTree = 0;\n        int bestFitness = 0;\n        const int ALPHA = 2; // penalize cycles more strongly\n\n        for(int r=0; r<M; r++){\n            int vcnt = compVerts[r];\n            if(vcnt==0) continue;\n            int ecnt = compEdges[r];\n            int extra = ecnt - (vcnt - 1); // >= 0\n            if(extra==0) bestTree = max(bestTree, vcnt);\n\n            int fitness = vcnt - ALPHA * extra; // tree => fitness=vcnt, otherwise lower\n            if(fitness < 0) fitness = 0;\n            bestFitness = max(bestFitness, fitness);\n        }\n        return {bestTree, bestFitness};\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    long long T;\n    cin >> N >> T;\n    vector<string> s(N);\n    for(int i=0;i<N;i++) cin >> s[i];\n\n    int M = N*N;\n    vector<uint8_t> b(M);\n    int emptyIdx = -1;\n\n    auto hexToVal = [&](char c)->int{\n        if('0'<=c && c<='9') return c-'0';\n        return 10 + (c-'a');\n    };\n\n    for(int i=0;i<N;i++){\n        for(int j=0;j<N;j++){\n            int v = hexToVal(s[i][j]);\n            int idx = i*N+j;\n            b[idx] = (uint8_t)v;\n            if(v==0) emptyIdx = idx;\n        }\n    }\n\n    Evaluator evaluator(N);\n\n    int fullTree = N*N - 1;\n\n    auto start = chrono::steady_clock::now();\n    auto elapsedSec = [&]()->double{\n        return chrono::duration<double>(chrono::steady_clock::now()-start).count();\n    };\n\n    // scoring scalar for annealing/beam\n    auto scoreScalar = [&](const EvalRes& r)->int{\n        // bestTree dominates strongly\n        return r.bestTree * 1000 + r.bestFitness;\n    };\n\n    int bestTreeGlobal = evaluator.eval(b).bestTree;\n    vector<char> bestMovesGlobal;\n    int bestKGlobal = (int)bestMovesGlobal.size();\n\n    // RNG\n    uint64_t seed = (uint64_t)chrono::steady_clock::now().time_since_epoch().count();\n    seed ^= 0x9e3779b97f4a7c15ULL * (uint64_t)N;\n    seed ^= (uint64_t)b[emptyIdx] + 0x1234567ULL;\n    for(int i=0;i<M;i++) seed = seed * 1315423911u + b[i];\n    mt19937_64 rng(seed);\n\n    int dr[4] = {-1, 1, 0, 0};\n    int dc[4] = {0, 0, -1, 1};\n    char dirChar[4] = {'U','D','L','R'};\n    int opp[4] = {1,0,3,2};\n\n    auto inBounds = [&](int r,int c)->bool{\n        return 0<=r && r<N && 0<=c && c<N;\n    };\n\n    // More restarts with faster evaluation\n    int maxRestarts = 35;\n    double LIMIT = 2.88; // keep margin\n\n    for(int restart=0; restart<maxRestarts; restart++){\n        if(elapsedSec() > LIMIT) break;\n\n        vector<uint8_t> curB = b;\n        int e = emptyIdx;\n        vector<char> moves;\n        moves.reserve((size_t)T);\n\n        EvalRes curEval = evaluator.eval(curB);\n\n        int bestTreeRun = curEval.bestTree;\n        vector<char> bestMovesRun = moves;\n        int bestKRun = 0;\n\n        if(bestTreeRun > bestTreeGlobal){\n            bestTreeGlobal = bestTreeRun;\n            bestMovesGlobal = bestMovesRun;\n            bestKGlobal = bestKRun;\n        } else if(bestTreeRun == bestTreeGlobal && bestKRun < bestKGlobal){\n            bestMovesGlobal = bestMovesRun;\n            bestKGlobal = bestKRun;\n        }\n\n        int prevDir = -1;\n\n        for(long long step=0; step<T; step++){\n            if(curEval.bestTree == fullTree) break;\n            if(elapsedSec() > LIMIT) break;\n\n            int er = e / N, ec = e % N;\n\n            struct Cand1 {\n                int dir;\n                int nei;\n                EvalRes r1;\n                int sc1;\n                int bestLookaheadSc; // max over dir2\n            };\n\n            vector<Cand1> cands;\n\n            // 1-step candidates\n            for(int dir=0; dir<4; dir++){\n                int nr = er + dr[dir], nc = ec + dc[dir];\n                if(!inBounds(nr,nc)) continue;\n                int nei = nr*N + nc;\n\n                swap(curB[e], curB[nei]);\n                EvalRes r1 = evaluator.eval(curB);\n                swap(curB[e], curB[nei]);\n\n                Cand1 c;\n                c.dir = dir;\n                c.nei = nei;\n                c.r1 = r1;\n                c.sc1 = scoreScalar(r1);\n                c.bestLookaheadSc = c.sc1; // default\n                cands.push_back(c);\n            }\n            if(cands.empty()) break;\n\n            // optionally avoid immediate backtracking (but don't forbid)\n            if(prevDir != -1){\n                double pAllowBack = 0.25;\n                vector<Cand1> filtered;\n                filtered.reserve(cands.size());\n                for(auto &c : cands){\n                    if(c.dir == opp[prevDir]){\n                        if(uniform_real_distribution<double>(0,1)(rng) < pAllowBack) filtered.push_back(c);\n                    }else filtered.push_back(c);\n                }\n                if(!filtered.empty()) cands.swap(filtered);\n            }\n\n            // beam: keep top B by 1-step score\n            int B = min(3, (int)cands.size());\n            nth_element(cands.begin(), cands.begin()+B, cands.end(),\n                        [&](const Cand1& a, const Cand1& b){ return a.sc1 > b.sc1; });\n            cands.resize(B);\n\n            // 2-step lookahead for each remaining candidate:\n            // choose the best dir2 result score (max) and set bestLookaheadSc\n            for(auto &c1 : cands){\n                swap(curB[e], curB[c1.nei]); // apply move1\n                int e1 = c1.nei;\n\n                int lr = e1 / N, lc = e1 % N;\n\n                int bestSc2 = c1.sc1; // if no 2nd move, remain\n                bool hasSecond = false;\n\n                for(int dir2=0; dir2<4; dir2++){\n                    int nr = lr + dr[dir2], nc = lc + dc[dir2];\n                    if(!inBounds(nr,nc)) continue;\n                    int e2 = nr*N + nc;\n\n                    // apply move2\n                    swap(curB[e1], curB[e2]);\n                    EvalRes r2 = evaluator.eval(curB);\n                    int sc2 = scoreScalar(r2);\n                    bestSc2 = max(bestSc2, sc2);\n                    hasSecond = true;\n\n                    // undo\n                    swap(curB[e1], curB[e2]);\n                }\n\n                if(hasSecond) c1.bestLookaheadSc = bestSc2;\n                else c1.bestLookaheadSc = c1.sc1;\n\n                // undo move1\n                swap(curB[e], curB[c1.nei]);\n            }\n\n            // pick among candidates using annealing on bestLookaheadSc\n            int maxSc = -1;\n            for(auto &c : cands) maxSc = max(maxSc, c.bestLookaheadSc);\n\n            // temp schedule\n            double temp = 6000.0 - (5500.0 * (double)step / (double)T);\n            if(temp < 1500) temp = 1500;\n\n            // roulette\n            vector<double> w(cands.size());\n            double sumW = 0.0;\n            for(size_t i=0;i<cands.size();i++){\n                double diff = (double)(cands[i].bestLookaheadSc - maxSc); // <=0\n                double x = diff / temp;\n                if(x < -50) x = -50;\n                w[i] = exp(x);\n                sumW += w[i];\n            }\n            uniform_real_distribution<double> dist(0.0, sumW);\n            double pick = dist(rng);\n\n            size_t chosen = 0;\n            double acc = 0.0;\n            for(size_t i=0;i<cands.size();i++){\n                acc += w[i];\n                if(acc >= pick){\n                    chosen = i;\n                    break;\n                }\n            }\n\n            // execute chosen move1\n            auto chosenC = cands[chosen];\n            swap(curB[e], curB[chosenC.nei]);\n            e = chosenC.nei;\n            moves.push_back(dirChar[chosenC.dir]);\n            prevDir = chosenC.dir;\n\n            curEval = chosenC.r1;\n\n            // update run/best\n            if(curEval.bestTree > bestTreeRun){\n                bestTreeRun = curEval.bestTree;\n                bestMovesRun = moves;\n                bestKRun = (int)moves.size();\n            } else if(curEval.bestTree == bestTreeRun && (int)moves.size() < bestKRun){\n                bestMovesRun = moves;\n                bestKRun = (int)moves.size();\n            }\n\n            if(bestTreeRun > bestTreeGlobal){\n                bestTreeGlobal = bestTreeRun;\n                bestMovesGlobal = bestMovesRun;\n                bestKGlobal = bestKRun;\n            } else if(bestTreeRun == bestTreeGlobal && bestKRun < bestKGlobal){\n                bestMovesGlobal = bestMovesRun;\n                bestKGlobal = bestKRun;\n            }\n\n            if(bestTreeGlobal == fullTree) break; // can't do better in S\n        }\n\n        if(bestTreeGlobal == fullTree) break;\n    }\n\n    // output only performed moves (<=T)\n    string out;\n    out.reserve(bestMovesGlobal.size());\n    for(char c: bestMovesGlobal) out.push_back(c);\n    cout << out << '\\n';\n    return 0;\n}","ahc012":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\n\nstatic const ll LIM = 1000000000LL;\n\nstruct Point {\n    ll x, y;\n};\n\nstruct Candidate {\n    int orient; // 0..3\n    int V, H;\n    vector<ll> cuts1; // proj1 cuts\n    vector<ll> cuts2; // proj2 cuts\n    int matched = -1; // sum min(a_d, b_d)\n};\n\nstatic uint64_t splitmix64(uint64_t &x) {\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\nstruct RNG {\n    uint64_t state;\n    explicit RNG(uint64_t seed) : state(seed) {}\n    ll nextLL(ll l, ll r) {\n        return (ll)(splitmix64(state) % (uint64_t)(r - l + 1)) + l;\n    }\n    int nextInt(int l, int r) { return (int)nextLL(l, r); }\n};\n\nstatic inline ll proj_value(int orient, const Point& p, int which) {\n    // which=0 -> proj1, which=1 -> proj2\n    // Orient definitions:\n    // 0: (x, y)\n    // 1: (x, x+y)\n    // 2: (x, x-y)\n    // 3: (x+y, x-y)\n    if (orient == 0) {\n        if (which == 0) return p.x;\n        else return p.y;\n    } else if (orient == 1) {\n        if (which == 0) return p.x;\n        else return p.x + p.y;\n    } else if (orient == 2) {\n        if (which == 0) return p.x;\n        else return p.x - p.y;\n    } else { // orient == 3\n        if (which == 0) return p.x + p.y;\n        else return p.x - p.y;\n    }\n}\n\nstatic inline bool in_bound(ll v) {\n    return (-LIM <= v && v <= LIM);\n}\n\nstatic ll pick_cut(ll prev, double target, const unordered_set<ll>& occupied, RNG &rng) {\n    // Try around target first.\n    ll base = (ll)floor(target);\n    for (ll delta = -30; delta <= 30; delta++) {\n        ll c = base + delta;\n        if (c <= prev) continue;\n        if (!in_bound(c)) continue;\n        if (occupied.find(c) != occupied.end()) continue;\n        return c;\n    }\n    // Fallback: walk upward until free (should be plenty).\n    // Also randomize step a bit to avoid pathological cases.\n    ll step = rng.nextLL(1, 5);\n    for (ll tries = 0; tries < 5000; tries++) {\n        ll c = prev + 1 + tries * step;\n        if (!in_bound(c)) break;\n        if (occupied.find(c) == occupied.end()) return c;\n    }\n    // Last resort (should never happen).\n    return prev + 1;\n}\n\nstatic vector<ll> make_cuts_by_quantiles(\n    const vector<ll>& sortedProj, // size N\n    const unordered_set<ll>& occupied,\n    int numCuts,\n    RNG &rng,\n    int maxShift // in indices\n) {\n    int N = (int)sortedProj.size();\n    vector<ll> cuts;\n    cuts.reserve(numCuts);\n    if (numCuts <= 0) return cuts;\n    int cols = numCuts + 1;\n    ll prev = (ll)-4e18;\n\n    for (int t = 1; t <= numCuts; t++) {\n        // boundary between column t-1 and t\n        ll desiredLeft = (ll)t * N / cols; // number of points intended on left\n        int idx = (int)desiredLeft; // split: left uses [0..idx-1], right starts at idx\n        if (idx < 1) idx = 1;\n        if (idx > N - 1) idx = N - 1;\n\n        int off = rng.nextInt(-maxShift, maxShift);\n        int idx2 = idx + off;\n        idx2 = max(1, min(N - 1, idx2));\n\n        ll a = sortedProj[idx2 - 1];\n        ll b = sortedProj[idx2];\n\n        double target = ( (double)a + (double)b ) * 0.5;\n\n        ll c = pick_cut(prev, target, occupied, rng);\n        // enforce strictly increasing\n        if (c <= prev) c = prev + 1;\n        // ensure not occupied\n        while (occupied.find(c) != occupied.end()) c++;\n        // still should be within bounds\n        if (!in_bound(c)) {\n            // shift downward if possible\n            while (c > -LIM && occupied.find(c) != occupied.end()) c--;\n            if (!in_bound(c)) c = (prev + 1 > LIM ? LIM : prev + 1);\n        }\n\n        cuts.push_back(c);\n        prev = c;\n    }\n\n    // Ensure strictly increasing (should already).\n    for (int i = 1; i < (int)cuts.size(); i++) {\n        if (cuts[i] <= cuts[i-1]) cuts[i] = cuts[i-1] + 1;\n    }\n    return cuts;\n}\n\nstatic int evaluate_candidate(\n    const vector<Point>& pts,\n    int orient,\n    const vector<ll>& cuts1,\n    const vector<ll>& cuts2,\n    const array<int,11>& a // 1..10\n) {\n    int V = (int)cuts1.size();\n    int H = (int)cuts2.size();\n    int cols = V + 1;\n    int rows = H + 1;\n\n    int cells = cols * rows;\n    vector<int> cnt(cells, 0);\n\n    for (auto &p : pts) {\n        ll p1 = proj_value(orient, p, 0);\n        ll p2 = proj_value(orient, p, 1);\n        // points should never lie on cut lines because we avoided occupied constants,\n        // but even if they do, upper_bound mapping still keeps validity.\n        int col = (int)(upper_bound(cuts1.begin(), cuts1.end(), p1) - cuts1.begin());\n        int row = (int)(upper_bound(cuts2.begin(), cuts2.end(), p2) - cuts2.begin());\n        if (0 <= col && col < cols && 0 <= row && row < rows) {\n            cnt[col * rows + row]++;\n        }\n    }\n\n    array<int,11> b{};\n    b.fill(0);\n    for (int x : cnt) {\n        if (1 <= x && x <= 10) b[x]++;\n    }\n\n    int matched = 0;\n    for (int d = 1; d <= 10; d++) {\n        matched += min(a[d], b[d]);\n    }\n    return matched;\n}\n\nstatic void output_line_vertical(ll x, ostream& out) {\n    // line x = const\n    out << x << \" \" << -LIM << \" \" << x << \" \" << LIM << \"\\n\";\n}\nstatic void output_line_horizontal(ll y, ostream& out) {\n    // line y = const\n    out << -LIM << \" \" << y << \" \" << LIM << \" \" << y << \"\\n\";\n}\nstatic void output_line_x_plus_y(ll c, ostream& out) {\n    // x + y = c, points (0,c) and (1,c-1)\n    out << 0 << \" \" << c << \" \" << 1 << \" \" << (c - 1) << \"\\n\";\n}\nstatic void output_line_x_minus_y(ll c, ostream& out) {\n    // x - y = c, points (c,0) and (c+1,1)\n    out << c << \" \" << 0 << \" \" << (c + 1) << \" \" << 1 << \"\\n\";\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    int totalA = 0;\n    for (int d = 1; d <= 10; d++) {\n        cin >> a[d];\n        totalA += a[d];\n    }\n\n    vector<Point> pts(N);\n    for (int i = 0; i < N; i++) {\n        ll x, y;\n        cin >> x >> y;\n        pts[i] = {x, y};\n    }\n\n    // Precompute sorted projections and occupied sets for orientations.\n    const int ORI = 4;\n    vector<vector<ll>> sortedP1(ORI), sortedP2(ORI);\n    vector<unordered_set<ll>> occ1(ORI), occ2(ORI);\n\n    for (int t = 0; t < ORI; t++) {\n        sortedP1[t].reserve(N);\n        sortedP2[t].reserve(N);\n        occ1[t].reserve(N * 2);\n        occ2[t].reserve(N * 2);\n        for (auto &p : pts) {\n            ll v1 = proj_value(t, p, 0);\n            ll v2 = proj_value(t, p, 1);\n            sortedP1[t].push_back(v1);\n            sortedP2[t].push_back(v2);\n            occ1[t].insert(v1);\n            occ2[t].insert(v2);\n        }\n        sort(sortedP1[t].begin(), sortedP1[t].end());\n        sort(sortedP2[t].begin(), sortedP2[t].end());\n    }\n\n    int M = totalA;\n\n    // Candidate (V,H) pairs: V cuts on proj1, H cuts on proj2.\n    // We'll try combinations where (V+1)*(H+1) is not too far from M.\n    vector<pair<int,int>> pairs;\n    for (int V = 0; V <= K; V++) {\n        int cols = V + 1;\n        // target cells ~ M\n        double approx = (double)M / (double)cols;\n        int H0 = (int)floor(approx) - 1; // so (V+1)*(H0+1) ~ M\n        for (int dh = -4; dh <= 4; dh++) {\n            int H = H0 + dh;\n            if (H < 0 || H > K - V) continue;\n            long long cells = 1LL * (V + 1) * (H + 1);\n            if (cells < max(1, M/4) || cells > 1LL*M*4 + 10) continue;\n            pairs.push_back({V,H});\n        }\n    }\n    // Deduplicate and sort by closeness.\n    sort(pairs.begin(), pairs.end());\n    pairs.erase(unique(pairs.begin(), pairs.end()), pairs.end());\n    sort(pairs.begin(), pairs.end(), [&](auto &p, auto &q){\n        ll c1 = 1LL*(p.first+1)*(p.second+1);\n        ll c2 = 1LL*(q.first+1)*(q.second+1);\n        ll d1 = llabs(c1 - M);\n        ll d2 = llabs(c2 - M);\n        if (d1 != d2) return d1 < d2;\n        return (p.first+p.second) < (q.first+q.second);\n    });\n\n    int maxPairsToTry = min<int>(30, pairs.size());\n    pairs.resize(maxPairsToTry);\n\n    uint64_t seed = chrono::high_resolution_clock::now().time_since_epoch().count();\n    RNG rng(seed);\n\n    Candidate best;\n    best.matched = -1;\n\n    int budgetPerPair = 4; // number of random variants per (orientation, V,H)\n\n    for (int orient = 0; orient < ORI; orient++) {\n        for (auto [V,H] : pairs) {\n            if (V + H > K) continue;\n\n            for (int it = 0; it < budgetPerPair; it++) {\n                // Randomness magnitude:\n                int maxShift = 2 + it; // small perturbations\n\n                auto cuts1 = make_cuts_by_quantiles(sortedP1[orient], occ1[orient], V, rng, maxShift);\n                auto cuts2 = make_cuts_by_quantiles(sortedP2[orient], occ2[orient], H, rng, maxShift);\n\n                // Evaluate\n                int matched = evaluate_candidate(pts, orient, cuts1, cuts2, a);\n                if (matched > best.matched) {\n                    best.matched = matched;\n                    best.orient = orient;\n                    best.V = V;\n                    best.H = H;\n                    best.cuts1 = std::move(cuts1);\n                    best.cuts2 = std::move(cuts2);\n                }\n            }\n        }\n    }\n\n    // Output best candidate.\n    int k = (int)best.cuts1.size() + (int)best.cuts2.size();\n    if (k > K) {\n        // Shouldn't happen, but just in case, truncate (keeping validity).\n        k = 0;\n        best.cuts1.clear();\n        best.cuts2.clear();\n        best.V = best.H = 0;\n    }\n\n    cout << k << \"\\n\";\n    // Which family corresponds to which projection depends on orient.\n    // Family 0: proj1, family 1: proj2.\n    // We output corresponding lines:\n    // orient 0: proj1=x, proj2=y\n    // orient 1: proj1=x, proj2=x+y\n    // orient 2: proj1=x, proj2=x-y\n    // orient 3: proj1=x+y, proj2=x-y\n    for (ll c : best.cuts1) {\n        if (best.orient == 0 || best.orient == 1 || best.orient == 2) {\n            // proj1 = x\n            output_line_vertical(c, cout);\n        } else {\n            // proj1 = x+y\n            output_line_x_plus_y(c, cout);\n        }\n    }\n    for (ll c : best.cuts2) {\n        if (best.orient == 0) {\n            // proj2 = y\n            output_line_horizontal(c, cout);\n        } else if (best.orient == 1) {\n            // proj2 = x+y\n            output_line_x_plus_y(c, cout);\n        } else if (best.orient == 2) {\n            // proj2 = x-y\n            output_line_x_minus_y(c, cout);\n        } else {\n            // orient 3: proj2 = x-y\n            output_line_x_minus_y(c, cout);\n        }\n    }\n\n    return 0;\n}","ahc014":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Edge {\n    // kind: 0=H,1=V,2=D1 (slope +1),3=DM (slope -1)\n    int kind;\n    int a, b; // encoded coordinates (see access functions)\n};\n\nstruct Rect {\n    // vertices in cyclic order around perimeter\n    array<int, 4> v;\n    array<Edge, 4> edges; // 4 unit segments on the perimeter\n};\n\nstruct Candidate {\n    long long key;\n    int rid;\n    bool operator<(Candidate const& other) const {\n        return key < other.key; // max-heap\n    }\n};\n\nstruct SimResult {\n    long long sumWeight = 0;\n    vector<array<int,4>> ops; // p1..p4 as vertex ids\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M;\n    cin >> N >> M;\n    vector<char> initDot(N * N, 0);\n    for (int i = 0; i < M; i++) {\n        int x, y;\n        cin >> x >> y;\n        initDot[x * N + y] = 1;\n    }\n\n    const int c = (N - 1) / 2;\n\n    // Precompute weights for each vertex\n    vector<long long> weight(N * N, 0);\n    for (int x = 0; x < N; x++) for (int y = 0; y < N; y++) {\n        long long dx = x - c;\n        long long dy = y - c;\n        weight[x * N + y] = dx * dx + dy * dy + 1;\n    }\n\n    // Precompute all unit rectangles (axis unit squares + rotated unit diamonds)\n    vector<Rect> rects;\n    rects.reserve((N-1)*(N-1) + (N-3)*(N-2));\n\n    // Helper lambda to add a rect\n    auto addRect = [&](const array<int,4>& v, const array<Edge,4>& edges) {\n        Rect r;\n        r.v = v;\n        r.edges = edges;\n        rects.push_back(r);\n    };\n\n    // Axis-aligned unit squares:\n    // BL(x,y)= (x,y), BR(x+1,y), TR(x+1,y+1), TL(x,y+1)\n    for (int x = 0; x <= N - 2; x++) {\n        for (int y = 0; y <= N - 2; y++) {\n            int bl = x * N + y;\n            int br = (x+1) * N + y;\n            int tr = (x+1) * N + (y+1);\n            int tl = x * N + (y+1);\n            array<int,4> v = {bl, br, tr, tl}; // cyclic clockwise\n            // Edges:\n            // bottom: (x,y)-(x+1,y) => H(a=x,b=y)\n            // right:  (x+1,y)-(x+1,y+1) => V(a=x+1,b=y)\n            // top:    (x,y+1)-(x+1,y+1) => H(a=x,b=y+1)\n            // left:   (x,y)-(x,y+1) => V(a=x,b=y)\n            array<Edge,4> edges = {\n                Edge{0, x, y},\n                Edge{1, x+1, y},\n                Edge{0, x, y+1},\n                Edge{1, x, y}\n            };\n            addRect(v, edges);\n        }\n    }\n\n    // Rotated-by-45 unit diamonds:\n    // A=(x,y), B=(x+1,y+1), C=(x+2,y), D=(x+1,y-1)\n    // cyclic order A->B->C->D\n    for (int x = 0; x <= N - 3; x++) {\n        for (int y = 1; y <= N - 2; y++) {\n            int A = x * N + y;\n            int B = (x+1) * N + (y+1);\n            int C = (x+2) * N + y;\n            int D = (x+1) * N + (y-1);\n            array<int,4> v = {A, B, C, D};\n\n            // Edge marking:\n            // AB: (x,y)-(x+1,y+1) => D1(a=x,b=y) (slope +1)\n            // BC: (x+1,y+1)-(x+2,y) => DM(a=x+1,b=y)   (slope -1, store y_low=y)\n            // CD: (x+2,y)-(x+1,y-1) => D1(a=x+1,b=y-1)\n            // DA: (x+1,y-1)-(x,y) => DM(a=x,b=y-1)\n            array<Edge,4> edges = {\n                Edge{2, x, y},\n                Edge{3, x+1, y},\n                Edge{2, x+1, y-1},\n                Edge{3, x, y-1}\n            };\n            addRect(v, edges);\n        }\n    }\n\n    // Build vertex -> list of rectangles containing it\n    vector<vector<int>> adj(N*N);\n    for (int rid = 0; rid < (int)rects.size(); rid++) {\n        for (int k = 0; k < 4; k++) {\n            adj[rects[rid].v[k]].push_back(rid);\n        }\n    }\n\n    auto run = [&](long long lambdaPotential) -> SimResult {\n        SimResult res;\n        vector<char> dot = initDot;\n\n        int R = (int)rects.size();\n        vector<int> cnt(R, 0);\n        vector<char> usedRect(R, 0);\n\n        // Used edges for condition3\n        // H: (N-1)*N ; index a*N + b, a in [0..N-2], b in [0..N-1]\n        // V: N*(N-1) ; index a*(N-1) + b, a in [0..N-1], b in [0..N-2]\n        // D1: (N-1)*(N-1) ; index a*(N-1) + b, a in [0..N-2], b in [0..N-2]\n        // DM: (N-1)*(N-1) ; same indexing\n        vector<uint8_t> usedH((N-1)*N, 0);\n        vector<uint8_t> usedV(N*(N-1), 0);\n        vector<uint8_t> usedD1((N-1)*(N-1), 0);\n        vector<uint8_t> usedDM((N-1)*(N-1), 0);\n\n        auto edgeUsed = [&](const Edge& e) -> bool {\n            if (e.kind == 0) { // H\n                return usedH[e.a * N + e.b];\n            } else if (e.kind == 1) { // V\n                return usedV[e.a * (N-1) + e.b];\n            } else if (e.kind == 2) { // D1\n                return usedD1[e.a * (N-1) + e.b];\n            } else { // 3 DM\n                return usedDM[e.a * (N-1) + e.b];\n            }\n        };\n        auto setEdgeUsed = [&](const Edge& e) {\n            if (e.kind == 0) {\n                usedH[e.a * N + e.b] = 1;\n            } else if (e.kind == 1) {\n                usedV[e.a * (N-1) + e.b] = 1;\n            } else if (e.kind == 2) {\n                usedD1[e.a * (N-1) + e.b] = 1;\n            } else {\n                usedDM[e.a * (N-1) + e.b] = 1;\n            }\n        };\n\n        auto edgesAvailable = [&](int rid) -> bool {\n            for (auto &e : rects[rid].edges) {\n                if (edgeUsed(e)) return false;\n            }\n            return true;\n        };\n\n        // initial cnt and sumWeight\n        long long sumW = 0;\n        for (int id = 0; id < N*N; id++) if (dot[id]) sumW += weight[id];\n        res.sumWeight = sumW;\n\n        for (int rid = 0; rid < R; rid++) {\n            int ctmp = 0;\n            for (int k = 0; k < 4; k++) ctmp += (dot[rects[rid].v[k]] ? 1 : 0);\n            cnt[rid] = ctmp;\n        }\n\n        priority_queue<Candidate> pq;\n\n        auto pushIfCnt3 = [&](int rid) {\n            if (usedRect[rid]) return;\n            if (cnt[rid] != 3) return;\n\n            // find missing vertex u\n            int missIdx = -1;\n            int u = -1;\n            for (int i = 0; i < 4; i++) {\n                int vid = rects[rid].v[i];\n                if (!dot[vid]) { missIdx = i; u = vid; break; }\n            }\n            if (missIdx == -1) return;\n\n            // potentialCount: rectangles that would become cnt==3 if we add dot at u\n            long long potential = 0;\n            for (int rr : adj[u]) {\n                if (usedRect[rr]) continue;\n                if (cnt[rr] == 2) potential++;\n            }\n            long long key = weight[u] + lambdaPotential * potential;\n            pq.push(Candidate{key, rid});\n        };\n\n        for (int rid = 0; rid < R; rid++) {\n            if (cnt[rid] == 3) pushIfCnt3(rid);\n        }\n\n        while (!pq.empty()) {\n            auto cand = pq.top(); pq.pop();\n            int rid = cand.rid;\n            if (usedRect[rid]) continue;\n            if (cnt[rid] != 3) continue;\n\n            if (!edgesAvailable(rid)) continue;\n\n            int missIdx = -1;\n            int u = -1;\n            for (int i = 0; i < 4; i++) {\n                int vid = rects[rid].v[i];\n                if (!dot[vid]) { missIdx = i; u = vid; break; }\n            }\n            if (missIdx == -1) continue;\n            if (dot[u]) continue; // should not happen\n\n            // Execute the move\n            usedRect[rid] = 1;\n            for (auto &e : rects[rid].edges) setEdgeUsed(e);\n\n            dot[u] = 1;\n            res.sumWeight += weight[u];\n            // record p1..p4 in cyclic order starting from missIdx\n            array<int,4> op;\n            for (int t = 0; t < 4; t++) {\n                op[t] = rects[rid].v[(missIdx + t) % 4];\n            }\n            res.ops.push_back(op);\n\n            // update cnt for adjacent rectangles\n            for (int rr : adj[u]) {\n                if (usedRect[rr]) continue;\n                // u was empty before, now becomes dot -> cnt increases by 1\n                cnt[rr]++;\n                if (cnt[rr] == 3) pushIfCnt3(rr);\n            }\n        }\n\n        return res;\n    };\n\n    // Try two greedy variants\n    SimResult best = run(0);\n    SimResult alt = run(5);\n    if (alt.sumWeight > best.sumWeight) best = std::move(alt);\n\n    // Output\n    cout << best.ops.size() << \"\\n\";\n    for (auto &op : best.ops) {\n        for (int t = 0; t < 4; t++) {\n            int id = op[t];\n            int x = id / N;\n            int y = id % N;\n            cout << x << \" \" << y << (t == 3 ? '\\n' : ' ');\n        }\n    }\n    return 0;\n}","ahc015":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct State {\n    // index = r*10 + c, value 0..3\n    array<uint8_t, 100> a{};\n};\n\nstatic inline int idx(int r, int c) { return r * 10 + c; }\n\nstatic State tilt(const State& s, int dir) {\n    // dir: 0=F (up), 1=B (down), 2=L (left), 3=R (right)\n    State t;\n    t.a.fill(0);\n\n    if (dir == 0) { // F: compress each column towards r=0\n        for (int c = 0; c < 10; c++) {\n            int k = 0;\n            for (int r = 0; r < 10; r++) {\n                uint8_t v = s.a[idx(r,c)];\n                if (v) t.a[idx(k++,c)] = v;\n            }\n        }\n    } else if (dir == 1) { // B: compress each column towards r=9\n        for (int c = 0; c < 10; c++) {\n            int k = 9;\n            for (int r = 9; r >= 0; r--) {\n                uint8_t v = s.a[idx(r,c)];\n                if (v) t.a[idx(k--,c)] = v;\n            }\n        }\n    } else if (dir == 2) { // L: compress each row towards c=0\n        for (int r = 0; r < 10; r++) {\n            int k = 0;\n            for (int c = 0; c < 10; c++) {\n                uint8_t v = s.a[idx(r,c)];\n                if (v) t.a[idx(r,k++)] = v;\n            }\n        }\n    } else { // dir==3, R: compress each row towards c=9\n        for (int r = 0; r < 10; r++) {\n            int k = 9;\n            for (int c = 9; c >= 0; c--) {\n                uint8_t v = s.a[idx(r,c)];\n                if (v) t.a[idx(r,k--)] = v;\n            }\n        }\n    }\n    return t;\n}\n\nstatic long long calcNumerator(const State& s) {\n    static int q[100];\n    bool vis[100];\n    memset(vis, 0, sizeof(vis));\n\n    const int dr[4] = {1,-1,0,0};\n    const int dc[4] = {0,0,1,-1};\n\n    long long sum = 0;\n    for (int start = 0; start < 100; start++) {\n        if (s.a[start] == 0 || vis[start]) continue;\n        uint8_t flavor = s.a[start];\n\n        int head = 0, tail = 0;\n        q[tail++] = start;\n        vis[start] = true;\n\n        long long cnt = 0;\n        while (head < tail) {\n            int v = q[head++];\n            cnt++;\n\n            int r = v / 10, c = v % 10;\n            for (int k = 0; k < 4; k++) {\n                int nr = r + dr[k], nc = c + dc[k];\n                if (nr < 0 || nr >= 10 || nc < 0 || nc >= 10) continue;\n                int u = idx(nr, nc);\n                if (vis[u]) continue;\n                if (s.a[u] != flavor) continue;\n                vis[u] = true;\n                q[tail++] = u;\n            }\n        }\n        sum += cnt * cnt;\n    }\n    return sum;\n}\n\nstatic int bestDirGreedyAfterPlacement(const State& s, uint8_t flavor) {\n    // not used for decision directly; kept for potential extension\n    // We return best direction by numerator\n    long long best = -1;\n    int bestDir = 0;\n    for (int dir = 0; dir < 4; dir++) {\n        State t = tilt(s, dir);\n        t.a.fill(t.a[0]); // dummy to avoid warnings\n    }\n    // Actually not used in this function in our final code.\n    (void)flavor;\n    return bestDir;\n}\n\nstatic long long bestNumeratorAfterNextTilt(const State& sWithNext, int dummyFlavor) {\n    // returns max over dir of calcNumerator(tilt(sWithNext, dir))\n    (void)dummyFlavor;\n    long long best = -1;\n    for (int dir = 0; dir < 4; dir++) {\n        State t = tilt(sWithNext, dir);\n        long long num = calcNumerator(t);\n        if (num > best) best = num;\n    }\n    return best;\n}\n\nstatic long long expectedBestNumeratorAfterNext(const State& sAfterD1, uint8_t nextFlavor,\n                                                       std::mt19937_64 &rng) {\n    vector<int> empties;\n    empties.reserve(100);\n    for (int i = 0; i < 100; i++) if (sAfterD1.a[i] == 0) empties.push_back(i);\n\n    int E = (int)empties.size();\n    if (E == 0) return 0;\n\n    // Exact if small empties remain\n    if (E <= 25) {\n        long long total = 0;\n        for (int cell : empties) {\n            State s2 = sAfterD1;\n            s2.a[cell] = nextFlavor;\n            long long bestNext = bestNumeratorAfterNextTilt(s2, nextFlavor);\n            total += bestNext;\n        }\n        return total / E;\n    }\n\n    // Monte Carlo otherwise\n    int K = 10;\n    if (E > 60) K = 12;\n    else if (E > 40) K = 10;\n    else K = 8;\n\n    shuffle(empties.begin(), empties.end(), rng);\n    K = min(K, E);\n\n    long long total = 0;\n    for (int i = 0; i < K; i++) {\n        int cell = empties[i];\n        State s2 = sAfterD1;\n        s2.a[cell] = nextFlavor;\n        long long bestNext = bestNumeratorAfterNextTilt(s2, nextFlavor);\n        total += bestNext;\n    }\n    return total / K;\n}\n\nstatic int findCellByPT(const State& g, int p) {\n    int cnt = 0;\n    for (int r = 0; r < 10; r++) for (int c = 0; c < 10; c++) {\n        if (g.a[idx(r,c)] == 0) {\n            cnt++;\n            if (cnt == p) return idx(r,c);\n        }\n    }\n    return -1; // should not happen\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    vector<int> f(101);\n    for (int i = 1; i <= 100; i++) cin >> f[i];\n\n    State g;\n    g.a.fill(0);\n\n    const char dirChar[4] = {'F','B','L','R'};\n\n    // RNG seed\n    uint64_t seed = chrono::steady_clock::now().time_since_epoch().count();\n    seed ^= (uint64_t)(uintptr_t)&g;\n    std::mt19937_64 rng(seed);\n\n    for (int t = 1; t <= 100; t++) {\n        int p;\n        cin >> p;\n\n        // Place t-th candy into p-th empty cell in front-to-back, left-to-right.\n        int cell = findCellByPT(g, p);\n        g.a[cell] = (uint8_t)f[t];\n\n        if (t == 100) break; // no need to output\n\n        uint8_t nextFlavor = (uint8_t)f[t+1];\n\n        long long bestVal = LLONG_MIN;\n        int bestDir = 0;\n\n        // Weight for immediate numerator term.\n        // If remaining time small, we rely more on immediate greedy.\n        int remaining = 100 - t;\n        double wImm = (remaining >= 5 ? 0.02 : 0.05);\n\n        for (int dir = 0; dir < 4; dir++) {\n            State sAfterD1 = tilt(g, dir);\n\n            long long imm = calcNumerator(sAfterD1);\n            long long expBestNext = expectedBestNumeratorAfterNext(sAfterD1, nextFlavor, rng);\n\n            // Choose direction maximizing estimated objective for near future.\n            long long val = (long long)llround((double)expBestNext + wImm * (double)imm);\n\n            if (val > bestVal) {\n                bestVal = val;\n                bestDir = dir;\n            }\n        }\n\n        g = tilt(g, bestDir);\n        cout << dirChar[bestDir] << \"\\n\" << flush;\n    }\n    return 0;\n}","ahc016":"#include <bits/stdc++.h>\nusing namespace std;\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 Analyzer {\n    int N;\n    int L;\n    int T; // N*(N-1)/2\n    vector<long long> offset; // for canonical upper-tri flatten\n    vector<uint64_t> maskGT; // maskGT[j] = {k | k>j}\n\n    Analyzer(int N_, int L_) : N(N_), L(L_) {\n        offset.assign(N, 0);\n        for (int i = 0; i < N; i++) {\n            offset[i] = 1LL * i * (2LL * N - i - 1) / 2;\n        }\n        T = N * (N - 1) / 2;\n\n        uint64_t fullMask = (N == 64 ? ~0ULL : ((1ULL << N) - 1ULL));\n        maskGT.assign(N, 0);\n        for (int j = 0; j < N; j++) {\n            uint64_t le = (j + 1 == 64 ? ~0ULL : ((1ULL << (j + 1)) - 1ULL));\n            maskGT[j] = fullMask & ~le; // bits > j\n        }\n    }\n\n    static inline int popcnt_u64(uint64_t x) { return (int)__builtin_popcountll(x); }\n\n    struct Result {\n        vector<uint64_t> canonBits;       // upper triangle in canonical order\n        vector<uint64_t> finalColorSorted; // multiset of col[L] values\n        int edges = 0;\n        long long twoStars = 0;\n        long long triangles = 0;\n        vector<int> degSorted;\n    };\n\n    Result analyze(const vector<uint64_t>& adj) const {\n        // degrees and scalar features\n        vector<int> deg(N);\n        int edges = 0;\n        long long twoStars = 0;\n        for (int v = 0; v < N; v++) {\n            deg[v] = popcnt_u64(adj[v]);\n            edges += deg[v];\n            twoStars += 1LL * deg[v] * (deg[v] - 1) / 2;\n        }\n        edges /= 2;\n\n        // triangles: count (i<j<k)\n        long long triangles = 0;\n        for (int i = 0; i < N; i++) {\n            for (int j = i + 1; j < N; j++) {\n                if ((adj[i] >> j) & 1ULL) {\n                    uint64_t common = adj[i] & adj[j] & maskGT[j];\n                    triangles += popcnt_u64(common);\n                }\n            }\n        }\n\n        // WL refinement\n        vector<vector<uint64_t>> col(L + 1, vector<uint64_t>(N, 0));\n        for (int v = 0; v < N; v++) {\n            col[0][v] = splitmix64((uint64_t)deg[v] + 0x9e3779b97f4a7c15ULL);\n        }\n\n        const uint64_t A1 = 0x1234567890abcdefULL;\n        const uint64_t A2 = 0xfedcba0987654321ULL;\n        const uint64_t A3 = 0x0f0f0f0f0f0f0f0fULL;\n\n        for (int r = 0; r < L; r++) {\n            for (int v = 0; v < N; v++) {\n                uint64_t sum1 = 0, sum2 = 0;\n                uint64_t xr = 0;\n                int cnt = 0;\n                uint64_t row = adj[v];\n                while (row) {\n                    int u = __builtin_ctzll(row);\n                    row &= row - 1;\n                    uint64_t cu = col[r][u];\n                    sum1 += splitmix64(cu + A1);\n                    sum2 += splitmix64(cu + A2);\n                    xr ^= splitmix64(cu + A3);\n                    cnt++;\n                }\n                uint64_t oldc = col[r][v];\n                uint64_t nc = splitmix64(oldc ^ (sum1 + 0x9e3779b97f4a7c15ULL)) ^\n                              splitmix64(sum2 ^ 0xbf58476d1ce4e5b9ULL) ^\n                              (xr + splitmix64((uint64_t)cnt + 0x94d049bb133111ebULL));\n                col[r + 1][v] = nc;\n            }\n        }\n\n        // final color multiset (permutation-invariant)\n        vector<uint64_t> finalSorted(N);\n        for (int v = 0; v < N; v++) finalSorted[v] = col[L][v];\n        sort(finalSorted.begin(), finalSorted.end());\n\n        // Invariant neighbor-signature for tie-breaking:\n        // depends only on final colors of neighbors (permutation-invariant).\n        vector<uint64_t> neighSig(N, 0);\n        for (int v = 0; v < N; v++) {\n            uint64_t h = 1469598103934665603ULL;\n            uint64_t row = adj[v];\n            while (row) {\n                int u = __builtin_ctzll(row);\n                row &= row - 1;\n                uint64_t cu = col[L][u];\n                h ^= splitmix64(cu + 0x9ddfea08eb382d69ULL);\n                h *= 1099511628211ULL;\n            }\n            // incorporate degree too (still invariant)\n            h ^= splitmix64((uint64_t)deg[v] + 0x632be59bd9b4e019ULL);\n            neighSig[v] = h;\n        }\n\n        // canonical order (now permutation-invariant in tie cases)\n        vector<int> ord(N);\n        iota(ord.begin(), ord.end(), 0);\n\n        auto cmp = [&](int a, int b) {\n            for (int r = 0; r <= L; r++) {\n                uint64_t ca = col[r][a], cb = col[r][b];\n                if (ca != cb) return ca < cb;\n            }\n            if (neighSig[a] != neighSig[b]) return neighSig[a] < neighSig[b];\n            if (deg[a] != deg[b]) return deg[a] < deg[b];\n            return a < b; // last resort; should be extremely rare now\n        };\n        sort(ord.begin(), ord.end(), cmp);\n\n        // canonical bits in that order\n        int W = (T + 63) / 64;\n        vector<uint64_t> canonBits(W, 0);\n\n        for (int a = 0; a < N; a++) {\n            int oa = ord[a];\n            uint64_t row = adj[oa];\n            for (int b = a + 1; b < N; b++) {\n                int ob = ord[b];\n                if ((row >> ob) & 1ULL) {\n                    int pos = (int)offset[a] + (b - a - 1);\n                    canonBits[pos >> 6] |= (1ULL << (pos & 63));\n                }\n            }\n        }\n\n        vector<int> degSorted = deg;\n        sort(degSorted.begin(), degSorted.end());\n\n        Result res;\n        res.canonBits = std::move(canonBits);\n        res.finalColorSorted = std::move(finalSorted);\n        res.edges = edges;\n        res.twoStars = twoStars;\n        res.triangles = triangles;\n        res.degSorted = std::move(degSorted);\n        return res;\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int M;\n    double epsInput;\n    cin >> M >> epsInput;\n    double eps = epsInput;\n\n    // Choose N with stronger bias towards stability, still moderate to keep 1/N.\n    int N;\n    if (eps <= 0.15) N = 25;\n    else if (eps <= 0.25) N = 30;\n    else if (eps <= 0.30) N = 35;\n    else N = 40; // eps up to 0.4\n\n    // WL rounds: higher reduces ambiguous tie classes.\n    int L = 4;\n    if (N >= 40) L = 3; // slight speed guard\n\n    Analyzer analyzer(N, L);\n\n    // Deterministic RNG for candidate graphs\n    uint64_t seedBase = 0x6a09e667f3bcc909ULL ^ splitmix64((uint64_t)M * 1000ULL) ^ splitmix64((uint64_t)llround(eps * 1000.0));\n\n    auto nextRand = [&](uint64_t &st) -> uint64_t {\n        st = splitmix64(st);\n        return st;\n    };\n\n    // Generate and store all candidate adjacency matrices\n    vector<vector<uint64_t>> allAdj(M, vector<uint64_t>(N, 0ULL));\n    for (int k = 0; k < M; k++) {\n        uint64_t st = seedBase ^ splitmix64((uint64_t)k * 0x9e3779b97f4a7c15ULL);\n        for (int i = 0; i < N; i++) {\n            for (int j = i + 1; j < N; j++) {\n                uint64_t r = nextRand(st);\n                if (r & 1ULL) {\n                    allAdj[k][i] |= (1ULL << j);\n                    allAdj[k][j] |= (1ULL << i);\n                }\n            }\n        }\n    }\n\n    // Analyze candidates once\n    vector<Analyzer::Result> candRes(M);\n    for (int k = 0; k < M; k++) {\n        candRes[k] = analyzer.analyze(allAdj[k]);\n    }\n\n    // Output graphs\n    cout << N << \"\\n\";\n    int T = N * (N - 1) / 2;\n    for (int k = 0; k < M; k++) {\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                s.push_back(((allAdj[k][i] >> j) & 1ULL) ? '1' : '0');\n            }\n        }\n        cout << s << \"\\n\";\n    }\n    cout.flush();\n\n    // Weights for scoring\n    double f = min(1.0, eps / 0.4);\n    double wColor = 0.03 * (1.0 + f);\n    double wDeg = 0.02 * (1.0 + f);\n    double wE = 0.01 * (1.0 + f);\n    double w2 = 5e-4 * (1.0 + f);\n    double wTri = 2e-4 * (1.0 + f);\n\n    int W = (T + 63) / 64;\n\n    for (int q = 0; q < 100; q++) {\n        string H;\n        cin >> H;\n\n        // Parse H into adjacency bitsets\n        vector<uint64_t> adj(N, 0ULL);\n        int idx = 0;\n        for (int i = 0; i < N; i++) {\n            for (int j = i + 1; j < N; j++) {\n                if (H[idx++] == '1') {\n                    adj[i] |= (1ULL << j);\n                    adj[j] |= (1ULL << i);\n                }\n            }\n        }\n\n        auto hRes = analyzer.analyze(adj);\n        const auto &canonH = hRes.canonBits;\n\n        int best = 0;\n        long long bestScore = (1LL << 62);\n\n        for (int k = 0; k < M; k++) {\n            // Hamming distance on canonical adjacency bits\n            long long dHam = 0;\n            const auto &cb = candRes[k].canonBits;\n            for (int w = 0; w < W; w++) {\n                dHam += __builtin_popcountll(cb[w] ^ canonH[w]);\n            }\n\n            // WL final color multiset distance (permutation-invariant)\n            long long dColor = 0;\n            for (int i = 0; i < N; i++) {\n                dColor += __builtin_popcountll(candRes[k].finalColorSorted[i] ^ hRes.finalColorSorted[i]);\n            }\n\n            // scalar tie-breakers\n            long long ediff = llabs((long long)hRes.edges - candRes[k].edges);\n            long long d2 = llabs(hRes.twoStars - candRes[k].twoStars);\n            long long dt = llabs(hRes.triangles - candRes[k].triangles);\n\n            long long dDeg = 0;\n            for (int i = 0; i < N; i++) dDeg += llabs((long long)hRes.degSorted[i] - candRes[k].degSorted[i]);\n\n            long long score = dHam;\n            score += (long long)llround(wColor * (double)dColor);\n            score += (long long)llround(wDeg * (double)dDeg);\n            score += (long long)llround(wE * (double)ediff);\n            score += (long long)llround(w2 * (double)d2);\n            score += (long long)llround(wTri * (double)dt);\n\n            if (score < bestScore) {\n                bestScore = score;\n                best = k;\n            }\n        }\n\n        cout << best << \"\\n\";\n        cout.flush();\n    }\n\n    return 0;\n}","ahc017":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct AdjItem {\n    int to;\n    int eid;\n};\n\nstruct PQNode {\n    double impSum;\n    int cnt;\n    int id;\n    int ver;\n};\n\nstruct PQCmp {\n    bool operator()(const PQNode& a, const PQNode& b) const {\n        if (a.impSum != b.impSum) return a.impSum > b.impSum; // min-heap by impSum\n        if (a.cnt != b.cnt) return a.cnt > b.cnt;             // then min-heap by cnt\n        return a.id > b.id;\n    }\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<int> U(M), V(M);\n    vector<long long> W(M);\n    vector<vector<AdjItem>> g(N);\n\n    for (int i = 0; i < M; i++) {\n        int u, v;\n        long long w;\n        cin >> u >> v >> w;\n        --u; --v;\n        U[i] = u; V[i] = v; W[i] = w;\n        g[u].push_back({v, i});\n        g[v].push_back({u, i});\n    }\n\n    // coordinates are not needed for this heuristic\n    for (int i = 0; i < N; i++) {\n        int x, y;\n        cin >> x >> y;\n    }\n\n    // --- Compute edge importance via (weighted) Brandes-like shortest-path dependency ---\n    // importance[e] ~ edgeBetw[e] * W[e]\n    vector<double> edgeBetw(M, 0.0);\n\n    const long long INF = (1LL<<62);\n    const double SIGMA_LIM = 1e300;\n    const double DELTA_LIM = 1e300;\n\n    vector<long long> dist(N);\n    vector<double> sigma(N), delta(N);\n    vector<vector<pair<int,int>>> pred; // pred[v] = list of (u, eid) where u->v is on a shortest path from source\n    pred.assign(N, {});\n\n    vector<int> order;\n    order.reserve(N);\n\n    auto t_start = chrono::steady_clock::now();\n    const double TIME_LIMIT_SEC = 5.7; // leave margin under 6.0s\n\n    int S = N;\n    // Time safety: if too slow, we stop early.\n    for (int s = 0; s < S; s++) {\n        if (s % 20 == 0) {\n            double elapsed = chrono::duration<double>(chrono::steady_clock::now() - t_start).count();\n            if (elapsed > TIME_LIMIT_SEC) break;\n        }\n\n        // init\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 i = 0; i < N; i++) pred[i].clear();\n        order.clear();\n\n        dist[s] = 0;\n        sigma[s] = 1.0;\n\n        priority_queue<pair<long long,int>, vector<pair<long long,int>>, greater<pair<long long,int>>> pq;\n        pq.push({0, s});\n\n        while (!pq.empty()) {\n            auto [d, v] = pq.top(); pq.pop();\n            if (d != dist[v]) continue;\n            order.push_back(v);\n\n            for (auto [to, eid] : g[v]) {\n                long long nd = d + W[eid];\n                if (nd < dist[to]) {\n                    dist[to] = nd;\n                    pq.push({nd, to});\n\n                    sigma[to] = sigma[v];\n                    pred[to].clear();\n                    pred[to].push_back({v, eid});\n                } else if (nd == dist[to]) {\n                    sigma[to] += sigma[v];\n                    if (sigma[to] > SIGMA_LIM) sigma[to] = SIGMA_LIM;\n                    pred[to].push_back({v, eid});\n                }\n            }\n        }\n\n        // accumulation\n        for (int i = (int)order.size() - 1; i >= 0; i--) {\n            int v = order[i];\n            if (sigma[v] == 0.0) continue;\n            double dv = delta[v];\n\n            for (auto [u, eid] : pred[v]) {\n                // u is predecessor on shortest-path DAG: u -> v\n                if (sigma[u] == 0.0) continue;\n                double c = (sigma[u] / sigma[v]) * (1.0 + dv);\n                if (c > DELTA_LIM) c = DELTA_LIM;\n\n                delta[u] += c;\n                if (delta[u] > DELTA_LIM) delta[u] = DELTA_LIM;\n\n                edgeBetw[eid] += c;\n            }\n        }\n    }\n\n    // undirected correction (each pair counted twice in undirected Brandes)\n    for (int e = 0; e < M; e++) edgeBetw[e] *= 0.5;\n\n    // convert to importance with edge weight factor\n    vector<double> imp(M);\n    double mx = 0.0;\n    for (int e = 0; e < M; e++) {\n        long double val = (long double)edgeBetw[e] * (long double)W[e];\n        double x = (val > 1e300L ? 1e300 : (double)val);\n        imp[e] = x;\n        mx = max(mx, x);\n    }\n    if (mx == 0.0) mx = 1.0;\n    for (int e = 0; e < M; e++) imp[e] /= mx; // normalize to [0..1] roughly\n\n    // --- Greedy scheduling: spread important edges across days with capacity K ---\n    vector<int> idx(M);\n    iota(idx.begin(), idx.end(), 0);\n    sort(idx.begin(), idx.end(), [&](int a, int b) {\n        if (imp[a] != imp[b]) return imp[a] > imp[b];\n        return W[a] > W[b];\n    });\n\n    vector<int> dayOfEdge(M, 0);\n    vector<vector<int>> edgesByDay(D);\n    vector<double> sumImpDay(D, 0.0);\n    vector<int> cntDay(D, 0);\n    vector<int> ver(D, 0);\n\n    priority_queue<PQNode, vector<PQNode>, PQCmp> pq;\n    for (int d = 0; d < D; d++) {\n        pq.push({0.0, 0, d, ver[d]});\n    }\n\n    for (int e : idx) {\n        while (true) {\n            auto cur = pq.top(); pq.pop();\n            int d = cur.id;\n            if (cur.ver != ver[d]) continue;\n            if (cntDay[d] >= K) continue;\n\n            dayOfEdge[e] = d;\n            edgesByDay[d].push_back(e);\n            cntDay[d]++;\n            sumImpDay[d] += imp[e];\n            ver[d]++;\n            pq.push({sumImpDay[d], cntDay[d], d, ver[d]});\n            break;\n        }\n    }\n\n    // --- Local improvement (proxy objective): minimize sum of squares of daily importance ---\n    auto computeP = [&]() -> long double {\n        long double P = 0;\n        for (int d = 0; d < D; d++) P += (long double)sumImpDay[d] * (long double)sumImpDay[d];\n        return P;\n    };\n\n    long double P = computeP();\n\n    for (int it = 0; it < 250; it++) {\n        int A = -1, B = -1;\n        for (int d = 0; d < D; d++) {\n            if (A == -1 || sumImpDay[d] > sumImpDay[A]) A = d;\n            if (B == -1 || sumImpDay[d] < sumImpDay[B]) B = d;\n        }\n        if (A == B) break;\n\n        // Find min/max edges in A and B\n        auto &LA = edgesByDay[A];\n        auto &LB = edgesByDay[B];\n\n        int posMinA = -1, posMaxA = -1, posMinB = -1, posMaxB = -1;\n        double minA = 1e300, maxA = -1e300;\n        double minB = 1e300, maxB = -1e300;\n\n        for (int i = 0; i < (int)LA.size(); i++) {\n            int e = LA[i];\n            if (imp[e] < minA) { minA = imp[e]; posMinA = i; }\n            if (imp[e] > maxA) { maxA = imp[e]; posMaxA = i; }\n        }\n        for (int i = 0; i < (int)LB.size(); i++) {\n            int e = LB[i];\n            if (imp[e] < minB) { minB = imp[e]; posMinB = i; }\n            if (imp[e] > maxB) { maxB = imp[e]; posMaxB = i; }\n        }\n\n        // Candidate 1: swap (minA) <-> (maxB)\n        int eA1 = LA[posMinA], eB1 = LB[posMaxB];\n        double newA1 = sumImpDay[A] - imp[eA1] + imp[eB1];\n        double newB1 = sumImpDay[B] - imp[eB1] + imp[eA1];\n        long double deltaP1 = (long double)newA1 * newA1 + (long double)newB1 * newB1\n                              - ((long double)sumImpDay[A] * sumImpDay[A] + (long double)sumImpDay[B] * sumImpDay[B]);\n\n        // Candidate 2: swap (maxA) <-> (minB)\n        int eA2 = LA[posMaxA], eB2 = LB[posMinB];\n        double newA2 = sumImpDay[A] - imp[eA2] + imp[eB2];\n        double newB2 = sumImpDay[B] - imp[eB2] + imp[eA2];\n        long double deltaP2 = (long double)newA2 * newA2 + (long double)newB2 * newB2\n                              - ((long double)sumImpDay[A] * sumImpDay[A] + (long double)sumImpDay[B] * sumImpDay[B]);\n\n        long double bestDelta = 0;\n        int mode = -1;\n        if (deltaP1 < bestDelta) { bestDelta = deltaP1; mode = 1; }\n        if (deltaP2 < bestDelta) { bestDelta = deltaP2; mode = 2; }\n\n        if (mode == -1) break; // no improvement\n\n        if (mode == 1) {\n            // swap LA[posMinA] and LB[posMaxB]\n            swap(edgesByDay[A][posMinA], edgesByDay[B][posMaxB]);\n            sumImpDay[A] = newA1;\n            sumImpDay[B] = newB1;\n            P += bestDelta;\n        } else {\n            // swap LA[posMaxA] and LB[posMinB]\n            swap(edgesByDay[A][posMaxA], edgesByDay[B][posMinB]);\n            sumImpDay[A] = newA2;\n            sumImpDay[B] = newB2;\n            P += bestDelta;\n        }\n    }\n\n    // --- Output ---\n    for (int e = 0; e < M; e++) {\n        cout << dayOfEdge[e] + 1 << (e + 1 == M ? '\\n' : ' ');\n    }\n    return 0;\n}","ahc019":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic inline int idx3(int D, int x, int y, int z){\n    return x*D*D + y*D + z;\n}\n\nstruct Coord { int x,y,z; };\n\nstruct HopcroftKarp {\n    int nL, nR;\n    vector<vector<int>> adj;\n    vector<int> dist;\n    vector<int> matchL, matchR;\n\n    HopcroftKarp(int nL_, int nR_) : nL(nL_), nR(nR_) {\n        adj.assign(nL, {});\n        dist.assign(nL, 0);\n        matchL.assign(nL, -1);\n        matchR.assign(nR, -1);\n    }\n\n    void add_edge(int a, int b){\n        adj[a].push_back(b);\n    }\n\n    bool bfs(int s=-1){\n        queue<int> q;\n        for(int i=0;i<nL;i++){\n            if(matchL[i] == -1){\n                dist[i] = 0;\n                q.push(i);\n            }else{\n                dist[i] = -1;\n            }\n        }\n        bool reachableFreeR = false;\n        while(!q.empty()){\n            int v = q.front(); q.pop();\n            for(int to : adj[v]){\n                int u = matchR[to];\n                if(u == -1){\n                    reachableFreeR = true;\n                }else if(dist[u] == -1){\n                    dist[u] = dist[v] + 1;\n                    q.push(u);\n                }\n            }\n        }\n        return reachableFreeR;\n    }\n\n    bool dfs(int v){\n        for(int to : adj[v]){\n            int u = matchR[to];\n            if(u == -1 || (dist[u] == dist[v] + 1 && dfs(u))){\n                matchL[v] = to;\n                matchR[to] = v;\n                return true;\n            }\n        }\n        dist[v] = -1;\n        return false;\n    }\n\n    int max_matching(){\n        int flow = 0;\n        while(bfs()){\n            for(int i=0;i<nL;i++){\n                if(matchL[i] == -1){\n                    if(dfs(i)) flow++;\n                }\n            }\n        }\n        return flow;\n    }\n};\n\nstatic vector<pair<int,int>> maxDominoMatchingGlobal(\n    const vector<int>& remGlobalIdx,\n    const vector<Coord>& remCoords,\n    int D\n){\n    int n = (int)remGlobalIdx.size();\n    vector<int> posToLocal(D*D*D, -1);\n    for(int i=0;i<n;i++){\n        posToLocal[remGlobalIdx[i]] = i;\n    }\n\n    vector<int> leftNodes, rightNodes;\n    leftNodes.reserve(n); rightNodes.reserve(n);\n\n    vector<int> localToLeft(n, -1), localToRight(n, -1);\n\n    for(int i=0;i<n;i++){\n        auto c = remCoords[i];\n        int p = (c.x + c.y + c.z) & 1;\n        if(p==0){\n            localToLeft[i] = (int)leftNodes.size();\n            leftNodes.push_back(i);\n        }else{\n            localToRight[i] = (int)rightNodes.size();\n            rightNodes.push_back(i);\n        }\n    }\n\n    int L = (int)leftNodes.size();\n    int R = (int)rightNodes.size();\n    HopcroftKarp hk(L, R);\n\n    const int dx[6] = {1,-1,0,0,0,0};\n    const int dy[6] = {0,0,1,-1,0,0};\n    const int dz[6] = {0,0,0,0,1,-1};\n\n    for(int li=0; li<L; li++){\n        int uLocal = leftNodes[li];\n        auto u = remCoords[uLocal];\n        for(int dir=0; dir<6; dir++){\n            int nx = u.x + dx[dir];\n            int ny = u.y + dy[dir];\n            int nz = u.z + dz[dir];\n            if(nx<0||nx>=D||ny<0||ny>=D||nz<0||nz>=D) continue;\n            int gidx = idx3(D, nx, ny, nz);\n            int vLocal = posToLocal[gidx];\n            if(vLocal < 0) continue;\n            int rv = localToRight[vLocal];\n            if(rv >= 0){\n                hk.add_edge(li, rv);\n            }\n        }\n    }\n\n    hk.max_matching();\n\n    vector<pair<int,int>> matching;\n    matching.reserve(L);\n\n    for(int li=0; li<L; li++){\n        int rj = hk.matchL[li];\n        if(rj != -1){\n            int uLocal = leftNodes[li];\n            int vLocal = rightNodes[rj];\n            matching.push_back({remGlobalIdx[uLocal], remGlobalIdx[vLocal]});\n        }\n    }\n    return matching;\n}\n\nstruct BlockList {\n    // each block is list of global cube indices\n    vector<vector<int>> blocks;\n};\n\nstatic vector<pair<int,int>> dims2x2x1_orients() {\n    // (dx,dy,dz) with multiset {2,2,1}\n    return {{2,2},{2,1},{1,2}}; // not used directly\n}\n\n// Extract axis-aligned 2x2x1 boxes (volume 4) in any orientation.\n// orientations:\n//  - dx=2, dy=2, dz=1\n//  - dx=2, dy=1, dz=2\n//  - dx=1, dy=2, dz=2\nstatic BlockList extract2x2x1(\n    const vector<char>& exist,\n    int D,\n    int need,\n    vector<char>& used\n){\n    BlockList res;\n    res.blocks.reserve(need);\n\n    auto try_place = [&](int ox,int oy,int oz,int dx,int dy,int dz)->bool{\n        vector<int> cubes;\n        cubes.reserve(dx*dy*dz);\n        for(int x=0;x<dx;x++){\n            for(int y=0;y<dy;y++){\n                for(int z=0;z<dz;z++){\n                    int gx=ox+x, gy=oy+y, gz=oz+z;\n                    int id = idx3(D,gx,gy,gz);\n                    if(!exist[id] || used[id]) return false;\n                    cubes.push_back(id);\n                }\n            }\n        }\n        for(int id: cubes) used[id]=1;\n        res.blocks.push_back(std::move(cubes));\n        return true;\n    };\n\n    // fixed greedy scan order\n    struct Ori{int dx,dy,dz;};\n    vector<Ori> oris = {\n        {2,2,1},\n        {2,1,2},\n        {1,2,2}\n    };\n\n    for(auto [dx,dy,dz] : vector<Ori>{{2,2,1},{2,1,2},{1,2,2}}){\n        (void)dx;(void)dy;(void)dz;\n    }\n\n    for(auto ori : oris){\n        int dx=ori.dx, dy=ori.dy, dz=ori.dz;\n        for(int x=0; x+dx<=D && (int)res.blocks.size()<need; x++){\n            for(int y=0; y+dy<=D && (int)res.blocks.size()<need; y++){\n                for(int z=0; z+dz<=D && (int)res.blocks.size()<need; z++){\n                    if(try_place(x,y,z,dx,dy,dz)) {\n                        // placed\n                    }\n                }\n            }\n        }\n    }\n    return res;\n}\n\n// Extract 1x1x3 bars (volume 3) in any orientation.\n// orientations:\n//  - dx=3,dy=1,dz=1\n//  - dx=1,dy=3,dz=1\n//  - dx=1,dy=1,dz=3\nstatic BlockList extract1x1x3(\n    const vector<char>& exist,\n    int D,\n    int need,\n    vector<char>& used\n){\n    BlockList res;\n    res.blocks.reserve(need);\n\n    auto try_place = [&](int ox,int oy,int oz,int dx,int dy,int dz)->bool{\n        vector<int> cubes;\n        cubes.reserve(dx*dy*dz);\n        for(int x=0;x<dx;x++){\n            for(int y=0;y<dy;y++){\n                for(int z=0;z<dz;z++){\n                    int gx=ox+x, gy=oy+y, gz=oz+z;\n                    int id = idx3(D,gx,gy,gz);\n                    if(!exist[id] || used[id]) return false;\n                    cubes.push_back(id);\n                }\n            }\n        }\n        for(int id: cubes) used[id]=1;\n        res.blocks.push_back(std::move(cubes));\n        return true;\n    };\n\n    struct Ori{int dx,dy,dz;};\n    vector<Ori> oris = {\n        {3,1,1},\n        {1,3,1},\n        {1,1,3}\n    };\n\n    for(auto ori : oris){\n        int dx=ori.dx, dy=ori.dy, dz=ori.dz;\n        for(int x=0; x+dx<=D && (int)res.blocks.size()<need; x++){\n            for(int y=0; y+dy<=D && (int)res.blocks.size()<need; y++){\n                for(int z=0; z+dz<=D && (int)res.blocks.size()<need; z++){\n                    if(try_place(x,y,z,dx,dy,dz)) {\n                        // placed\n                    }\n                }\n            }\n        }\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\n    vector<vector<string>> f(2, vector<string>(D));\n    vector<vector<string>> r(2, vector<string>(D));\n\n    for(int i=0;i<2;i++){\n        for(int z=0; z<D; z++){\n            cin >> f[i][z];\n        }\n        for(int z=0; z<D; z++){\n            cin >> r[i][z];\n        }\n    }\n\n    auto buildExist = [&](int i)->vector<char>{\n        vector<char> exist(D*D*D, 0);\n        for(int x=0;x<D;x++){\n            for(int y=0;y<D;y++){\n                for(int z=0;z<D;z++){\n                    if(f[i][z][x]=='1' && r[i][z][y]=='1'){\n                        exist[idx3(D,x,y,z)] = 1;\n                    }\n                }\n            }\n        }\n        return exist;\n    };\n\n    vector<char> exist0 = buildExist(0);\n    vector<char> exist1 = buildExist(1);\n\n    auto getMax2x2x1count = [&](const vector<char>& exist)->int{\n        vector<char> used(D*D*D, 0);\n        int maxNeed = 1000000; // effectively INF\n        auto blk = extract2x2x1(exist, D, maxNeed, used);\n        return (int)blk.blocks.size();\n    };\n\n    int c4max0 = getMax2x2x1count(exist0);\n    int c4max1 = getMax2x2x1count(exist1);\n    int s4 = min(c4max0, c4max1);\n\n    auto buildAfterRectangles = [&](const vector<char>& exist, int s4)->BlockList{\n        vector<char> used(D*D*D*D,0);\n        // place exactly s4 2x2x1 blocks\n        auto rects = extract2x2x1(exist, D, s4, used);\n        // we will reuse 'used' in bars extraction; so return only blocks and stash used via capturing outside\n        // Here we just return blocks; used will be recomputed when needed.\n        return rects;\n    };\n\n    // To compute s3 correctly, we need to place exactly s4 rectangles and then count bars in remaining.\n    auto getMax1x1x3countAfterRect = [&](const vector<char>& exist, int s4)->int{\n        vector<char> used(D*D*D*D,0);\n        auto rects = extract2x2x1(exist, D, s4, used);\n        (void)rects;\n        int maxNeed = 1000000;\n        auto bars = extract1x1x3(exist, D, maxNeed, used);\n        return (int)bars.blocks.size();\n    };\n\n    int c3max0 = getMax1x1x3countAfterRect(exist0, s4);\n    int c3max1 = getMax1x1x3countAfterRect(exist1, s4);\n    int s3 = min(c3max0, c3max1);\n\n    // Now build complete decomposition for shared rectangles and bars, then dominos, then units.\n    auto buildObject = [&](const vector<char>& exist, int s4, int s3){\n        vector<int> b(D*D*D, 0);\n        vector<char> used(D*D*D*D, 0);\n\n        int id = 1;\n        BlockList rects = extract2x2x1(exist, D, s4, used);\n        // assert placed counts are sufficient\n        // (they should be, since s4 chosen via min greedy max)\n        for(int k=0;k<(int)rects.blocks.size();k++){\n            for(int cube : rects.blocks[k]) b[cube] = id + k;\n        }\n        id += (int)rects.blocks.size();\n\n        // If greedy couldn't place all s4 (shouldn't happen), adjust to placed.\n        int placed4 = (int)rects.blocks.size();\n        if(placed4 < s4){\n            // fallback: treat missing as 0-shared; but to stay safe, we just continue.\n            // In practice this shouldn't occur with our construction.\n            s4 = placed4;\n        }\n\n        BlockList bars = extract1x1x3(exist, D, s3, used);\n        int placed3 = (int)bars.blocks.size();\n        for(int k=0;k<placed3;k++){\n            for(int cube : bars.blocks[k]) b[cube] = id + k;\n        }\n        id += placed3;\n\n        // Build remaining cubes\n        vector<int> remGlobal;\n        vector<Coord> remCoords;\n        for(int x=0;x<D;x++){\n            for(int y=0;y<D;y++){\n                for(int z=0;z<D;z++){\n                    int g = idx3(D,x,y,z);\n                    if(exist[g] && !used[g]){\n                        remGlobal.push_back(g);\n                        remCoords.push_back(Coord{x,y,z});\n                    }\n                }\n            }\n        }\n\n        return tuple<vector<int>, vector<char>, vector<int>, vector<Coord>, int, int>(\n            b, used, remGlobal, remCoords, placed4, placed3\n        );\n    };\n\n    auto [b0_init, used_dummy0, remG0, remC0, placed40, placed30] = buildObject(exist0, s4, s3);\n    auto [b1_init, used_dummy1, remG1, remC1, placed41, placed31] = buildObject(exist1, s4, s3);\n\n    // In case greedy placed fewer than requested due to scan limitations,\n    // we recompute shared counts actually placed.\n    // To keep consistent ids, we share only the minimum actually placed.\n    int actual_s4 = min(placed40, placed41);\n    int actual_s3 = min(placed30, placed31);\n\n    // Rebuild both objects with actual_s4/actual_s3 to ensure consistent shared block ids.\n    auto rebuildObjectWithActual = [&](const vector<char>& exist, int actual_s4, int actual_s3){\n        vector<int> b(D*D*D, 0);\n        vector<char> used(D*D*D*D, 0);\n\n        int id = 1;\n        BlockList rects = extract2x2x1(exist, D, actual_s4, used);\n        for(int k=0;k<(int)rects.blocks.size();k++){\n            for(int cube : rects.blocks[k]) b[cube] = id + k;\n        }\n        id += (int)rects.blocks.size();\n\n        BlockList bars = extract1x1x3(exist, D, actual_s3, used);\n        for(int k=0;k<(int)bars.blocks.size();k++){\n            for(int cube : bars.blocks[k]) b[cube] = id + k;\n        }\n        id += (int)bars.blocks.size();\n\n        vector<int> remGlobal;\n        vector<Coord> remCoords;\n        for(int x=0;x<D;x++){\n            for(int y=0;y<D;y++){\n                for(int z=0;z<D;z++){\n                    int g = idx3(D,x,y,z);\n                    if(exist[g] && !used[g]){\n                        remGlobal.push_back(g);\n                        remCoords.push_back(Coord{x,y,z});\n                    }\n                }\n            }\n        }\n        return tuple<vector<int>, vector<int>, vector<Coord>>(b, remGlobal, remCoords);\n    };\n\n    auto [b0, remG0b, remC0b] = rebuildObjectWithActual(exist0, actual_s4, actual_s3);\n    auto [b1, remG1b, remC1b] = rebuildObjectWithActual(exist1, actual_s4, actual_s3);\n\n    // Domino matching on remaining\n    auto domPairs0 = maxDominoMatchingGlobal(remG0b, remC0b, D);\n    auto domPairs1 = maxDominoMatchingGlobal(remG1b, remC1b, D);\n    int k0 = (int)domPairs0.size();\n    int k1 = (int)domPairs1.size();\n    int keepDom = min(k0, k1);\n\n    int idRectEnd = actual_s4;                // ids 1..actual_s4\n    int idBarEnd  = actual_s4 + actual_s3;  // ids actual_s4+1 .. actual_s4+actual_s3\n    int idDomStart = idBarEnd + 1;\n    int idUnitBase = idDomStart + keepDom;\n\n    // Mark selected dominos and assign to b arrays\n    // For object0\n    vector<char> usedRem0(D*D*D*D, 0);\n    for(int j=0;j<keepDom;j++){\n        auto [a,b] = domPairs0[j];\n        usedRem0[a]=1; usedRem0[b]=1;\n        int bid = idDomStart + j;\n        b0[a] = bid;\n        b0[b] = bid;\n    }\n    // For object1\n    vector<char> usedRem1(D*D*D*D, 0);\n    for(int j=0;j<keepDom;j++){\n        auto [a,b] = domPairs1[j];\n        usedRem1[a]=1; usedRem1[b]=1;\n        int bid = idDomStart + j;\n        b1[a] = bid;\n        b1[b] = bid;\n    }\n\n    // Units = remaining cubes not used in selected dominos\n    vector<int> units0, units1;\n    units0.reserve(remG0b.size());\n    units1.reserve(remG1b.size());\n\n    for(int g : remG0b) if(!usedRem0[g]) units0.push_back(g);\n    for(int g : remG1b) if(!usedRem1[g]) units1.push_back(g);\n\n    int u0 = (int)units0.size();\n    int u1 = (int)units1.size();\n    int unitMax = max(u0, u1);\n\n    for(int t=0;t<u0;t++){\n        int bid = idUnitBase + t;\n        b0[units0[t]] = bid;\n    }\n    for(int t=0;t<u1;t++){\n        int bid = idUnitBase + t;\n        b1[units1[t]] = bid;\n    }\n\n    int nBlocks = idUnitBase + unitMax - 1;\n    if(unitMax==0) nBlocks = idDomStart + keepDom - 1; // careful though idUnitBase=...+keepDom, unitMax=0 => base> end\n    if(nBlocks < 0) nBlocks = 0;\n\n    cout << nBlocks << \"\\n\";\n\n    auto printB = [&](const vector<int>& b){\n        bool first = true;\n        for(int x=0;x<D;x++){\n            for(int y=0;y<D;y++){\n                for(int z=0;z<D;z++){\n                    int v = b[idx3(D,x,y,z)];\n                    if(!first) cout << ' ';\n                    first = false;\n                    cout << v;\n                }\n            }\n        }\n        cout << \"\\n\";\n    };\n\n    printB(b0);\n    printB(b1);\n    return 0;\n}","ahc020":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\n\nstatic int ceil_sqrt_ll(long long x) {\n    // returns smallest r s.t. r*r >= x, for x>=0\n    if (x <= 0) return 0;\n    long long r = (long long) sqrt((long double)x);\n    while (r * r < x) ++r;\n    while ((r - 1) * (r - 1) >= x) --r;\n    return (int)r;\n}\n\nstruct Fenwick {\n    int n = 0;\n    vector<int> bit;\n    int bitMask = 1;\n\n    void init(int n_) {\n        if ((int)bit.size() != n_ + 1) bit.assign(n_ + 1, 0);\n        else fill(bit.begin(), bit.end(), 0);\n        n = n_;\n        bitMask = 1;\n        while (bitMask < n) bitMask <<= 1;\n    }\n\n    void add(int idx, int delta) { // idx: 1..n\n        for (; idx <= n; idx += idx & -idx) bit[idx] += delta;\n    }\n\n    int kth(int k) const {\n        // smallest idx such that prefix sum >= k, assuming 1<=k<=total\n        int idx = 0;\n        for (int d = bitMask; d > 0; d >>= 1) {\n            int next = idx + d;\n            if (next <= n && bit[next] < k) {\n                idx = next;\n                k -= bit[next];\n            }\n        }\n        return idx + 1;\n    }\n\n    int getMax(int total) const {\n        if (total == 0) return 0;\n        int pos = kth(total); // fenwick index\n        return pos - 1; // radius = (r+1)-1\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, K;\n    cin >> N >> M >> K;\n    vector<ll> x(N), y(N);\n    for (int i = 0; i < N; i++) cin >> x[i] >> y[i];\n\n    vector<int> U(M), V(M);\n    vector<ll> W(M);\n    vector<vector<tuple<int,ll,int>>> adj(N);\n    for (int j = 0; j < M; j++) {\n        cin >> U[j] >> V[j] >> W[j];\n        --U[j]; --V[j];\n        adj[U[j]].push_back({V[j], W[j], j});\n        adj[V[j]].push_back({U[j], W[j], j});\n    }\n\n    vector<ll> ax(K), ay(K);\n    for (int k = 0; k < K; k++) cin >> ax[k] >> ay[k];\n\n    const int LIM = 5000;\n    const int INF_R = LIM + 1;\n\n    // r[station][resident] = ceil(sqrt(dist^2)) or INF_R if >5000\n    vector<vector<uint16_t>> r(N, vector<uint16_t>(K, INF_R));\n    const long long LIM2 = 1LL * LIM * LIM;\n    for (int i = 0; i < N; i++) {\n        for (int k = 0; k < K; k++) {\n            ll dx = x[i] - ax[k];\n            ll dy = y[i] - ay[k];\n            ll dist2 = dx*dx + dy*dy;\n            if (dist2 > LIM2) continue;\n            int rr = ceil_sqrt_ll(dist2);\n            if (rr > LIM) continue;\n            r[i][k] = (uint16_t)rr;\n        }\n    }\n\n    // Build a shortest-path tree from root 0 by cable weights w_j.\n    // (Tie-break deterministic; could be randomized but kept stable for simplicity.)\n    const ll INF = (1LL<<62);\n    vector<ll> dist(N, INF);\n    vector<int> parent(N, -1), parentEdgeId(N, -1);\n    vector<ll> bestEdgeW(N, INF);\n\n    dist[0] = 0;\n    parent[0] = -1;\n    bestEdgeW[0] = 0;\n    using PII = pair<ll,int>;\n    priority_queue<PII, vector<PII>, greater<PII>> pq;\n    pq.push({0, 0});\n\n    while (!pq.empty()) {\n        auto [d, u] = pq.top(); pq.pop();\n        if (d != dist[u]) continue;\n        for (auto [v, ww, id] : adj[u]) {\n            ll nd = d + ww;\n            if (nd < dist[v]) {\n                dist[v] = nd;\n                parent[v] = u;\n                parentEdgeId[v] = id;\n                bestEdgeW[v] = ww;\n                pq.push({nd, v});\n            } else if (nd == dist[v]) {\n                if (ww < bestEdgeW[v] || (ww == bestEdgeW[v] && u < parent[v])) {\n                    parent[v] = u;\n                    parentEdgeId[v] = id;\n                    bestEdgeW[v] = ww;\n                    pq.push({nd, v});\n                }\n            }\n        }\n    }\n\n    vector<ll> weightToParent(N, 0);\n    for (int v = 1; v < N; v++) weightToParent[v] = W[parentEdgeId[v]];\n\n    // Precompute rooted-tree children and ancestor chains (excluding root).\n    vector<vector<int>> children(N);\n    for (int v = 1; v < N; v++) children[parent[v]].push_back(v);\n\n    vector<vector<int>> anc(N); // anc[v] = nodes on path v->root excluding root, including v\n    vector<int> depthCnt(N, 0);\n    for (int v = 1; v < N; v++) {\n        int cur = v;\n        while (cur != 0) {\n            anc[v].push_back(cur);\n            cur = parent[cur];\n        }\n        depthCnt[v] = (int)anc[v].size();\n        // root depthCnt=0\n    }\n\n    // Candidate sets per resident:\n    // take near-by-radius + shallow-by-depth for diversity\n    const int L = 20;\n    const int Lnear = 14;\n    const int Lshallow = 6;\n\n    vector<vector<int>> cand(K);\n    for (int k = 0; k < K; k++) {\n        vector<pair<int,int>> tmp; // (r, station)\n        tmp.reserve(N);\n        for (int i = 0; i < N; i++) {\n            int need = r[i][k];\n            if (need <= LIM) tmp.push_back({need, i});\n        }\n\n        // near\n        sort(tmp.begin(), tmp.end());\n        vector<int> nearSet;\n        for (int t = 0; t < (int)tmp.size() && (int)nearSet.size() < Lnear; t++)\n            nearSet.push_back(tmp[t].second);\n\n        // shallow\n        vector<pair<int,int>> tmp2;\n        tmp2.reserve(tmp.size());\n        for (auto &pr : tmp) {\n            int i = pr.second;\n            tmp2.push_back({depthCnt[i], i});\n        }\n        sort(tmp2.begin(), tmp2.end());\n        vector<int> shallowSet;\n        for (int t = 0; t < (int)tmp2.size() && (int)shallowSet.size() < Lshallow; t++)\n            shallowSet.push_back(tmp2[t].second);\n\n        // union\n        vector<int> res;\n        res.reserve(L);\n        vector<char> used(N, 0);\n        auto addv = [&](int s) {\n            if (!used[s]) {\n                used[s] = 1;\n                res.push_back(s);\n            }\n        };\n        for (int s : nearSet) addv(s);\n        for (int s : shallowSet) addv(s);\n\n        // if too small, fill with next-nearest\n        if ((int)res.size() < L) {\n            for (auto &pr : tmp) {\n                addv(pr.second);\n                if ((int)res.size() >= L) break;\n            }\n        }\n        cand[k] = std::move(res);\n        // Statement guarantees at least one station within 5000, so cand[k] non-empty.\n    }\n\n    // Greedy clustered initialization for one order permutation.\n    auto buildGreedyAssign = [&](mt19937_64 &rng) -> vector<int> {\n        vector<int> assign(K, -1);\n\n        vector<int> sz(N, 0);             // active station count (for initialization)\n        vector<int> curMax(N, 0);        // current max radius assigned to station\n        vector<int> subtreeCnt(N, 0);   // active stations count in subtree for initialization\n\n        vector<int> order(K);\n        iota(order.begin(), order.end(), 0);\n        shuffle(order.begin(), order.end(), rng);\n\n        for (int k : order) {\n            ll bestDelta = (1LL<<62);\n            vector<int> bestStations;\n\n            for (int to : cand[k]) {\n                int need = (int)r[to][k]; // <= 5000\n                int oldMax = curMax[to];\n                int newMax = max(oldMax, need);\n                ll deltaP = 1LL * newMax * newMax - 1LL * oldMax * oldMax;\n\n                ll deltaEdge = 0;\n                if (sz[to] == 0) {\n                    // station becomes active: add edges along anc[to] where subtreeCnt becomes 1\n                    for (int u : anc[to]) {\n                        if (subtreeCnt[u] == 0) deltaEdge += weightToParent[u];\n                    }\n                }\n                ll delta = deltaP + deltaEdge;\n\n                if (delta < bestDelta) {\n                    bestDelta = delta;\n                    bestStations.clear();\n                    bestStations.push_back(to);\n                } else if (delta == bestDelta) {\n                    bestStations.push_back(to);\n                }\n            }\n\n            int chosen = bestStations[rng() % bestStations.size()];\n            assign[k] = chosen;\n\n            int need = (int)r[chosen][k];\n            bool wasInactive = (sz[chosen] == 0);\n            sz[chosen]++;\n            curMax[chosen] = max(curMax[chosen], need);\n\n            if (wasInactive) {\n                // activate station => increment subtreeCnt along anc[chosen]\n                for (int u : anc[chosen]) subtreeCnt[u] += 1;\n            }\n        }\n        return assign;\n    };\n\n    // Local improvement given an initial assignment, using exact objective within this SPT-union model.\n    auto solveTrial = [&](const vector<int> &assignInit, int timeLimitMs) -> pair<ll, vector<int>> {\n        auto tStart = chrono::steady_clock::now();\n        auto timeUp = [&]() {\n            auto now = chrono::steady_clock::now();\n            return chrono::duration_cast<chrono::milliseconds>(now - tStart).count() > timeLimitMs;\n        };\n\n        vector<int> assign = assignInit;\n\n        // Fenwicks per station for max radius\n        vector<Fenwick> fenw(N);\n        for (int i = 0; i < N; i++) fenw[i].init(LIM + 1);\n\n        vector<int> sz(N, 0);\n        vector<int> P(N, 0);\n\n        for (int k = 0; k < K; k++) {\n            int i = assign[k];\n            int need = (int)r[i][k];\n            fenw[i].add(need + 1, +1);\n            sz[i]++;\n        }\n\n        ll Pcost = 0;\n        for (int i = 0; i < N; i++) {\n            if (sz[i] > 0) P[i] = fenw[i].getMax(sz[i]);\n            else P[i] = 0;\n            Pcost += 1LL * P[i] * P[i];\n        }\n\n        // subtreeCnt by active stations\n        vector<int> subtreeCnt(N, 0);\n        function<int(int)> dfs = [&](int v) -> int {\n            int cnt = (sz[v] > 0) ? 1 : 0;\n            for (int to : children[v]) cnt += dfs(to);\n            subtreeCnt[v] = cnt;\n            return cnt;\n        };\n        dfs(0);\n\n        ll edgeCost = 0;\n        for (int v = 1; v < N; v++) {\n            if (subtreeCnt[v] > 0) edgeCost += weightToParent[v];\n        }\n\n        ll totalCost = Pcost + edgeCost;\n\n        // Temp arrays for deltaEdge when both toggles happen\n        vector<int> mark(N, 0);\n        vector<int> change(N, 0);\n        int stamp = 1;\n\n        auto deltaEdge = [&](int from, int to, bool fromInactive, bool toActive) -> ll {\n            if (!fromInactive && !toActive) return 0LL;\n            ll dE = 0;\n\n            if (fromInactive && !toActive) {\n                for (int u : anc[from]) {\n                    // subtreeCnt[u] decreases by 1; edge toggles off iff it was 1\n                    if (subtreeCnt[u] == 1) dE -= weightToParent[u];\n                }\n                return dE;\n            }\n            if (!fromInactive && toActive) {\n                for (int u : anc[to]) {\n                    // subtreeCnt[u] increases by 1; edge toggles on iff it was 0\n                    if (subtreeCnt[u] == 0) dE += weightToParent[u];\n                }\n                return dE;\n            }\n\n            // both inactive->inactive? actually fromInactive means from becomes empty; toActive means to becomes non-empty\n            // handle overlap exactly\n            int curStamp = stamp++;\n            for (int u : anc[from]) {\n                if (mark[u] != curStamp) {\n                    mark[u] = curStamp;\n                    change[u] = -1;\n                } else change[u] -= 1;\n            }\n            for (int u : anc[to]) {\n                if (mark[u] != curStamp) {\n                    mark[u] = curStamp;\n                    change[u] = +1;\n                } else change[u] += 1;\n            }\n\n            // iterate marked nodes by scanning anc[from] and anc[to] chains (N<=100, ok)\n            // We\u2019ll gather unique nodes quickly.\n            int tmpList[200];\n            int tcnt = 0;\n            auto addUniq = [&](int u) {\n                if (mark[u] == curStamp) {\n                    // check uniq by linear scan (small)\n                    for (int i = 0; i < tcnt; i++) if (tmpList[i] == u) return;\n                    tmpList[tcnt++] = u;\n                }\n            };\n            for (int u : anc[from]) addUniq(u);\n            for (int u : anc[to]) addUniq(u);\n\n            for (int i = 0; i < tcnt; i++) {\n                int u = tmpList[i];\n                int before = subtreeCnt[u];\n                int after = before + change[u];\n                bool b1 = before > 0;\n                bool b2 = after > 0;\n                if (b1 != b2) {\n                    dE += (b2 ? +weightToParent[u] : -weightToParent[u]);\n                }\n            }\n            return dE;\n        };\n\n        auto evalDelta = [&](int k, int to) -> ll {\n            int from = assign[k];\n            if (to == from) return 0LL;\n            int rFrom = (int)r[from][k];\n            int rTo = (int)r[to][k];\n\n            int oldPFrom = P[from], oldPTo = P[to];\n\n            bool fromInactive = (sz[from] == 1);\n            bool toActive = (sz[to] == 0);\n\n            ll dE = deltaEdge(from, to, fromInactive, toActive);\n\n            // delta P via fenwick max update\n            fenw[from].add(rFrom + 1, -1);\n            sz[from]--;\n            fenw[to].add(rTo + 1, +1);\n            sz[to]++;\n\n            int newPFrom = (sz[from] == 0 ? 0 : fenw[from].getMax(sz[from]));\n            int newPTo   = (sz[to] == 0 ? 0 : fenw[to].getMax(sz[to]));\n\n            ll dP = 1LL*newPFrom*newPFrom + 1LL*newPTo*newPTo\n                  - (1LL*oldPFrom*oldPFrom + 1LL*oldPTo*oldPTo);\n\n            // rollback\n            fenw[to].add(rTo + 1, -1);\n            sz[to]--;\n            fenw[from].add(rFrom + 1, +1);\n            sz[from]++;\n\n            return dP + dE;\n        };\n\n        auto commitMove = [&](int k, int to) {\n            int from = assign[k];\n            int rFrom = (int)r[from][k];\n            int rTo = (int)r[to][k];\n\n            int oldPFrom = P[from], oldPTo = P[to];\n            bool fromInactive = (sz[from] == 1);\n            bool toActive = (sz[to] == 0);\n\n            // apply fenwick & Pcost\n            fenw[from].add(rFrom + 1, -1);\n            sz[from]--;\n            fenw[to].add(rTo + 1, +1);\n            sz[to]++;\n\n            int newPFrom = (sz[from] == 0 ? 0 : fenw[from].getMax(sz[from]));\n            int newPTo   = (sz[to] == 0 ? 0 : fenw[to].getMax(sz[to]));\n\n            Pcost += 1LL*newPFrom*newPFrom + 1LL*newPTo*newPTo\n                   - (1LL*oldPFrom*oldPFrom + 1LL*oldPTo*oldPTo);\n\n            P[from] = newPFrom;\n            P[to] = newPTo;\n\n            // update edge cost / subtreeCnt only if active toggles\n            if (fromInactive) {\n                for (int u : anc[from]) {\n                    subtreeCnt[u]--;\n                    if (subtreeCnt[u] == 0) edgeCost -= weightToParent[u];\n                }\n            }\n            if (toActive) {\n                for (int u : anc[to]) {\n                    if (subtreeCnt[u] == 0) edgeCost += weightToParent[u];\n                    subtreeCnt[u]++;\n                }\n            }\n\n            assign[k] = to;\n            totalCost = Pcost + edgeCost;\n        };\n\n        vector<int> order(K);\n        iota(order.begin(), order.end(), 0);\n\n        mt19937_64 rng(1234567 ^ (ll)assign[0] * 1000003);\n\n        for (int pass = 0; pass < 3 && !timeUp(); pass++) {\n            shuffle(order.begin(), order.end(), rng);\n            bool any = false;\n            for (int k : order) {\n                if (timeUp()) break;\n                int from = assign[k];\n\n                ll bestDelta = 0;\n                int bestTo = -1;\n\n                // evaluate all candidates for this resident\n                for (int to : cand[k]) {\n                    if (to == from) continue;\n                    ll d = evalDelta(k, to);\n                    if (d < bestDelta) {\n                        bestDelta = d;\n                        bestTo = to;\n                    }\n                }\n                if (bestTo != -1) {\n                    commitMove(k, bestTo);\n                    any = true;\n                }\n            }\n            if (!any) break;\n        }\n\n        // Build edge selection B from subtreeCnt\n        vector<int> activeEdges(M, 0);\n        for (int v = 1; v < N; v++) {\n            if (subtreeCnt[v] > 0) activeEdges[parentEdgeId[v]] = 1;\n        }\n\n        // score objective uses totalCost; but for output we return P and B packed? We'll rebuild B outside.\n        // We'll return totalCost and store P in a special vector by encoding: [P0..PN-1, dummy]\n        // However easiest: return P only, and rebuild B in main using recomputed? Can't.\n        // So we return totalCost and store B by global capture not possible. We'll return both by rebuilding now:\n        // We'll pack into vector<int> out size N+M as [P, B].\n        vector<int> out(N + M);\n        for (int i = 0; i < N; i++) out[i] = P[i];\n        for (int j = 0; j < M; j++) out[N + j] = activeEdges[j];\n        return {totalCost, out};\n    };\n\n    // Initial assignments:\n    // 1) nearest-by-radius\n    // 2) random among top candidates\n    // 3-5) greedy clustered (different random orders)\n    vector<vector<int>> inits;\n\n    {\n        vector<int> assign0(K);\n        for (int k = 0; k < K; k++) {\n            // cand[k] is union; use smallest required radius among them\n            int best = cand[k][0];\n            int bestNeed = (int)r[best][k];\n            for (int s : cand[k]) {\n                int need = (int)r[s][k];\n                if (need < bestNeed) {\n                    bestNeed = need;\n                    best = s;\n                }\n            }\n            assign0[k] = best;\n        }\n        inits.push_back(assign0);\n    }\n\n    {\n        mt19937_64 rng(777777);\n        vector<int> assign1(K);\n        for (int k = 0; k < K; k++) {\n            int t = min(5, (int)cand[k].size());\n            int idx = rng() % t;\n            // bias towards small radii: pick among first by radii (sort a temp)\n            vector<pair<int,int>> tmp;\n            tmp.reserve(cand[k].size());\n            for (int s : cand[k]) tmp.push_back({(int)r[s][k], s});\n            sort(tmp.begin(), tmp.end());\n            assign1[k] = tmp[idx].second;\n        }\n        inits.push_back(assign1);\n    }\n\n    // Greedy clustered inits\n    for (int rep = 0; rep < 4; rep++) {\n        mt19937_64 rng(12345 + rep * 998244353ULL);\n        inits.push_back(buildGreedyAssign(rng));\n    }\n\n    // Run several trials under time control.\n    // We will try up to 4 different initial assignments.\n    int maxTrials = 4;\n    int timePerTrialMs = 320; // refined from 450ms to allow more candidates/starts\n\n    ll bestCost = (1LL<<62);\n    vector<int> bestOut;\n\n    for (int t = 0; t < (int)inits.size() && t < maxTrials; t++) {\n        auto [cost, out] = solveTrial(inits[t], timePerTrialMs);\n        if (cost < bestCost) {\n            bestCost = cost;\n            bestOut = std::move(out);\n        }\n    }\n\n    // Output best\n    for (int i = 0; i < N; i++) {\n        if (i) cout << ' ';\n        cout << bestOut[i];\n    }\n    cout << '\\n';\n    for (int j = 0; j < M; j++) {\n        if (j) cout << ' ';\n        cout << bestOut[N + j];\n    }\n    cout << '\\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 LIM = 10000;\n\nstruct SwapOp {\n    short x1, y1, x2, y2;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // Precompute cell id <-> (x,y)\n    auto id = [](int x, int y) -> int {\n        return x * (x + 1) / 2 + y;\n    };\n    vector<int> cx(V), cy(V);\n    for (int x = 0; x < N; x++) {\n        for (int y = 0; y <= x; y++) {\n            int idx = id(x, y);\n            cx[idx] = x;\n            cy[idx] = y;\n        }\n    }\n\n    // Read initial pyramid\n    vector<int> at(V);       // token value at cell\n    vector<int> pos(V);      // cell id where token value sits\n    for (int x = 0; x < N; x++) {\n        for (int y = 0; y <= x; y++) {\n            int b;\n            cin >> b;\n            int idx = id(x, y);\n            at[idx] = b;\n            pos[b] = idx;\n        }\n    }\n\n    // key[v] = which tier-block the value v belongs to in sorted order by value\n    // tier t block has size (t+1), cumulative prefix P(t) = 1+2+...+(t+1) = (t+1)(t+2)/2\n    vector<int> key(V, 0);\n    vector<int> pref(N, 0);\n    for (int t = 0; t < N; t++) {\n        pref[t] = (t + 1) * (t + 2) / 2; // 1..465\n    }\n    for (int v = 0; v < V; v++) {\n        int t = 0;\n        while (t < N && v >= pref[t]) t++;\n        key[v] = t; // 0..29\n    }\n\n    auto keyEdgeViolations = [&]() -> int {\n        int cnt = 0;\n        for (int x = 0; x <= N - 2; x++) {\n            for (int y = 0; y <= x; y++) {\n                int u = id(x, y);\n                int c1 = id(x + 1, y);\n                int c2 = id(x + 1, y + 1);\n                if (key[at[u]] > key[at[c1]]) cnt++;\n                if (key[at[u]] > key[at[c2]]) cnt++;\n            }\n        }\n        return cnt;\n    };\n\n    auto computeE = [&]() -> int {\n        int E = 0;\n        for (int x = 0; x <= N - 2; x++) {\n            for (int y = 0; y <= x; y++) {\n                int u = id(x, y);\n                int c1 = id(x + 1, y);\n                int c2 = id(x + 1, y + 1);\n                if (at[u] > at[c1]) E++;\n                if (at[u] > at[c2]) E++;\n            }\n        }\n        return E;\n    };\n\n    vector<SwapOp> ops;\n    ops.reserve(LIM);\n\n    int K = 0;\n\n    auto doSwap = [&](int a, int b) {\n        if (K >= LIM) return false;\n        if (a == b) return true;\n        int va = at[a], vb = at[b];\n        // record coordinates of the cells being swapped\n        ops.push_back(SwapOp{(short)cx[a], (short)cy[a], (short)cx[b], (short)cy[b]});\n        K++;\n        // apply swap\n        swap(at[a], at[b]);\n        pos[va] = b;\n        pos[vb] = a;\n        return true;\n    };\n\n    auto sweepDownKey = [&](int iter) {\n        // x increasing: parent at (x, y), children at (x+1, y) and (x+1, y+1)\n        for (int x = 0; x <= N - 2; x++) {\n            if ((iter & 1) == 0) {\n                for (int y = 0; y <= x; y++) {\n                    int u = id(x, y);\n                    int v1 = id(x + 1, y);\n                    int v2 = id(x + 1, y + 1);\n                    if ((iter & 2) == 0) {\n                        if (key[at[u]] > key[at[v1]]) { if (!doSwap(u, v1)) return; }\n                        if (key[at[u]] > key[at[v2]]) { if (!doSwap(u, v2)) return; }\n                    } else {\n                        if (key[at[u]] > key[at[v2]]) { if (!doSwap(u, v2)) return; }\n                        if (key[at[u]] > key[at[v1]]) { if (!doSwap(u, v1)) return; }\n                    }\n                }\n            } else {\n                for (int y = x; y >= 0; y--) {\n                    int u = id(x, y);\n                    int v1 = id(x + 1, y);\n                    int v2 = id(x + 1, y + 1);\n                    if ((iter & 2) == 0) {\n                        if (key[at[u]] > key[at[v1]]) { if (!doSwap(u, v1)) return; }\n                        if (key[at[u]] > key[at[v2]]) { if (!doSwap(u, v2)) return; }\n                    } else {\n                        if (key[at[u]] > key[at[v2]]) { if (!doSwap(u, v2)) return; }\n                        if (key[at[u]] > key[at[v1]]) { if (!doSwap(u, v1)) return; }\n                    }\n                }\n            }\n            if (K >= LIM) return;\n        }\n    };\n\n    auto sweepUpKey = [&](int iter) {\n        // x decreasing: for each node (x,y) look at its two parents\n        for (int x = N - 1; x >= 1; x--) {\n            if ((iter & 1) == 0) {\n                for (int y = 0; y <= x; y++) {\n                    int v = id(x, y);\n                    int p1 = (y - 1 >= 0) ? id(x - 1, y - 1) : -1; // left parent\n                    int p2 = (y <= x - 1) ? id(x - 1, y) : -1;   // right parent\n                    if ((iter & 2) == 0) {\n                        if (p1 != -1 && key[at[p1]] > key[at[v]]) { if (!doSwap(p1, v)) return; }\n                        if (p2 != -1 && key[at[p2]] > key[at[v]]) { if (!doSwap(p2, v)) return; }\n                    } else {\n                        if (p2 != -1 && key[at[p2]] > key[at[v]]) { if (!doSwap(p2, v)) return; }\n                        if (p1 != -1 && key[at[p1]] > key[at[v]]) { if (!doSwap(p1, v)) return; }\n                    }\n                }\n            } else {\n                for (int y = x; y >= 0; y--) {\n                    int v = id(x, y);\n                    int p1 = (y - 1 >= 0) ? id(x - 1, y - 1) : -1;\n                    int p2 = (y <= x - 1) ? id(x - 1, y) : -1;\n                    if ((iter & 2) == 0) {\n                        if (p1 != -1 && key[at[p1]] > key[at[v]]) { if (!doSwap(p1, v)) return; }\n                        if (p2 != -1 && key[at[p2]] > key[at[v]]) { if (!doSwap(p2, v)) return; }\n                    } else {\n                        if (p2 != -1 && key[at[p2]] > key[at[v]]) { if (!doSwap(p2, v)) return; }\n                        if (p1 != -1 && key[at[p1]] > key[at[v]]) { if (!doSwap(p1, v)) return; }\n                    }\n                }\n            }\n            if (K >= LIM) return;\n        }\n    };\n\n    auto sweepDownEqualVal = [&](int iter) {\n        // swap only if keys are equal and actual values violate\n        for (int x = 0; x <= N - 2; x++) {\n            if ((iter & 1) == 0) {\n                for (int y = 0; y <= x; y++) {\n                    int u = id(x, y);\n                    int v1 = id(x + 1, y);\n                    int v2 = id(x + 1, y + 1);\n                    auto tryChild = [&](int c) {\n                        if (key[at[u]] == key[at[c]] && at[u] > at[c]) {\n                            doSwap(u, c);\n                        }\n                    };\n                    if ((iter & 2) == 0) {\n                        tryChild(v1);\n                        tryChild(v2);\n                    } else {\n                        tryChild(v2);\n                        tryChild(v1);\n                    }\n                    if (K >= LIM) return;\n                }\n            } else {\n                for (int y = x; y >= 0; y--) {\n                    int u = id(x, y);\n                    int v1 = id(x + 1, y);\n                    int v2 = id(x + 1, y + 1);\n                    auto tryChild = [&](int c) {\n                        if (key[at[u]] == key[at[c]] && at[u] > at[c]) {\n                            doSwap(u, c);\n                        }\n                    };\n                    if ((iter & 2) == 0) {\n                        tryChild(v1);\n                        tryChild(v2);\n                    } else {\n                        tryChild(v2);\n                        tryChild(v1);\n                    }\n                    if (K >= LIM) return;\n                }\n            }\n        }\n    };\n\n    auto sweepUpEqualVal = [&](int iter) {\n        for (int x = N - 1; x >= 1; x--) {\n            if ((iter & 1) == 0) {\n                for (int y = 0; y <= x; y++) {\n                    int v = id(x, y);\n                    int p1 = (y - 1 >= 0) ? id(x - 1, y - 1) : -1;\n                    int p2 = (y <= x - 1) ? id(x - 1, y) : -1;\n\n                    auto tryParent = [&](int p) {\n                        if (p != -1 && key[at[p]] == key[at[v]] && at[p] > at[v]) {\n                            doSwap(p, v);\n                        }\n                    };\n                    if ((iter & 2) == 0) {\n                        tryParent(p1);\n                        tryParent(p2);\n                    } else {\n                        tryParent(p2);\n                        tryParent(p1);\n                    }\n                    if (K >= LIM) return;\n                }\n            } else {\n                for (int y = x; y >= 0; y--) {\n                    int v = id(x, y);\n                    int p1 = (y - 1 >= 0) ? id(x - 1, y - 1) : -1;\n                    int p2 = (y <= x - 1) ? id(x - 1, y) : -1;\n\n                    auto tryParent = [&](int p) {\n                        if (p != -1 && key[at[p]] == key[at[v]] && at[p] > at[v]) {\n                            doSwap(p, v);\n                        }\n                    };\n                    if ((iter & 2) == 0) {\n                        tryParent(p1);\n                        tryParent(p2);\n                    } else {\n                        tryParent(p2);\n                        tryParent(p1);\n                    }\n                    if (K >= LIM) return;\n                }\n            }\n        }\n    };\n\n    // Stage 1: fix key-order inversions along edges\n    int maxIter1 = 60;\n    for (int iter = 0; iter < maxIter1; iter++) {\n        if (K >= LIM) break;\n        sweepDownKey(iter);\n        if (K >= LIM) break;\n        sweepUpKey(iter);\n\n        if (keyEdgeViolations() == 0) break;\n    }\n\n    // If already perfect, stop\n    if (computeE() == 0) {\n        cout << K << \"\\n\";\n        for (auto &op : ops) {\n            cout << op.x1 << \" \" << op.y1 << \" \" << op.x2 << \" \" << op.y2 << \"\\n\";\n        }\n        return 0;\n    }\n\n    // Stage 2: only equal-key edges can still violate now, so fix them by value compare-swap\n    int maxIter2 = 120;\n    for (int iter = 0; iter < maxIter2; iter++) {\n        if (K >= LIM) break;\n        sweepDownEqualVal(iter);\n        if (K >= LIM) break;\n        sweepUpEqualVal(iter);\n\n        if (computeE() == 0) break;\n    }\n\n    cout << K << \"\\n\";\n    for (auto &op : ops) {\n        cout << op.x1 << \" \" << op.y1 << \" \" << op.x2 << \" \" << op.y2 << \"\\n\";\n    }\n    return 0;\n}","toyota2023summer-final":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\n\nstatic const int dx4[4] = {-1, 1, 0, 0}; // up, down, left, right (in i, j coordinates)\nstatic const int dy4[4] = {0, 0, -1, 1};\n\nstruct Tree {\n    int V = 0;\n    int entrance = -1;\n    vector<int> parent;\n    vector<int> depth;\n    vector<int> bfsOrder;\n    vector<vector<int>> children;\n};\n\nstatic Tree build_tree(\n    int D,\n    const vector<vector<int>>& id,\n    int entranceVid,\n    const vector<int>& dirOrder\n) {\n    int V = 0;\n    for (int i = 0; i < D; i++) for (int j = 0; j < D; j++) if (id[i][j] >= 0) V = max(V, id[i][j] + 1);\n\n    vector<int> parent(V, -1), depth(V, -1), bfsOrder(V, -1);\n    vector<vector<int>> children(V);\n    vector<char> vis(V, 0);\n\n    queue<int> q;\n    vis[entranceVid] = 1;\n    depth[entranceVid] = 0;\n    parent[entranceVid] = -1;\n    bfsOrder[entranceVid] = 0;\n    int ord = 1;\n    q.push(entranceVid);\n\n    auto coord_of = [&](int v) -> pair<int,int> {\n        // id -> (i,j) inverse isn't stored; reconstruct by scanning (small D=9, ok)\n        for (int i = 0; i < D; i++) for (int j = 0; j < D; j++) {\n            if (id[i][j] == v) return {i, j};\n        }\n        return {-1,-1};\n    };\n\n    while (!q.empty()) {\n        int v = q.front(); q.pop();\n        auto [x, y] = coord_of(v);\n        for (int di : dirOrder) {\n            int nx = x + dx4[di];\n            int ny = y + dy4[di];\n            if (nx < 0 || nx >= D || ny < 0 || ny >= D) continue;\n            int nid = id[nx][ny];\n            if (nid < 0) continue;\n            if (vis[nid]) continue;\n            vis[nid] = 1;\n            parent[nid] = v;\n            depth[nid] = depth[v] + 1;\n            bfsOrder[nid] = ord++;\n            q.push(nid);\n        }\n    }\n\n    for (int v = 0; v < V; v++) {\n        if (v == entranceVid) continue;\n        int p = parent[v];\n        if (p >= 0) children[p].push_back(v);\n    }\n\n    Tree t;\n    t.V = V;\n    t.entrance = entranceVid;\n    t.parent = move(parent);\n    t.depth = move(depth);\n    t.bfsOrder = move(bfsOrder);\n    t.children = move(children);\n    return t;\n}\n\nstatic vector<int> simulate_proxy_pos(\n    const Tree& tree,\n    const vector<int>& key2, // additional tie key (unique-ish) combined with depth and key2\n    bool useKey2Sign\n) {\n    int V = tree.V;\n    int ent = tree.entrance;\n    int M = V - 1;\n\n    // priority: (depth, +/-key2, bfsOrder)\n    struct Node {\n        int pri1, pri2, pri3, v;\n    };\n    struct Cmp {\n        bool operator()(const Node& a, const Node& b) const {\n            if (a.pri1 != b.pri1) return a.pri1 > b.pri1; // min-heap\n            if (a.pri2 != b.pri2) return a.pri2 > b.pri2;\n            if (a.pri3 != b.pri3) return a.pri3 > b.pri3;\n            return a.v > b.v;\n        }\n    };\n\n    priority_queue<Node, vector<Node>, Cmp> pq;\n    vector<char> inited(V, 0);\n\n    for (int ch : tree.children[ent]) {\n        pq.push({tree.depth[ch], useKey2Sign ? key2[ch] : key2[ch], tree.bfsOrder[ch], ch});\n        inited[ch] = 1;\n    }\n\n    vector<int> pos(V, -1);\n    int cnt = 0;\n    vector<char> removed(V, 0);\n\n    auto push_children = [&](int v) {\n        for (int ch : tree.children[v]) {\n            if (!removed[ch]) pq.push({tree.depth[ch], useKey2Sign ? key2[ch] : key2[ch], tree.bfsOrder[ch], ch});\n        }\n    };\n\n    while (cnt < M) {\n        if (pq.empty()) break; // should not happen\n        auto cur = pq.top(); pq.pop();\n        int v = cur.v;\n        if (removed[v]) continue;\n        removed[v] = 1;\n        pos[v] = cnt++;\n        push_children(v);\n    }\n\n    return pos;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int D, N;\n    cin >> D >> N;\n    vector<vector<bool>> obs(D, vector<bool>(D, false));\n    for (int k = 0; k < N; k++) {\n        int ri, rj;\n        cin >> ri >> rj;\n        obs[ri][rj] = true;\n    }\n\n    int ei = 0, ej = (D - 1) / 2;\n    // build id mapping\n    vector<vector<int>> id(D, vector<int>(D, -1));\n    vector<pair<int,int>> coord;\n    coord.reserve(D * D);\n\n    int V = 0;\n    for (int i = 0; i < D; i++) for (int j = 0; j < D; j++) {\n        if (obs[i][j]) continue;\n        id[i][j] = V++;\n        coord.push_back({i, j});\n    }\n\n    int entranceVid = id[ei][ej];\n    int M = V - 1; // number of containers\n\n    // Try multiple BFS parent-construction variants and pick best structural tree.\n    vector<vector<int>> dirOrders = {\n        {0, 3, 1, 2}, // up,right,down,left\n        {0, 2, 1, 3}, // up,left,down,right\n        {1, 3, 0, 2}, // down,right,up,left\n        {1, 2, 0, 3}, // down,left,up,right\n        {3, 0, 2, 1}, // right,up,left,down\n        {2, 0, 3, 1}, // left,up,right,down\n    };\n\n    Tree bestTree;\n    int bestScore = -1e9;\n\n    for (auto &order : dirOrders) {\n        Tree t = build_tree(D, id, entranceVid, order);\n\n        // structural heuristic: more leaves and smaller average depth\n        int leaves = 0;\n        ll sumDepth = 0;\n        for (int v = 0; v < t.V; v++) {\n            if (v == t.entrance) continue;\n            sumDepth += t.depth[v];\n            if ((int)t.children[v].size() == 0) leaves++;\n        }\n        double avgDepth = (double)sumDepth / max(1, M);\n        int score = (int)(leaves * 1000 - avgDepth * 10.0); // weight leaves strongly\n        if (score > bestScore) {\n            bestScore = score;\n            bestTree = move(t);\n        }\n    }\n\n    const Tree& tree = bestTree;\n\n    // compute subtree sizes for tie-break priorities\n    vector<int> subtreeSize(tree.V, 1);\n    vector<int> byDepthDesc(tree.V);\n    iota(byDepthDesc.begin(), byDepthDesc.end(), 0);\n    sort(byDepthDesc.begin(), byDepthDesc.end(), [&](int a, int b){\n        return tree.depth[a] > tree.depth[b];\n    });\n    for (int v : byDepthDesc) {\n        for (int ch : tree.children[v]) subtreeSize[v] += subtreeSize[ch];\n    }\n\n    // initial priority keys: use subtreeSize as tie key\n    vector<int> keyA(tree.V), keyB(tree.V);\n    for (int v = 0; v < tree.V; v++) {\n        keyA[v] = -subtreeSize[v];\n        keyB[v] = +subtreeSize[v];\n    }\n\n    // simulate proxy removal order using greedy by (depth, key*, bfsOrder)\n    // pos1 and pos2 are ranks 0..M-1 (only meaningful for v!=entrance)\n    auto pos1 = simulate_proxy_pos(tree, keyA, true);\n    auto pos2 = simulate_proxy_pos(tree, keyB, true);\n\n    // Insertion (online): maintain nodes whose children are already inserted\n    vector<int> remChildCnt(tree.V, 0);\n    for (int v = 0; v < tree.V; v++) {\n        if (v == tree.entrance) continue;\n        remChildCnt[v] = (int)tree.children[v].size();\n    }\n\n    set<int> ready;\n    for (int v = 0; v < tree.V; v++) {\n        if (v == tree.entrance) continue;\n        if (remChildCnt[v] == 0) ready.insert(v);\n    }\n\n    vector<char> inserted(tree.V, 0);\n    vector<int> label(tree.V, -1);\n\n    vector<int> assignedNodes;\n    assignedNodes.reserve(M);\n\n    for (int d = 0; d < M; d++) {\n        int t_d;\n        cin >> t_d;\n\n        int bestV = -1;\n        int bestCost = INT_MAX;\n        int bestTie = INT_MAX;\n\n        for (int v : ready) {\n            int p1 = pos1[v];\n            int p2 = pos2[v];\n\n            int cost1 = 0, cost2 = 0;\n            for (int u : assignedNodes) {\n                int a1 = pos1[u];\n                int a2 = pos2[u];\n                int labU = label[u];\n\n                // inversion in proxy1\n                if (a1 < p1) {\n                    if (labU > t_d) cost1++;\n                } else { // a1 > p1 (unique ranks)\n                    if (t_d > labU) cost1++;\n                }\n\n                // inversion in proxy2\n                if (a2 < p2) {\n                    if (labU > t_d) cost2++;\n                } else {\n                    if (t_d > labU) cost2++;\n                }\n            }\n\n            int totalCost = cost1 + cost2;\n\n            int tie = abs(p1 - t_d) + abs(p2 - t_d);\n            if (totalCost < bestCost || (totalCost == bestCost && tie < bestTie)) {\n                bestCost = totalCost;\n                bestTie = tie;\n                bestV = v;\n            }\n        }\n\n        // output storing location for container t_d into node bestV\n        auto [pi, pj] = coord[bestV];\n        cout << pi << ' ' << pj << \"\\n\" << flush;\n\n        inserted[bestV] = 1;\n        label[bestV] = t_d;\n        assignedNodes.push_back(bestV);\n\n        ready.erase(bestV);\n\n        int p = tree.parent[bestV];\n        if (p >= 0 && p != tree.entrance) {\n            remChildCnt[p]--;\n            if (remChildCnt[p] == 0) ready.insert(p);\n        } else if (p == tree.entrance) {\n            // entrance isn't a container node, ignore\n        }\n    }\n\n    // Transport (offline): remove nodes using min-heap by actual label among currently removable nodes.\n    vector<char> removed(tree.V, 0);\n    priority_queue<pair<int,int>, vector<pair<int,int>>, greater<pair<int,int>>> pq;\n    for (int ch : tree.children[tree.entrance]) {\n        pq.push({label[ch], ch});\n    }\n\n    vector<int> transportOrder;\n    transportOrder.reserve(M);\n\n    while ((int)transportOrder.size() < M) {\n        auto [lab, v] = pq.top(); pq.pop();\n        if (removed[v]) continue;\n        removed[v] = 1;\n        transportOrder.push_back(v);\n\n        for (int ch : tree.children[v]) {\n            if (!removed[ch]) pq.push({label[ch], ch});\n        }\n    }\n\n    for (int k = 0; k < M; k++) {\n        auto [qi, qj] = coord[transportOrder[k]];\n        cout << qi << ' ' << qj << \"\\n\" << flush;\n    }\n\n    return 0;\n}","ahc024":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const int DIRS[4][2] = {{1,0},{-1,0},{0,1},{0,-1}};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int n, m;\n    cin >> n >> m;\n    vector<vector<int>> a(n, vector<int>(n));\n    for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) cin >> a[i][j];\n\n    auto idx = [&](int i, int j){ return i*n + j; };\n    auto unidx = [&](int id){ return pair<int,int>(id/n, id%n); };\n\n    // Original adjacency matrix among colors 0..m\n    vector<vector<unsigned char>> adjOrig(m+1, vector<unsigned char>(m+1, 0));\n    for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) {\n        int c1 = a[i][j];\n        for (auto &dr: DIRS) {\n            int ni = i + dr[0], nj = j + dr[1];\n            int c2 = (ni < 0 || ni >= n || nj < 0 || nj >= n) ? 0 : a[ni][nj];\n            if (c1 == c2) continue;\n            int x = min(c1, c2), y = max(c1, c2);\n            adjOrig[x][y] = 1;\n        }\n    }\n\n    // posByColor\n    vector<vector<int>> posByColor(m+1);\n    for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) posByColor[a[i][j]].push_back(idx(i,j));\n\n    // touchOutside[c] : whether color c appears on boundary in original\n    vector<unsigned char> touchOutside(m+1, 0);\n    for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) {\n        if (i==0 || i==n-1 || j==0 || j==n-1) touchOutside[a[i][j]] = 1;\n    }\n\n    // Representative adjacent cell pairs for ward colors (not including 0)\n    // repEdges[x][y] (1<=x<y<=m) stores pairs (cell of x, cell of y) where those colors are adjacent in original.\n    vector<vector<vector<pair<int,int>>>> repEdges(m+1, vector<vector<pair<int,int>>>(m+1));\n    for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) {\n        int u = a[i][j];\n        if (j+1 < n) {\n            int v = a[i][j+1];\n            if (u != v) {\n                int x = min(u,v), y = max(u,v);\n                if (x >= 1 && y >= 1) {\n                    int id_x = (u==x ? idx(i,j) : idx(i,j+1));\n                    int id_y = (u==x ? idx(i,j+1) : idx(i,j));\n                    repEdges[x][y].push_back({id_x, id_y});\n                }\n            }\n        }\n        if (i+1 < n) {\n            int v = a[i+1][j];\n            if (u != v) {\n                int x = min(u,v), y = max(u,v);\n                if (x >= 1 && y >= 1) {\n                    int id_x = (u==x ? idx(i,j) : idx(i+1,j));\n                    int id_y = (u==x ? idx(i+1,j) : idx(i,j));\n                    repEdges[x][y].push_back({id_x, id_y});\n                }\n            }\n        }\n    }\n\n    // boundary cells list per color\n    vector<vector<int>> boundaryCells(m+1);\n    for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) {\n        if (i==0 || i==n-1 || j==0 || j==n-1) {\n            int c = a[i][j];\n            boundaryCells[c].push_back(idx(i,j));\n        }\n    }\n\n    // Connect all components of color c within original region of c (cells where a==c),\n    // by recoloring some cells to c.\n    auto connectColor = [&](vector<vector<int>> &b, int c) {\n        vector<unsigned char> seen(n*n, 0);\n        vector<vector<int>> comps;\n\n        for (int id : posByColor[c]) {\n            auto [ci,cj] = unidx(id);\n            if (b[ci][cj] != c) continue;\n            if (seen[id]) continue;\n\n            vector<int> comp;\n            queue<int> q;\n            seen[id] = 1;\n            q.push(id);\n            while(!q.empty()){\n                int cur = q.front(); q.pop();\n                comp.push_back(cur);\n                auto [x,y] = unidx(cur);\n                for (auto &dr: DIRS) {\n                    int nx=x+dr[0], ny=y+dr[1];\n                    if (nx<0||nx>=n||ny<0||ny>=n) continue;\n                    if (b[nx][ny] != c) continue;\n                    int nid = idx(nx,ny);\n                    if (!seen[nid]) { seen[nid]=1; q.push(nid); }\n                }\n            }\n            comps.push_back(std::move(comp));\n        }\n\n        if (comps.size() <= 1) return;\n\n        vector<unsigned char> target(n*n, 0);\n        for (int id : comps[0]) target[id] = 1;\n\n        vector<int> dist(n*n), parent(n*n);\n\n        for (size_t k = 1; k < comps.size(); k++) {\n            int startId = comps[k][0];\n\n            fill(dist.begin(), dist.end(), -1);\n            fill(parent.begin(), parent.end(), -1);\n\n            queue<int> q;\n            dist[startId] = 0;\n            q.push(startId);\n\n            int reached = -1;\n            while(!q.empty() && reached == -1) {\n                int cur = q.front(); q.pop();\n                if (target[cur]) { reached = cur; break; }\n                auto [ci,cj] = unidx(cur);\n                for (auto &dr: DIRS) {\n                    int ni=ci+dr[0], nj=cj+dr[1];\n                    if (ni<0||ni>=n||nj<0||nj>=n) continue;\n                    if (a[ni][nj] != c) continue; // only traverse original c cells\n                    int nid = idx(ni,nj);\n                    if (dist[nid] != -1) continue;\n                    dist[nid] = dist[cur] + 1;\n                    parent[nid] = cur;\n                    q.push(nid);\n                }\n            }\n\n            if (reached == -1) continue; // should not happen\n            int cur = reached;\n            while(cur != startId) {\n                auto [x,y] = unidx(cur);\n                b[x][y] = c;\n                cur = parent[cur];\n                if (cur == -1) break;\n            }\n            auto [sx,sy] = unidx(startId);\n            b[sx][sy] = c;\n        }\n    };\n\n    auto checkAll = [&](const vector<vector<int>> &b)->bool{\n        // 1) ward colors connectivity + non-empty (should be non-empty in our construction)\n        vector<unsigned char> vis(n*n, 0);\n\n        for (int c = 1; c <= m; c++) {\n            int start = -1, tot = 0;\n            for (int id : posByColor[c]) {\n                auto [i,j] = unidx(id);\n                if (b[i][j] == c) {\n                    tot++;\n                    if (start == -1) start = id;\n                }\n            }\n            if (tot == 0) return false;\n            fill(vis.begin(), vis.end(), 0);\n            queue<int> q;\n            vis[start] = 1;\n            q.push(start);\n            int cnt = 1;\n            while(!q.empty()) {\n                int cur = q.front(); q.pop();\n                auto [i,j] = unidx(cur);\n                for (auto &dr: DIRS) {\n                    int ni=i+dr[0], nj=j+dr[1];\n                    if (ni<0||ni>=n||nj<0||nj>=n) continue;\n                    if (b[ni][nj] != c) continue;\n                    int nid = idx(ni,nj);\n                    if (!vis[nid]) { vis[nid]=1; q.push(nid); cnt++; }\n                }\n            }\n            if (cnt != tot) return false;\n        }\n\n        // 2) connectivity of color 0 through outside\n        int N = n + 2;\n        auto idExt = [&](int x,int y){ return x*N + y; };\n        vector<unsigned char> vis0(N*N, 0);\n        queue<pair<int,int>> q;\n        vis0[idExt(0,0)] = 1;\n        q.push({0,0});\n        while(!q.empty()){\n            auto [x,y] = q.front(); q.pop();\n            for (auto &dr: DIRS) {\n                int nx=x+dr[0], ny=y+dr[1];\n                if (nx<0||nx>=N||ny<0||ny>=N) continue;\n                bool pass;\n                if (nx==0||nx==N-1||ny==0||ny==N-1) pass = true; // outside\n                else pass = (b[nx-1][ny-1] == 0);\n                if (!pass) continue;\n                int nid = idExt(nx,ny);\n                if (!vis0[nid]) { vis0[nid]=1; q.push({nx,ny}); }\n            }\n        }\n        for (int i=0;i<n;i++) for (int j=0;j<n;j++) {\n            if (b[i][j] == 0) {\n                if (!vis0[idExt(i+1,j+1)]) return false;\n            }\n        }\n\n        // 3) adjacency equivalence\n        vector<vector<unsigned char>> adjOut(m+1, vector<unsigned char>(m+1, 0));\n        for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) {\n            int c1 = b[i][j];\n            for (auto &dr: DIRS) {\n                int ni=i+dr[0], nj=j+dr[1];\n                int c2 = (ni<0||ni>=n||nj<0||nj>=n) ? 0 : b[ni][nj];\n                if (c1 == c2) continue;\n                int x = min(c1,c2), y = max(c1,c2);\n                adjOut[x][y] = 1;\n            }\n        }\n        for (int x=0;x<=m;x++) for (int y=x+1;y<=m;y++){\n            if (adjOut[x][y] != adjOrig[x][y]) return false;\n        }\n        return true;\n    };\n\n    // Try to connect all required nodes for a color c with a BFS-tree rooted at some candidate root,\n    // choosing the root that minimizes kept nodes count for that color.\n    auto connectColorByRequired = [&](vector<vector<int>> &b, int c, const vector<int> &req, int root, vector<int> &tmpMark)->void {\n        fill(tmpMark.begin(), tmpMark.end(), 0);\n        vector<int> parent(n*n, -1);\n        queue<int> q;\n        parent[root] = root;\n        q.push(root);\n        while(!q.empty()){\n            int cur=q.front(); q.pop();\n            auto [x,y] = unidx(cur);\n            for (auto &dr: DIRS){\n                int nx=x+dr[0], ny=y+dr[1];\n                if (nx<0||nx>=n||ny<0||ny>=n) continue;\n                if (a[nx][ny] != c) continue;\n                int nid=idx(nx,ny);\n                if (parent[nid] != -1) continue;\n                parent[nid]=cur;\n                q.push(nid);\n            }\n        }\n        // Trace paths for all required nodes; mark all vertices on union of paths.\n        for (int t : req) {\n            if (parent[t] == -1) continue; // should not happen\n            int cur = t;\n            while(cur != root){\n                tmpMark[cur] = 1;\n                cur = parent[cur];\n                if (cur == -1) break;\n            }\n            tmpMark[root] = 1;\n        }\n        // Apply to b\n        for (int id : req) { (void)id; }\n        for (int id = 0; id < n*n; id++) {\n            if (tmpMark[id]) {\n                auto [x,y]=unidx(id);\n                b[x][y]=c;\n            }\n        }\n    };\n\n    mt19937_64 rng((uint64_t)chrono::high_resolution_clock::now().time_since_epoch().count());\n\n    // Precompute list of adjacent ward pairs present in original\n    vector<pair<int,int>> adjPairs;\n    for (int x=1;x<=m;x++) for (int y=x+1;y<=m;y++){\n        if (adjOrig[x][y]) adjPairs.push_back({x,y});\n    }\n\n    vector<vector<int>> best;\n    int bestZero = -1;\n    bool found = false;\n\n    auto startTime = chrono::high_resolution_clock::now();\n\n    int T = 40; // will be cut by time\n    for (int trial = 0; trial < T; trial++) {\n        double elapsed = chrono::duration<double>(chrono::high_resolution_clock::now() - startTime).count();\n        if (elapsed > 1.85) break;\n\n        vector<vector<int>> b(n, vector<int>(n, 0));\n\n        // Required endpoints per color\n        vector<vector<int>> req(m+1);\n        vector<vector<unsigned char>> reqMark(m+1); // only for small colors; allocate as needed\n        for (int c=1;c<=m;c++) reqMark[c].assign(n*n, 0);\n\n        // Choose one representative for each adjacent ward pair.\n        for (auto [x,y] : adjPairs) {\n            auto &vec = repEdges[x][y];\n            if (vec.empty()) { reqMark.clear(); break; }\n            auto e = vec[(size_t)(rng() % vec.size())];\n            auto [id_x, id_y] = e;\n            auto [xx,xy] = unidx(id_x);\n            auto [yx,yy] = unidx(id_y);\n            (void)xx; (void)xy; (void)yx; (void)yy;\n\n            if (!reqMark[x].empty() && !reqMark[x][id_x]) {\n                reqMark[x][id_x]=1; req[x].push_back(id_x);\n            }\n            if (!reqMark[y].empty() && !reqMark[y][id_y]) {\n                reqMark[y][id_y]=1; req[y].push_back(id_y);\n            }\n        }\n        // Add boundary requirement for colors that touch outside; and ensure non-empty for all colors.\n        bool bad = false;\n        for (int c=1;c<=m;c++) {\n            if (touchOutside[c]) {\n                if (boundaryCells[c].empty()) { bad = true; break; }\n                int choose = boundaryCells[c][(size_t)(rng() % boundaryCells[c].size())];\n                if (!reqMark[c][choose]) { reqMark[c][choose]=1; req[c].push_back(choose); }\n            }\n            if (req[c].empty()) {\n                // keep at least one cell of each color\n                int seed = posByColor[c][(size_t)(rng() % posByColor[c].size())];\n                if (!reqMark[c][seed]) { reqMark[c][seed]=1; req[c].push_back(seed); }\n            }\n        }\n        if (bad) continue;\n\n        // Build each color connected subgraph.\n        vector<int> tmpMark(n*n);\n\n        for (int c=1;c<=m;c++) {\n            // Choose candidate roots among required nodes (up to 3)\n            const auto &R = req[c];\n            int k = (int)R.size();\n            vector<int> candidates;\n            candidates.reserve(min(3, k));\n            // Always include first element\n            candidates.push_back(R[0]);\n            while ((int)candidates.size() < min(3, k)) {\n                int cand = R[(size_t)(rng() % R.size())];\n                if (find(candidates.begin(), candidates.end(), cand) == candidates.end())\n                    candidates.push_back(cand);\n            }\n\n            int bestRoot = candidates[0];\n            int bestKeep = INT_MAX;\n\n            // Evaluate root by approximating union-of-path size via tracing on BFS parent\n            for (int root : candidates) {\n                vector<int> parent(n*n, -1);\n                queue<int> q;\n                parent[root] = root;\n                q.push(root);\n                while(!q.empty()){\n                    int cur=q.front(); q.pop();\n                    auto [x,y]=unidx(cur);\n                    for (auto &dr: DIRS){\n                        int nx=x+dr[0], ny=y+dr[1];\n                        if (nx<0||nx>=n||ny<0||ny>=n) continue;\n                        if (a[nx][ny] != c) continue;\n                        int nid=idx(nx,ny);\n                        if (parent[nid]!=-1) continue;\n                        parent[nid]=cur;\n                        q.push(nid);\n                    }\n                }\n                // trace union\n                fill(tmpMark.begin(), tmpMark.end(), 0);\n                int keep = 0;\n                for (int t : R) {\n                    if (parent[t] == -1) { keep = INT_MAX/2; break; }\n                    int cur = t;\n                    while(cur != root) {\n                        if (!tmpMark[cur]) { tmpMark[cur]=1; keep++; }\n                        cur = parent[cur];\n                        if (cur==-1) break;\n                    }\n                    if (!tmpMark[root]) { tmpMark[root]=1; keep++; }\n                }\n                if (keep < bestKeep) {\n                    bestKeep = keep;\n                    bestRoot = root;\n                }\n            }\n\n            // Apply best root\n            connectColorByRequired(b, c, R, bestRoot, tmpMark);\n        }\n\n        // Fix 0 connectivity by restoring enclosed zeros, then reconnect wards affected.\n        // Iterate because ward reconnection may consume 0 corridors.\n        for (int iter = 0; iter < 12; iter++) {\n            int N = n+2;\n            auto idExt = [&](int x,int y){ return x*N + y; };\n            vector<unsigned char> vis0(N*N, 0);\n            queue<pair<int,int>> q;\n            vis0[idExt(0,0)] = 1;\n            q.push({0,0});\n            while(!q.empty()){\n                auto [x,y]=q.front(); q.pop();\n                for (auto &dr: DIRS){\n                    int nx=x+dr[0], ny=y+dr[1];\n                    if (nx<0||nx>=N||ny<0||ny>=N) continue;\n                    bool pass;\n                    if (nx==0||nx==N-1||ny==0||ny==N-1) pass = true;\n                    else pass = (b[nx-1][ny-1] == 0);\n                    if (!pass) continue;\n                    int nid=idExt(nx,ny);\n                    if (!vis0[nid]) { vis0[nid]=1; q.push({nx,ny}); }\n                }\n            }\n\n            vector<unsigned char> changed(m+1, 0);\n            bool anyHole = false;\n            for (int i=0;i<n;i++) for (int j=0;j<n;j++) {\n                if (b[i][j] == 0) {\n                    if (!vis0[idExt(i+1,j+1)]) {\n                        anyHole = true;\n                        int c = a[i][j];\n                        b[i][j] = c;\n                        changed[c] = 1;\n                    }\n                }\n            }\n            if (!anyHole) break;\n            for (int c=1;c<=m;c++) if (changed[c]) connectColor(b, c);\n        }\n\n        if (!checkAll(b)) continue;\n\n        int zeroCnt = 0;\n        for (int i=0;i<n;i++) for (int j=0;j<n;j++) if (b[i][j]==0) zeroCnt++;\n\n        if (!found || zeroCnt > bestZero) {\n            found = true;\n            bestZero = zeroCnt;\n            best = std::move(b);\n        }\n    }\n\n    if (!found) best = a; // always legal fallback\n\n    for (int i=0;i<n;i++){\n        for (int j=0;j<n;j++){\n            if (j) cout << ' ';\n            cout << best[i][j];\n        }\n        cout << '\\n';\n    }\n    return 0;\n}","ahc025":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int8_t UNK = 2;\n\nstruct Judge {\n    int N, D, Q;\n    int used = 0;\n    vector<vector<int8_t>> cmpMemo; // cmpMemo[i][j] in {-1,0,1,UNK}\n\n    Judge(int n, int d, int q) : N(n), D(d), Q(q) {\n        cmpMemo.assign(N, vector<int8_t>(N, UNK));\n    }\n\n    // Sends one query comparing sums of disjoint non-empty sets L and R.\n    // Returns sign: -1 if sum(L) < sum(R), 0 if =, +1 if sum(L) > sum(R).\n    int doQuery(const vector<int>& L, const vector<int>& R) {\n        if (used >= Q) return 0; // should not happen in well-designed flow\n        // L and R must be non-empty and disjoint by construction.\n        used++;\n        cout << (int)L.size() << ' ' << (int)R.size();\n        for (int x : L) cout << ' ' << x;\n        for (int x : R) cout << ' ' << x;\n        cout << '\\n' << flush;\n\n        string s;\n        cin >> s;\n        char c = s[0];\n        if (c == '<') return -1;\n        if (c == '>') return 1;\n        return 0;\n    }\n\n    int cmpSingleton(int i, int j) {\n        if (i == j) return 0;\n        int8_t &m = cmpMemo[i][j];\n        if (m != UNK) return m;\n        if (used >= Q) return 0;\n        vector<int> L{ i }, R{ j };\n        int s = doQuery(L, R);\n        cmpMemo[i][j] = (int8_t)s;\n        cmpMemo[j][i] = (int8_t)(-s);\n        return s;\n    }\n\n    int cmpSets(const vector<int>& A, const vector<int>& B) {\n        // assumes A,B non-empty, disjoint\n        if (A.empty() || B.empty()) return 0;\n        return doQuery(A, B);\n    }\n\n    int queriesUsed() const { return used; }\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    Judge judge(N, D, Q);\n\n    vector<vector<int>> bins(D);\n    vector<int> d_i(N, 0);\n\n    // ---------- Phase 1: Pivot bucketization ----------\n    // Choose pivot count Kp based on query budget estimate.\n    auto ceil_log2 = [&](int x) -> int {\n        // returns minimal b such that 2^b >= x, for x>=1; b>=0\n        int b = 0;\n        int v = 1;\n        while (v < x) { v <<= 1; b++; }\n        return b;\n    };\n\n    long long budget = (long long)(0.40L * (long long)Q);\n    int maxKp = min(20, N);\n    int bestKp = 1;\n\n    for (int Kp = 1; Kp <= maxKp; Kp++) {\n        // pivot sorting worst-case with insertion: Kp*(Kp-1)/2 comparisons\n        long long sortCost = 1LL * Kp * (Kp - 1) / 2;\n        // binary search comparisons per item for upper_bound: <= ceil_log2(Kp+1)\n        int perItem = ceil_log2(Kp + 1);\n        long long itemCost = 1LL * (N - Kp) * perItem;\n        long long cost = sortCost + itemCost;\n        if (cost <= budget) bestKp = Kp;\n        else break;\n    }\n    int Kp = bestKp;\n\n    // Pick pivots (deterministic RNG)\n    uint64_t seed = 712367821ULL + (uint64_t)N * 1000003ULL + (uint64_t)D * 9176ULL + (uint64_t)Q;\n    std::mt19937_64 rng(seed);\n\n    vector<int> idx(N);\n    iota(idx.begin(), idx.end(), 0);\n    shuffle(idx.begin(), idx.end(), rng);\n    vector<int> pivots(idx.begin(), idx.begin() + Kp);\n\n    // Sort pivots ascending by weight using singleton comparisons\n    // Insertion sort (simple + bounded for small Kp)\n    for (int i = 1; i < Kp; i++) {\n        int j = i;\n        while (j > 0) {\n            if (judge.queriesUsed() >= Q) break;\n            // pivots[j] < pivots[j-1] ?\n            int s = judge.cmpSingleton(pivots[j], pivots[j - 1]);\n            if (s == -1) {\n                swap(pivots[j], pivots[j - 1]);\n                j--;\n            } else break;\n        }\n        if (judge.queriesUsed() >= Q) break;\n    }\n\n    vector<int> pivotPos(N, -1);\n    for (int i = 0; i < Kp; i++) pivotPos[pivots[i]] = i;\n\n    // Exponential distribution quantile mapping.\n    // weights are generated from Exponential(lambda=1e-5), rounded and truncated above cap.\n    const double lambda = 1e-5;\n    double cap = 1e5 * (double)N / (double)D;\n\n    auto estimateFromBucket = [&](int bucket) -> double {\n        // bucket in [0..Kp], mapping to p=(bucket+0.5)/(Kp+1)\n        double p = (bucket + 0.5) / (double)(Kp + 1);\n        // quantile: F^{-1}(p) = -ln(1-p)/lambda\n        double x = -log(1.0 - p) / lambda;\n        if (x < 1.0) x = 1.0;\n        if (x > cap) x = cap;\n        return x;\n    };\n\n    vector<int> bucket(N, Kp / 2);\n    vector<double> w_est(N, 1.0);\n\n    // For pivots themselves, bucket = position\n    for (int p : pivots) {\n        bucket[p] = pivotPos[p];\n        w_est[p] = estimateFromBucket(bucket[p]);\n    }\n\n    // For others, determine bucket by upper_bound among pivots: count pivots strictly < item\n    for (int i = 0; i < N; i++) {\n        if (judge.queriesUsed() >= Q) break;\n        if (pivotPos[i] != -1) continue;\n\n        int lo = 0, hi = Kp; // first pivot >= i\n        while (lo < hi) {\n            if (judge.queriesUsed() >= Q) break;\n            int mid = (lo + hi) / 2;\n            // if w_i > pivot[mid], pivot[mid] < w_i => move right\n            int s = judge.cmpSingleton(i, pivots[mid]);\n            if (s == 1) lo = mid + 1;\n            else hi = mid;\n        }\n        // lo = number of pivots strictly less than i\n        bucket[i] = lo;\n        w_est[i] = estimateFromBucket(bucket[i]);\n    }\n\n    // ---------- Phase 2: Initial partition (LPT-style) ----------\n    vector<int> order(N);\n    iota(order.begin(), order.end(), 0);\n    sort(order.begin(), order.end(), [&](int a, int b) {\n        return w_est[a] > w_est[b];\n    });\n\n    vector<double> binSumEst(D, 0.0);\n    for (int b = 0; b < D; b++) bins[b].clear();\n\n    for (int x : order) {\n        int best = 0;\n        for (int b = 1; b < D; b++) {\n            if (binSumEst[b] < binSumEst[best]) best = b;\n        }\n        bins[best].push_back(x);\n        d_i[x] = best;\n        binSumEst[best] += w_est[x];\n    }\n\n    auto moveItem = [&](int item, int from, int to) {\n        auto &v = bins[from];\n        for (int i = 0; i < (int)v.size(); i++) {\n            if (v[i] == item) {\n                v.erase(v.begin() + i);\n                break;\n            }\n        }\n        bins[to].push_back(item);\n        d_i[item] = to;\n    };\n\n    // ---------- Phase 3: Local balancing with remaining queries ----------\n    int iters = 0;\n    int maxIters = 120; // keep modest\n\n    while (judge.queriesUsed() < Q && iters < maxIters) {\n        // find movable heavy bin (size >= 2)\n        int h = -1;\n        for (int b = 0; b < D; b++) {\n            if ((int)bins[b].size() >= 2) { h = b; break; }\n        }\n        if (h == -1) break;\n\n        // light bin: any non-empty bin\n        int l = -1;\n        for (int b = 0; b < D; b++) {\n            if (!bins[b].empty()) { l = b; break; }\n        }\n        if (l == -1) break;\n\n        // Make h the heaviest among bins with size>=2\n        for (int b = 0; b < D && judge.queriesUsed() < Q; b++) {\n            if (b == h) continue;\n            if ((int)bins[b].size() < 2) continue;\n            int s = judge.cmpSets(bins[h], bins[b]); // h ? b\n            if (s == -1) h = b; // h < b => b heavier\n        }\n        if (judge.queriesUsed() >= Q) break;\n\n        // Make l the lightest among all non-empty bins\n        for (int b = 0; b < D && judge.queriesUsed() < Q; b++) {\n            if (b == l) continue;\n            int s = judge.cmpSets(bins[l], bins[b]); // l ? b\n            if (s == 1) l = b; // l heavier => b lighter\n        }\n        if (judge.queriesUsed() >= Q) break;\n\n        // If h is not heavier than l, stop\n        int sHL = judge.cmpSets(bins[h], bins[l]);\n        if (sHL <= 0) break; // h <= l\n\n        // Candidate move from heavy h to light l\n        vector<int> cand = bins[h];\n        sort(cand.begin(), cand.end(), [&](int a, int b) {\n            return w_est[a] > w_est[b];\n        });\n\n        int bestX = cand.empty() ? -1 : cand[0];\n        bool moved = false;\n\n        for (int x : cand) {\n            if (judge.queriesUsed() >= Q) break;\n\n            // left = h without x (must be non-empty)\n            vector<int> left;\n            left.reserve(bins[h].size() - 1);\n            for (int y : bins[h]) if (y != x) left.push_back(y);\n            if (left.empty()) continue;\n\n            // right = l with x\n            vector<int> right = bins[l];\n            right.push_back(x);\n\n            int s = judge.cmpSets(left, right); // (h-x) ? (l+x)\n            if (s <= 0) { // (h-x) <= (l+x): accept\n                moveItem(x, h, l);\n                moved = true;\n                break;\n            }\n        }\n\n        if (!moved) {\n            // No crossing found (or budget exhausted): move the largest estimated item\n            if (bestX != -1 && (int)bins[h].size() >= 2) {\n                moveItem(bestX, h, l);\n            }\n        }\n\n        iters++;\n    }\n\n    // ---------- Dummy queries to reach exactly Q ----------\n    while (judge.queriesUsed() < Q) {\n        // compare singleton 0 vs 1 (disjoint, non-empty). N>=30 always, so ok.\n        if (N >= 2) {\n            vector<int> L{0}, R{1};\n            judge.doQuery(L, R);\n        } else {\n            // Should never happen for constraints\n            vector<int> L{0}, R{0}; // invalid but unreachable\n            judge.doQuery(L, R);\n        }\n    }\n\n    // ---------- Output final division ----------\n    for (int i = 0; i < N; i++) {\n        if (i) cout << ' ';\n        cout << d_i[i];\n    }\n    cout << '\\n' << flush;\n\n    return 0;\n}","ahc026":"#include <bits/stdc++.h>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int n, m;\n    cin >> n >> m;\n    vector<vector<int>> st(m);\n    for (int i = 0; i < m; i++) {\n        st[i].resize(n / m);\n        for (int j = 0; j < n / m; j++) cin >> st[i][j];\n    }\n\n    vector<int> posStack(n + 1, -1), posIndex(n + 1, -1);\n    for (int i = 0; i < m; i++) {\n        for (int j = 0; j < (int)st[i].size(); j++) {\n            int x = st[i][j];\n            posStack[x] = i;\n            posIndex[x] = j;\n        }\n    }\n\n    vector<pair<int,int>> ops; // (v, i) where i=0 for op2\n    ops.reserve(5000);\n\n    const int INF = 1e9;\n\n    for (int v = 1; v <= n; v++) {\n        int s = posStack[v];\n        int idx = posIndex[v];\n\n        // v is already on top\n        if (idx == (int)st[s].size() - 1) {\n            ops.emplace_back(v, 0);\n            st[s].pop_back();\n            posStack[v] = -1;\n            posIndex[v] = -1;\n            continue;\n        }\n\n        // Need to move the chunk starting from the box immediately above v\n        int u = st[s][idx + 1];\n        vector<int> S(st[s].begin() + (idx + 1), st[s].end()); // moved boxes\n\n        int bestDest = -1;\n        // lexicographic key we construct as tuple<int,int,int>\n        // For inv==0: key = (0, minD, sizeD)  (minD smaller better)\n        // Else:        key = (inv, -minD, sizeD) (minD larger better via -minD)\n        tuple<int,int,int> bestKey;\n\n        for (int d = 0; d < m; d++) if (d != s) {\n            // inversion count between D and S: count pairs (x in D, y in S) with x < y\n            int inv = 0;\n            const auto &D = st[d];\n            for (int x : D) {\n                for (int y : S) {\n                    if (x < y) inv++;\n                }\n            }\n\n            int minD = INF;\n            if (!D.empty()) {\n                minD = *min_element(D.begin(), D.end());\n            }\n\n            int sizeD = (int)D.size();\n\n            tuple<int,int,int> key;\n            if (inv == 0) {\n                // fully safe (or empty destination)\n                key = {0, minD, sizeD};\n            } else {\n                key = {inv, -minD, sizeD};\n            }\n\n            if (bestDest == -1 || key < bestKey) {\n                bestDest = d;\n                bestKey = key;\n            }\n        }\n\n        // Operation 1: move box u (= S[0] bottom) and all above to destination bestDest\n        ops.emplace_back(u, bestDest + 1);\n\n        int startDest = (int)st[bestDest].size();\n        // append S to destination and update positions\n        for (int j = 0; j < (int)S.size(); j++) {\n            int y = S[j];\n            st[bestDest].push_back(y);\n            posStack[y] = bestDest;\n            posIndex[y] = startDest + j;\n        }\n        // remove S from source (suffix after idx)\n        st[s].erase(st[s].begin() + (idx + 1), st[s].end());\n\n        // Now v must be on top of source, carry it out\n        ops.emplace_back(v, 0);\n        st[s].pop_back();\n        posStack[v] = -1;\n        posIndex[v] = -1;\n    }\n\n    // Safety check\n    if ((int)ops.size() > 5000) return 0;\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 SplitMix64 {\n    uint64_t x;\n    explicit SplitMix64(uint64_t seed = 0) : x(seed) {}\n    uint64_t next_u64() {\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 next_int(int l, int r) { // inclusive\n        return l + (int)(next_u64() % (uint64_t)(r - l + 1));\n    }\n    double next_double(double l, double r) {\n        // [l, r)\n        uint64_t v = next_u64();\n        long double t = (long double)(v) / (long double)numeric_limits<uint64_t>::max();\n        return (double)((long double)l + t * (long double)(r - l));\n    }\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 V = N * N;\n    vector<int> d(V);\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            int x;\n            cin >> x;\n            d[i * N + j] = x;\n        }\n    }\n\n    auto inside = [&](int i, int j) {\n        return 0 <= i && i < N && 0 <= j && j < N;\n    };\n    auto idx = [&](int i, int j) { return i * N + j; };\n\n    // Build adjacency graph (moves allowed by walls)\n    vector<vector<int>> g(V);\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            int a = idx(i, j);\n            // down\n            if (i + 1 < N && h[i][j] == '0') {\n                int b = idx(i + 1, j);\n                g[a].push_back(b);\n                g[b].push_back(a);\n            }\n            // right\n            if (j + 1 < N && v[i][j] == '0') {\n                int b = idx(i, j + 1);\n                g[a].push_back(b);\n                g[b].push_back(a);\n            }\n        }\n    }\n\n    // BFS distances from root (0,0)\n    const int root = 0;\n    vector<int> dist(V, -1);\n    queue<int> q;\n    dist[root] = 0;\n    q.push(root);\n    while (!q.empty()) {\n        int x = q.front(); q.pop();\n        for (int y : g[x]) {\n            if (dist[y] == -1) {\n                dist[y] = dist[x] + 1;\n                q.push(y);\n            }\n        }\n    }\n\n    // Parent candidates: neighbors with dist-1\n    vector<vector<int>> candParents(V);\n    for (int vv = 0; vv < V; vv++) {\n        if (vv == root) continue;\n        int dv = dist[vv];\n        for (int uu : g[vv]) {\n            if (dist[uu] == dv - 1) candParents[vv].push_back(uu);\n        }\n        // Guaranteed reachable => should be non-empty\n        // (problem statement guarantees reachability from root).\n    }\n\n    // Vertex order by dist descending (useful for subtree DP)\n    vector<int> verts(V);\n    iota(verts.begin(), verts.end(), 0);\n    sort(verts.begin(), verts.end(), [&](int a, int b) {\n        return dist[a] > dist[b];\n    });\n\n    auto getDir = [&](int from, int to) -> char {\n        int fi = from / N, fj = from % N;\n        int ti = to / N, tj = to % N;\n        if (ti == fi + 1 && tj == fj) return 'D';\n        if (ti == fi - 1 && tj == fj) return 'U';\n        if (ti == fi && tj == fj + 1) return 'R';\n        if (ti == fi && tj == fj - 1) return 'L';\n        // Should always be adjacent in the tree\n        return '?';\n    };\n\n    long long sum_d = 0;\n    for (int x : d) sum_d += x;\n\n    int Lfixed = 2 * (V - 1);\n    long long bestNumer = (1LL<<62);\n    string bestRoute;\n\n    SplitMix64 rng((uint64_t)chrono::steady_clock::now().time_since_epoch().count());\n\n    vector<int> parent(V), subMax(V), subSize(V);\n    vector<long long> subSum(V);\n    vector<vector<int>> children(V);\n\n    vector<int> last(V);\n    vector<int> pos_after; pos_after.reserve(Lfixed);\n\n    auto evaluate = [&](const vector<int>& pos) -> long long {\n        // pos size = Lfixed, pos[k] = vertex after (k+1)-th move in one cycle\n        long long numer = 0; // sum S_t for t in [L..2L-1]\n        fill(last.begin(), last.end(), 0);\n\n        long long sum_d_last = 0;\n        int L = Lfixed;\n        int T = 2 * L - 1;\n\n        for (int t = 1; t <= T; t++) {\n            int vv = pos[(t - 1) % L];\n            int old = last[vv];\n            last[vv] = t;\n            sum_d_last += (long long)d[vv] * (t - old);\n            long long S = (long long)t * sum_d - sum_d_last;\n            if (t >= L) numer += S;\n        }\n        return numer;\n    };\n\n    auto buildRouteAndPos = [&](const vector<vector<int>>& ordChildren,\n                                 const vector<int>& par) -> pair<string, vector<int>> {\n        string route;\n        route.reserve(Lfixed);\n        vector<int> pos;\n        pos.reserve(Lfixed);\n\n        vector<pair<int,int>> st;\n        st.reserve(V);\n        st.push_back({root, 0});\n\n        while (!st.empty()) {\n            int u = st.back().first;\n            int &i = st.back().second;\n            if (i == (int)ordChildren[u].size()) {\n                st.pop_back();\n                if (st.empty()) break;\n                int p = par[u];\n                route.push_back(getDir(u, p));\n                pos.push_back(p); // moved to parent\n            } else {\n                int c = ordChildren[u][i++];\n                route.push_back(getDir(u, c));\n                pos.push_back(c); // moved to child\n                st.push_back({c, 0});\n            }\n        }\n        // pos.size() should be Lfixed\n        return {route, pos};\n    };\n\n    // Deterministic initial candidate (greedy parents + one ordering)\n    {\n        double p_greedy = 1.0;\n        for (int i = 0; i < V; i++) children[i].clear();\n        parent[root] = -1;\n\n        // build parent in increasing dist order\n        vector<int> byDist(V);\n        iota(byDist.begin(), byDist.end(), 0);\n        sort(byDist.begin(), byDist.end(), [&](int a, int b) { return dist[a] < dist[b]; });\n\n        for (int vv : byDist) {\n            if (vv == root) continue;\n            auto &cp = candParents[vv];\n            int bestp = cp[0];\n            for (int u : cp) if (d[u] > d[bestp]) bestp = u;\n            int pick = bestp;\n            parent[vv] = pick;\n            children[pick].push_back(vv);\n        }\n\n        // subtree dp\n        for (int vtx : verts) {\n            subMax[vtx] = d[vtx];\n            subSum[vtx] = d[vtx];\n            subSize[vtx] = 1;\n            for (int c : children[vtx]) {\n                subMax[vtx] = max(subMax[vtx], subMax[c]);\n                subSum[vtx] += subSum[c];\n                subSize[vtx] += subSize[c];\n            }\n        }\n\n        // child ordering: ascending by subMax (often helps by delaying high-d subtrees)\n        vector<vector<int>> ordChildren = children;\n        for (int u = 0; u < V; u++) {\n            auto &ch = ordChildren[u];\n            if (ch.size() <= 1) continue;\n            sort(ch.begin(), ch.end(), [&](int a, int b) {\n                return subMax[a] < subMax[b];\n            });\n        }\n\n        auto [route, pos] = buildRouteAndPos(ordChildren, parent);\n        long long numer = evaluate(pos);\n        if (numer < bestNumer) {\n            bestNumer = numer;\n            bestRoute = route;\n        }\n    }\n\n    // Randomized candidates\n    auto startTime = chrono::steady_clock::now();\n    double TIME_LIMIT_SEC = 1.75; // keep margin\n\n    vector<int> byDist(V);\n    iota(byDist.begin(), byDist.end(), 0);\n    sort(byDist.begin(), byDist.end(), [&](int a, int b) { return dist[a] < dist[b]; });\n\n    int iter = 0;\n    while (true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - startTime).count();\n        if (elapsed > TIME_LIMIT_SEC) break;\n        iter++;\n        // parameters\n        double p_greedy = rng.next_double(0.7, 0.99);\n        int orderType = rng.next_int(0, 2); // 0: subMax, 1: subSum, 2: d(child)\n        bool ascending = rng.next_int(0, 1);\n        double noiseRate = rng.next_double(0.0, 0.25);\n\n        // build parent\n        for (int i = 0; i < V; i++) children[i].clear();\n        parent[root] = -1;\n\n        for (int vv : byDist) {\n            if (vv == root) continue;\n            auto &cp = candParents[vv];\n            int pick;\n            if (rng.next_double(0.0, 1.0) < p_greedy) {\n                // greedy by d[parent]\n                pick = cp[0];\n                for (int u : cp) if (d[u] > d[pick]) pick = u;\n            } else {\n                pick = cp[rng.next_int(0, (int)cp.size() - 1)];\n            }\n            parent[vv] = pick;\n            children[pick].push_back(vv);\n        }\n\n        // subtree dp\n        for (int vtx : verts) {\n            subMax[vtx] = d[vtx];\n            subSum[vtx] = d[vtx];\n            subSize[vtx] = 1;\n            for (int c : children[vtx]) {\n                subMax[vtx] = max(subMax[vtx], subMax[c]);\n                subSum[vtx] += subSum[c];\n                subSize[vtx] += subSize[c];\n            }\n        }\n\n        // order children with key + noise\n        vector<vector<int>> ordChildren(V);\n        for (int u = 0; u < V; u++) ordChildren[u] = children[u];\n\n        for (int u = 0; u < V; u++) {\n            auto &ch = ordChildren[u];\n            if (ch.size() <= 1) continue;\n\n            vector<pair<double,int>> tmp;\n            tmp.reserve(ch.size());\n            for (int c : ch) {\n                double key;\n                if (orderType == 0) key = (double)subMax[c];\n                else if (orderType == 1) key = (double)subSum[c];\n                else key = (double)d[c];\n\n                double sign = rng.next_double(-1.0, 1.0);\n                double adj = key + noiseRate * key * sign;\n                tmp.push_back({adj, c});\n            }\n            sort(tmp.begin(), tmp.end(), [&](auto &A, auto &B) {\n                if (A.first != B.first) return ascending ? (A.first < B.first) : (A.first > B.first);\n                return A.second < B.second;\n            });\n            for (int i = 0; i < (int)ch.size(); i++) ch[i] = tmp[i].second;\n        }\n\n        auto [route, pos] = buildRouteAndPos(ordChildren, parent);\n        // length should be fixed\n        // (we don't assert to avoid overhead, but it's always true)\n        long long numer = evaluate(pos);\n        if (numer < bestNumer) {\n            bestNumer = numer;\n            bestRoute = std::move(route);\n        }\n    }\n\n    cout << bestRoute << \"\\n\";\n    return 0;\n}","ahc028":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M;\n    cin >> N >> M;\n\n    int si, sj;\n    cin >> si >> sj;\n\n    vector<string> grid(N);\n    for (int i = 0; i < N; i++) cin >> grid[i];\n\n    vector<string> t(M);\n    for (int k = 0; k < M; k++) cin >> t[k];\n\n    auto idxOf = [N](int r, int c) { return r * N + c; };\n    auto coordOf = [N](int id) { return pair<int,int>{id / N, id % N}; };\n\n    int C = N * N;\n    int startCell = idxOf(si, sj);\n\n    vector<vector<int>> posByLetter(26);\n    for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) {\n        int a = grid[i][j] - 'A';\n        posByLetter[a].push_back(idxOf(i, j));\n    }\n\n    // dist between any two cells\n    vector<vector<int>> distCell(C, vector<int>(C, 0));\n    for (int a = 0; a < C; a++) {\n        auto [ar, ac] = coordOf(a);\n        for (int b = a; b < C; b++) {\n            auto [br, bc] = coordOf(b);\n            int d = abs(ar - br) + abs(ac - bc);\n            distCell[a][b] = distCell[b][a] = d;\n        }\n    }\n\n    // min dist from a cell to ANY cell containing given letter\n    vector<vector<int>> distCellToLetter(C, vector<int>(26, INT_MAX/4));\n    for (int p = 0; p < C; p++) {\n        for (int l = 0; l < 26; l++) {\n            int best = INT_MAX/4;\n            for (int q : posByLetter[l]) best = min(best, distCell[p][q]);\n            distCellToLetter[p][l] = best;\n        }\n    }\n\n    // min distance between any cell containing letter x and any cell containing y\n    vector<vector<int>> distLetter(26, vector<int>(26, INT_MAX/4));\n    for (int x = 0; x < 26; x++) for (int y = 0; y < 26; y++) {\n        int best = INT_MAX/4;\n        for (int p : posByLetter[x]) {\n            for (int q : posByLetter[y]) best = min(best, distCell[p][q]);\n        }\n        distLetter[x][y] = best;\n    }\n\n    vector<int> st(M), en(M);\n    for (int i = 0; i < M; i++) {\n        st[i] = t[i][0] - 'A';\n        en[i] = t[i][4] - 'A';\n    }\n\n    // overlapLen[i][j]: maximum r (0..4) such that suffix(t[i], r) == prefix(t[j], r)\n    vector<vector<uint8_t>> overlapLen(M, vector<uint8_t>(M, 0));\n    for (int i = 0; i < M; i++) for (int j = 0; j < M; j++) if (i != j) {\n        uint8_t best = 0;\n        for (int r = 4; r >= 0; r--) {\n            bool ok = true;\n            for (int k = 0; k < r; k++) {\n                if (t[i][5 - r + k] != t[j][k]) { ok = false; break; }\n            }\n            if (ok) { best = (uint8_t)r; break; }\n        }\n        overlapLen[i][j] = best;\n    }\n\n    vector<uint8_t> maxOverlapFrom(M, 0);\n    for (int i = 0; i < M; i++) {\n        uint8_t mx = 0;\n        for (int j = 0; j < M; j++) if (i != j) mx = max(mx, overlapLen[i][j]);\n        maxOverlapFrom[i] = mx;\n    }\n\n    // Build merged letter sequence from an order using overlaps.\n    auto buildSeq = [&](const vector<int>& order) -> vector<char> {\n        vector<char> seq;\n        seq.reserve(5 * M);\n        auto addStringFrom = [&](int idx, int fromPos) {\n            for (int p = fromPos; p < 5; p++) seq.push_back(t[idx][p]);\n        };\n        addStringFrom(order[0], 0);\n        for (int i = 1; i < M; i++) {\n            int prev = order[i-1], cur = order[i];\n            int r = overlapLen[prev][cur];\n            addStringFrom(cur, r);\n        }\n        return seq;\n    };\n\n    // Beam search simulation: minimize cost for the fixed letter sequence.\n    auto simulateBeam = [&](const vector<int>& order) -> pair<ll, vector<pair<int,int>>> {\n        vector<char> seq = buildSeq(order);\n        int L = (int)seq.size();\n\n        // beam width (small enough for speed, large enough to improve)\n        const int BEAM = 28;\n\n        vector<vector<int>> cellsAt(L);\n        vector<vector<int>> parentAt(L);\n        vector<vector<ll>> costAt(L);\n\n        // position 0\n        int l0 = seq[0] - 'A';\n        const vector<int>& cand0 = posByLetter[l0];\n\n        vector<tuple<ll,int,int>> vec; // cost, cell, parentIdx(-1)\n        vec.reserve(cand0.size());\n        for (int c : cand0) {\n            ll cost = (ll)distCell[startCell][c] + 1;\n            vec.emplace_back(cost, c, -1);\n        }\n        nth_element(vec.begin(), vec.begin() + min((int)vec.size(), BEAM) - 1, vec.end(),\n                    [](auto &a, auto &b){ return get<0>(a) < get<0>(b); });\n        int take0 = min((int)vec.size(), BEAM);\n        vec.resize(take0);\n        sort(vec.begin(), vec.end(), [](auto &a, auto &b){ return get<0>(a) < get<0>(b); });\n\n        cellsAt[0].resize(take0);\n        parentAt[0].assign(take0, -1);\n        costAt[0].resize(take0);\n        for (int i = 0; i < take0; i++) {\n            cellsAt[0][i] = get<1>(vec[i]);\n            costAt[0][i] = get<0>(vec[i]);\n        }\n\n        // forward DP\n        for (int pos = 1; pos < L; pos++) {\n            int l = seq[pos] - 'A';\n            const vector<int>& cand = posByLetter[l];\n\n            const auto &prevCells = cellsAt[pos-1];\n            const auto &prevCosts = costAt[pos-1];\n            int prevSz = (int)prevCells.size();\n\n            // compute best transition into each candidate cell\n            vector<tuple<ll,int,int>> bestForCand; // cost, cell, parentIdx\n            bestForCand.reserve(cand.size());\n\n            for (int c : cand) {\n                ll best = (1LL<<62);\n                int bestParent = -1;\n                // min over beam states\n                for (int pi = 0; pi < prevSz; pi++) {\n                    ll v = prevCosts[pi] + (ll)distCell[prevCells[pi]][c] + 1;\n                    if (v < best) {\n                        best = v;\n                        bestParent = pi;\n                    }\n                }\n                bestForCand.emplace_back(best, c, bestParent);\n            }\n\n            int take = min((int)bestForCand.size(), BEAM);\n            // select top-k by cost\n            nth_element(bestForCand.begin(), bestForCand.begin() + take - 1, bestForCand.end(),\n                        [](auto &a, auto &b){ return get<0>(a) < get<0>(b); });\n            bestForCand.resize(take);\n            sort(bestForCand.begin(), bestForCand.end(), [](auto &a, auto &b){ return get<0>(a) < get<0>(b); });\n\n            cellsAt[pos].resize(take);\n            parentAt[pos].resize(take);\n            costAt[pos].resize(take);\n            for (int i = 0; i < take; i++) {\n                cellsAt[pos][i] = get<1>(bestForCand[i]);\n                parentAt[pos][i] = get<2>(bestForCand[i]);\n                costAt[pos][i] = get<0>(bestForCand[i]);\n            }\n        }\n\n        // choose best end\n        int idx = (int)(min_element(costAt[L-1].begin(), costAt[L-1].end()) - costAt[L-1].begin());\n        ll bestCost = costAt[L-1][idx];\n\n        // reconstruct chosen cells\n        vector<int> chosenCells(L);\n        int curIdx = idx;\n        for (int pos = L-1; pos >= 0; pos--) {\n            chosenCells[pos] = cellsAt[pos][curIdx];\n            curIdx = parentAt[pos][curIdx];\n            if (pos == 0) break;\n        }\n\n        vector<pair<int,int>> ops;\n        ops.reserve(L);\n        for (int pos = 0; pos < L; pos++) ops.push_back(coordOf(chosenCells[pos]));\n        return {bestCost, ops};\n    };\n\n    // Candidate starting strings: use a slightly deeper proxy (first+second letter)\n    vector<pair<int,int>> startCand; // (proxy, idx)\n    startCand.reserve(M);\n    for (int i = 0; i < M; i++) {\n        int lStart = st[i];\n        int lSecond = t[i][1] - 'A';\n\n        ll proxy = (1LL<<62);\n        for (int c : posByLetter[lStart]) {\n            // move to c for first char, then minimal move to any cell of second char\n            ll v = distCell[startCell][c] + (ll)distCellToLetter[c][lSecond] + 1;\n            proxy = min(proxy, v);\n        }\n        startCand.push_back({(int)min<ll>(proxy, INT_MAX), i});\n    }\n    sort(startCand.begin(), startCand.end());\n\n    // More restarts but still bounded by time\n    int RESTARTS = 10;\n\n    // Random tie-breaking helper\n    std::mt19937 rng(712367);\n\n    ll bestCost = (1LL<<62);\n    vector<pair<int,int>> bestOps;\n\n    for (int rep = 0; rep < RESTARTS; rep++) {\n        int startIdx = startCand[rep].second;\n\n        vector<int> order;\n        order.reserve(M);\n\n        vector<char> used(M, 0);\n        order.push_back(startIdx);\n        used[startIdx] = 1;\n\n        int cur = startIdx;\n\n        for (int step = 1; step < M; step++) {\n            int bestR = -1;\n            int bestMx = -1;\n            int bestD = INT_MAX;\n\n            // First gather best by lexicographic-like criteria:\n            // 1) overlapLen[cur][j] (higher better)\n            // 2) dist between letters en[cur] -> st[j] (lower better)\n            // 3) maxOverlapFrom[j] (higher better)\n            vector<int> cand;\n            for (int j = 0; j < M; j++) if (!used[j]) {\n                int r = overlapLen[cur][j];\n                int d = distLetter[en[cur]][st[j]];\n                int mx = (int)maxOverlapFrom[j];\n                if (r > bestR ||\n                    (r == bestR && d < bestD) ||\n                    (r == bestR && d == bestD && mx > bestMx)) {\n                    bestR = r; bestD = d; bestMx = mx;\n                    cand.clear();\n                    cand.push_back(j);\n                } else if (r == bestR && d == bestD && mx == bestMx) {\n                    cand.push_back(j);\n                }\n            }\n\n            // Randomly pick among equally good candidates to diversify\n            int pick = cand.empty() ? -1 : cand[rng() % cand.size()];\n            used[pick] = 1;\n            order.push_back(pick);\n            cur = pick;\n        }\n\n        auto [cost, ops] = simulateBeam(order);\n        if ((int)ops.size() > 5000) continue; // safety\n        if (cost < bestCost) {\n            bestCost = cost;\n            bestOps = std::move(ops);\n        }\n    }\n\n    for (auto [i, j] : bestOps) cout << i << ' ' << j << '\\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    if (!(cin >> N >> M >> eps)) return 0;\n\n    // Read shapes (not needed for the safe strategy).\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>> ans;\n    ans.reserve(N * N);\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            cout << \"q 1 \" << i << \" \" << j << \"\\n\";\n            cout.flush();\n\n            long long v;\n            if (!(cin >> v)) return 0;\n            if (v > 0) ans.emplace_back(i, j);\n        }\n    }\n\n    cout << \"a \" << ans.size();\n    for (auto [i, j] : ans) cout << \" \" << i << \" \" << j;\n    cout << \"\\n\";\n    cout.flush();\n\n    int ok;\n    if (!(cin >> ok)) return 0;\n    // ok==1 means success, ok==0 means wrong (should not happen with this strategy).\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    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    // cost[k][w] = 100 * sum_d max(0, a[d][k] - w*W)\n    // where w is width in columns (height is always W), w in [1..W]\n    vector<vector<long long>> cost(N, vector<long long>(W + 1, 0));\n    for (int k = 0; k < N; k++) {\n        for (int w = 1; w <= W; w++) {\n            long long b = 1LL * w * W;\n            long long diffSum = 0;\n            for (int d = 0; d < D; d++) {\n                if (a[d][k] > b) diffSum += (a[d][k] - b);\n            }\n            cost[k][w] = 100LL * diffSum;\n        }\n    }\n\n    const long long INF = (1LL<<62);\n\n    // dp[i][cap] = min cost using first i items (0..i-1), total width cap.\n    // parent pointers to reconstruct widths.\n    vector<vector<long long>> dp(N + 1, vector<long long>(W + 1, INF));\n    vector<vector<int>> parentCap(N + 1, vector<int>(W + 1, -1));\n    vector<vector<int>> parentW(N + 1, vector<int>(W + 1, -1));\n\n    dp[0][0] = 0;\n\n    auto maxCapAfter = [&](int i) -> int {\n        // after placing i items, remaining N-i items need at least 1 width each\n        // => cap <= W - (N-i)\n        return W - (N - i);\n    };\n\n    for (int i = 1; i <= N; i++) {\n        int capLo = i; // since each of i widths >=1\n        int capHi = maxCapAfter(i);\n        if (capHi < capLo) continue;\n\n        for (int cap = capLo; cap <= capHi; cap++) {\n            // choose width w for item (i-1)\n            // previous capPrev = cap - w must be >= i-1\n            // and w >= 1\n            int wLo = 1;\n            int wHi = cap - (i - 1);\n            for (int w = wLo; w <= wHi; w++) {\n                int capPrev = cap - w;\n                if (capPrev < 0) continue;\n                if (dp[i-1][capPrev] == INF) continue;\n                long long cand = dp[i-1][capPrev] + cost[i-1][w];\n                if (cand < dp[i][cap]) {\n                    dp[i][cap] = cand;\n                    parentCap[i][cap] = capPrev;\n                    parentW[i][cap] = w;\n                }\n            }\n        }\n    }\n\n    // choose best cap for i=N\n    long long best = INF;\n    int bestCap = -1;\n    for (int cap = N; cap <= W; cap++) {\n        if (dp[N][cap] < best) {\n            best = dp[N][cap];\n            bestCap = cap;\n        }\n    }\n\n    // Reconstruct widths w_k\n    vector<int> wAns(N, 1);\n    int cap = bestCap;\n    for (int i = N; i >= 1; i--) {\n        int w = parentW[i][cap];\n        int capPrev = parentCap[i][cap];\n        if (w == -1 || capPrev == -1) {\n            // Should not happen; but keep safe fallback.\n            w = 1;\n            capPrev = cap - 1;\n        }\n        wAns[i-1] = w;\n        cap = capPrev;\n    }\n\n    // Build fixed rectangles (same for every day)\n    vector<int> x0(N), x1(N);\n    int curX = 0;\n    for (int k = 0; k < N; k++) {\n        x0[k] = curX;\n        x1[k] = curX + wAns[k];\n        curX = x1[k];\n    }\n    // Ensure within bounds\n    curX = min(curX, W);\n\n    // Output: for all days, same rectangles\n    for (int d = 0; d < D; d++) {\n        for (int k = 0; k < N; k++) {\n            cout << x0[k] << ' ' << 0 << ' ' << x1[k] << ' ' << W << \"\\n\";\n        }\n    }\n    return 0;\n}","ahc032":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int MOD = 998244353;\n\nstruct Op {\n    array<uint8_t, 9> idx;   // affected cell ids\n    array<int, 9> add;       // values to add on those cells (mod MOD)\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, K;\n    cin >> N >> M >> K; // constraints say N=9, M=20, K=81\n    vector<vector<int>> a(N, vector<int>(N));\n    for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) cin >> a[i][j];\n\n    vector<vector<vector<int>>> s(M, vector<vector<int>>(3, vector<int>(3)));\n    for (int m = 0; m < M; m++)\n        for (int i = 0; i < 3; i++)\n            for (int j = 0; j < 3; j++)\n                cin >> s[m][i][j];\n\n    const int NN = N * N; // 81\n    // Build all possible operations (m, p, q)\n    struct OutOp { uint8_t m, p, q; };\n    vector<Op> ops;\n    vector<OutOp> outMeta;\n    ops.reserve(M * (N - 2) * (N - 2));\n    outMeta.reserve(M * (N - 2) * (N - 2));\n\n    for (int m = 0; m < M; m++) {\n        for (int p = 0; p <= N - 3; p++) {\n            for (int q = 0; q <= N - 3; q++) {\n                Op op;\n                int t = 0;\n                for (int di = 0; di < 3; di++) {\n                    for (int dj = 0; dj < 3; dj++) {\n                        int ii = p + di;\n                        int jj = q + dj;\n                        op.idx[t] = (uint8_t)(ii * N + jj);\n                        op.add[t] = s[m][di][dj] % MOD;\n                        t++;\n                    }\n                }\n                ops.push_back(op);\n                outMeta.push_back(OutOp{(uint8_t)m, (uint8_t)p, (uint8_t)q});\n            }\n        }\n    }\n    const int numOps = (int)ops.size(); // 980\n\n    // Initial residues\n    array<int, 81> initX{};\n    for (int i = 0; i < N; i++)\n        for (int j = 0; j < N; j++)\n            initX[i * N + j] = a[i][j] % MOD;\n\n    // Precompute opAddCell[opId][cell] = op's add on that cell else 0\n    // 980*81 ~ 79k ints => fine.\n    vector<array<int, 81>> opAddCell(numOps);\n    for (int opId = 0; opId < numOps; opId++) {\n        opAddCell[opId].fill(0);\n        for (int t = 0; t < 9; t++) {\n            int cell = ops[opId].idx[t];\n            opAddCell[opId][cell] = ops[opId].add[t];\n        }\n    }\n\n    auto sumScore = [&](const array<int,81>& x) -> long long {\n        long long sc = 0;\n        for (int i = 0; i < NN; i++) sc += x[i];\n        return sc;\n    };\n\n    // Compute insertion delta if we ADD opId to current x:\n    auto deltaInsert = [&](int opId, const array<int,81>& x) -> long long {\n        long long d = 0;\n        const auto &op = ops[opId];\n        for (int t = 0; t < 9; t++) {\n            int cell = op.idx[t];\n            int oldv = x[cell];\n            int newv = oldv + op.add[t];\n            if (newv >= MOD) newv -= MOD;\n            d += (long long)(newv - oldv);\n        }\n        return d;\n    };\n\n    // Compute deletion delta if we REMOVE opId from current x (op was already applied):\n    auto deltaRemove = [&](int opId, const array<int,81>& x) -> long long {\n        long long d = 0;\n        const auto &op = ops[opId];\n        for (int t = 0; t < 9; t++) {\n            int cell = op.idx[t];\n            int oldv = x[cell];\n            int val = op.add[t];\n            int newv = oldv - val;\n            if (newv < 0) newv += MOD;\n            d += (long long)(newv - oldv);\n        }\n        return d;\n    };\n\n    // Compute replacement delta: remove oldOp and add newOp\n    auto deltaReplace = [&](int oldOpId, int newOpId, const array<int,81>& x) -> long long {\n        // union size <= 18\n        bool mark[81] = {};\n        long long d = 0;\n\n        // Process old cells\n        const auto &oldOp = ops[oldOpId];\n        for (int t = 0; t < 9; t++) {\n            int cell = oldOp.idx[t];\n            mark[cell] = true;\n            int oldAdd = opAddCell[oldOpId][cell]; // equals oldOp.add for this cell\n            int newAdd = opAddCell[newOpId][cell]; // 0 if newOp doesn't touch\n            int oldv = x[cell];\n\n            int tmp = oldv + newAdd - oldAdd;\n            // tmp in [-MOD+1, 2MOD-2]\n            if (tmp >= MOD) tmp -= MOD;\n            if (tmp < 0) tmp += MOD;\n\n            d += (long long)(tmp - oldv);\n        }\n\n        // Process cells only in newOp\n        const auto &newOp = ops[newOpId];\n        for (int t = 0; t < 9; t++) {\n            int cell = newOp.idx[t];\n            if (mark[cell]) continue;\n            int oldAdd = 0;\n            int newAdd = opAddCell[newOpId][cell];\n            int oldv = x[cell];\n\n            int tmp = oldv + newAdd - oldAdd; // just add\n            if (tmp >= MOD) tmp -= MOD;\n            if (tmp < 0) tmp += MOD; // never negative here, but safe\n\n            d += (long long)(tmp - oldv);\n        }\n        return d;\n    };\n\n    // Apply operations to x in-place\n    auto applyAdd = [&](int opId, array<int,81>& x) {\n        const auto &op = ops[opId];\n        for (int t = 0; t < 9; t++) {\n            int cell = op.idx[t];\n            int nv = x[cell] + op.add[t];\n            if (nv >= MOD) nv -= MOD;\n            x[cell] = nv;\n        }\n    };\n    auto applyRemove = [&](int opId, array<int,81>& x) {\n        const auto &op = ops[opId];\n        for (int t = 0; t < 9; t++) {\n            int cell = op.idx[t];\n            int nv = x[cell] - op.add[t];\n            if (nv < 0) nv += MOD;\n            x[cell] = nv;\n        }\n    };\n\n    // Small greedy initialization (stochastic among top few by 1-step delta from initial state)\n    vector<long long> deltaInit(numOps, 0);\n    {\n        array<int,81> x = initX;\n        for (int opId = 0; opId < numOps; opId++) {\n            deltaInit[opId] = deltaInsert(opId, x);\n        }\n    }\n\n    // topOpsIdx for biased sampling\n    vector<int> idxs(numOps);\n    iota(idxs.begin(), idxs.end(), 0);\n    int topKeep = min(numOps, 220);\n    nth_element(idxs.begin(), idxs.begin() + topKeep, idxs.end(),\n                [&](int i, int j){ return deltaInit[i] > deltaInit[j]; });\n    idxs.resize(topKeep);\n    sort(idxs.begin(), idxs.end(), [&](int i, int j){ return deltaInit[i] > deltaInit[j]; });\n\n    auto greedyInit = [&](uint64_t seed) -> vector<int> {\n        std::mt19937_64 rng(seed);\n        array<int,81> x = initX;\n        vector<int> chosen;\n        chosen.reserve(K);\n\n        const int TOPS = 7;\n        for (int step = 0; step < K; step++) {\n            // find best TOPS by exact deltaInsert from current x\n            // O(numOps*9) per step is fine (980*9*81 ~ 7e5)\n            array<long long, TOPS> bestD;\n            array<int, TOPS> bestId;\n            int sz = 0;\n            for (int opId = 0; opId < numOps; opId++) {\n                long long d = deltaInsert(opId, x);\n                if (sz < TOPS) {\n                    bestD[sz] = d;\n                    bestId[sz] = opId;\n                    sz++;\n                    // maintain by insertion sort (small TOPS)\n                    for (int i = sz - 1; i > 0; i--) {\n                        if (bestD[i] > bestD[i-1]) {\n                            swap(bestD[i], bestD[i-1]);\n                            swap(bestId[i], bestId[i-1]);\n                        }\n                    }\n                } else {\n                    if (d > bestD[TOPS-1]) {\n                        bestD[TOPS-1] = d;\n                        bestId[TOPS-1] = opId;\n                        // bubble up to keep sorted desc\n                        for (int i = TOPS-1; i > 0; i--) {\n                            if (bestD[i] > bestD[i-1]) {\n                                swap(bestD[i], bestD[i-1]);\n                                swap(bestId[i], bestId[i-1]);\n                            }\n                        }\n                    }\n                }\n            }\n            int pick = (int)(rng() % TOPS);\n            int opId = bestId[pick];\n            chosen.push_back(opId);\n            applyAdd(opId, x);\n        }\n        return chosen;\n    };\n\n    // Anneal with incremental evaluation\n    auto anneal = [&](vector<int> opsInit, uint64_t seed, int timeBudgetMs) -> pair<long long, vector<int>> {\n        std::mt19937_64 rng(seed);\n\n        vector<int> opsVec = std::move(opsInit);\n\n        array<int,81> x = initX;\n        for (int opId : opsVec) applyAdd(opId, x);\n        long long curScore = sumScore(x);\n        long long bestScore = curScore;\n        vector<int> bestOps = opsVec;\n\n        // temperature schedule (linear)\n        const double T0 = 2.0e9;\n        const double T1 = 5.0e6;\n\n        auto start = chrono::steady_clock::now();\n\n        auto elapsedMs = [&]() -> int {\n            return (int)chrono::duration_cast<chrono::milliseconds>(chrono::steady_clock::now() - start).count();\n        };\n\n        // candidate sampling sizes\n        const int SAMPLE_INS = 70;\n        const int SAMPLE_REP = 55;\n\n        auto randOpBiased = [&](bool biasTop) -> int {\n            if (biasTop && !idxs.empty()) {\n                // 65% from top list\n                if ((rng() % 100) < 65) return idxs[rng() % idxs.size()];\n            }\n            return (int)(rng() % numOps);\n        };\n\n        // main loop\n        int iter = 0;\n        while (elapsedMs() < timeBudgetMs) {\n            iter++;\n            // update temperature\n            int em = elapsedMs();\n            double prog = min(1.0, (double)em / (double)timeBudgetMs);\n            double T = T0 + (T1 - T0) * prog;\n\n            int sz = (int)opsVec.size();\n            int r = (int)(rng() % 100);\n\n            // Move choice\n            if (sz == 0) {\n                // must insert\n                int newOp = randOpBiased(true);\n\n                // choose best among sampled using exact deltaInsert\n                long long bestD = LLONG_MIN;\n                int bestNew = newOp;\n                for (int t = 0; t < SAMPLE_INS; t++) {\n                    int cand = randOpBiased(true);\n                    long long d = deltaInsert(cand, x);\n                    if (d > bestD) { bestD = d; bestNew = cand; }\n                }\n                long long candScore = curScore + bestD;\n                bool accept = (candScore >= curScore);\n                if (!accept) {\n                    double diff = (double)(candScore - curScore);\n                    double prob = exp(diff / T);\n                    double u = (double)rng() / (double)rng.max();\n                    accept = (u < prob);\n                }\n                if (accept) {\n                    opsVec.push_back(bestNew);\n                    applyAdd(bestNew, x);\n                    curScore = candScore;\n                    if (curScore > bestScore) {\n                        bestScore = curScore;\n                        bestOps = opsVec;\n                    }\n                }\n                continue;\n            }\n\n            if (sz == K) {\n                // can do replace or delete\n                if (r < 55) {\n                    // replacement\n                    int pos = (int)(rng() % sz);\n                    int oldOp = opsVec[pos];\n\n                    // choose best newOp among samples by exact replacement delta\n                    long long bestD = LLONG_MIN;\n                    int bestNew = oldOp;\n                    for (int t = 0; t < SAMPLE_REP; t++) {\n                        int cand = randOpBiased(true);\n                        if (cand == oldOp) continue;\n                        long long d = deltaReplace(oldOp, cand, x);\n                        if (d > bestD) { bestD = d; bestNew = cand; }\n                    }\n                    if (bestNew == oldOp) continue;\n\n                    long long candScore = curScore + bestD;\n                    bool accept = (candScore >= curScore);\n                    if (!accept) {\n                        double diff = (double)(candScore - curScore);\n                        double prob = exp(diff / T);\n                        double u = (double)rng() / (double)rng.max();\n                        accept = (u < prob);\n                    }\n                    if (accept) {\n                        // apply: remove old then add new\n                        applyRemove(oldOp, x);\n                        applyAdd(bestNew, x);\n                        opsVec[pos] = bestNew;\n                        curScore = candScore;\n                        if (curScore > bestScore) {\n                            bestScore = curScore;\n                            bestOps = opsVec;\n                        }\n                    }\n                } else {\n                    // deletion\n                    int pos = (int)(rng() % sz);\n                    int delOp = opsVec[pos];\n\n                    long long d = deltaRemove(delOp, x);\n                    long long candScore = curScore + d;\n                    bool accept = (candScore >= curScore);\n                    if (!accept) {\n                        double diff = (double)(candScore - curScore);\n                        double prob = exp(diff / T);\n                        double u = (double)rng() / (double)rng.max();\n                        accept = (u < prob);\n                    }\n                    if (accept) {\n                        applyRemove(delOp, x);\n                        opsVec.erase(opsVec.begin() + pos);\n                        curScore = candScore;\n                        if (curScore > bestScore) {\n                            bestScore = curScore;\n                            bestOps = opsVec;\n                        }\n                    }\n                }\n                continue;\n            }\n\n            // sz in (1..K-1)\n            if (r < 45) {\n                // replacement\n                int pos = (int)(rng() % sz);\n                int oldOp = opsVec[pos];\n\n                long long bestD = LLONG_MIN;\n                int bestNew = oldOp;\n                for (int t = 0; t < SAMPLE_REP; t++) {\n                    int cand = randOpBiased(true);\n                    if (cand == oldOp) continue;\n                    long long d = deltaReplace(oldOp, cand, x);\n                    if (d > bestD) { bestD = d; bestNew = cand; }\n                }\n                if (bestNew == oldOp) continue;\n\n                long long candScore = curScore + bestD;\n                bool accept = (candScore >= curScore);\n                if (!accept) {\n                    double diff = (double)(candScore - curScore);\n                    double prob = exp(diff / T);\n                    double u = (double)rng() / (double)rng.max();\n                    accept = (u < prob);\n                }\n                if (accept) {\n                    applyRemove(oldOp, x);\n                    applyAdd(bestNew, x);\n                    opsVec[pos] = bestNew;\n                    curScore = candScore;\n                    if (curScore > bestScore) {\n                        bestScore = curScore;\n                        bestOps = opsVec;\n                    }\n                }\n            } else if (r < 80) {\n                // insertion\n                long long bestD = LLONG_MIN;\n                int bestNew = 0;\n                for (int t = 0; t < SAMPLE_INS; t++) {\n                    int cand = randOpBiased(true);\n                    long long d = deltaInsert(cand, x);\n                    if (d > bestD) { bestD = d; bestNew = cand; }\n                }\n\n                long long candScore = curScore + bestD;\n                bool accept = (candScore >= curScore);\n                if (!accept) {\n                    double diff = (double)(candScore - curScore);\n                    double prob = exp(diff / T);\n                    double u = (double)rng() / (double)rng.max();\n                    accept = (u < prob);\n                }\n                if (accept) {\n                    opsVec.push_back(bestNew);\n                    applyAdd(bestNew, x);\n                    curScore = candScore;\n                    if (curScore > bestScore) {\n                        bestScore = curScore;\n                        bestOps = opsVec;\n                    }\n                }\n            } else {\n                // deletion\n                int pos = (int)(rng() % sz);\n                int delOp = opsVec[pos];\n\n                long long d = deltaRemove(delOp, x);\n                long long candScore = curScore + d;\n                bool accept = (candScore >= curScore);\n                if (!accept) {\n                    double diff = (double)(candScore - curScore);\n                    double prob = exp(diff / T);\n                    double u = (double)rng() / (double)rng.max();\n                    accept = (u < prob);\n                }\n                if (accept) {\n                    applyRemove(delOp, x);\n                    opsVec.erase(opsVec.begin() + pos);\n                    curScore = candScore;\n                    if (curScore > bestScore) {\n                        bestScore = curScore;\n                        bestOps = opsVec;\n                    }\n                }\n            }\n        }\n\n        return {bestScore, bestOps};\n    };\n\n    // Multiple restarts with more iterations thanks to incremental evaluation\n    auto globalStart = chrono::steady_clock::now();\n    auto globalElapsedMs = [&]() -> int {\n        return (int)chrono::duration_cast<chrono::milliseconds>(chrono::steady_clock::now() - globalStart).count();\n    };\n\n    long long bestScore = -1;\n    vector<int> bestOps;\n\n    int restarts = 5;\n    for (int r = 0; r < restarts; r++) {\n        if (globalElapsedMs() > 1900) break;\n        uint64_t seed = 123456789ULL + 10007ULL * (r + 1);\n\n        auto initOps = greedyInit(seed);\n\n        int remain = 1900 - globalElapsedMs();\n        int budget = max(120, remain / (restarts - r));\n        auto [sc, opsBest] = anneal(std::move(initOps), seed ^ 0x9e3779b97f4a7c15ULL, budget);\n        if (sc > bestScore) {\n            bestScore = sc;\n            bestOps = std::move(opsBest);\n        }\n    }\n\n    // Output operations (L <= K)\n    int L = (int)bestOps.size();\n    if (L > K) L = K;\n    cout << L << \"\\n\";\n    for (int i = 0; i < L; i++) {\n        int opId = bestOps[i];\n        auto meta = outMeta[opId];\n        cout << (int)meta.m << \" \" << (int)meta.p << \" \" << (int)meta.q << \"\\n\";\n    }\n    return 0;\n}","ahc033":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Crane {\n    int x, y;\n    bool holding = false;\n    int holdId = -1;\n    bool bombed = false;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    cin >> N;\n    vector<vector<int>> A(N, vector<int>(N));\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) cin >> A[i][j];\n    }\n\n    // Plan: bomb small cranes on the first turn, then use only the large crane.\n    // Processing receiving gates in order r=0..N-1, picking N containers each time gate has one.\n    // When holding a container b, deliver it to dispatch gate (b/N, N-1).\n\n    const int R = N, C = N;\n    vector<vector<int>> grid(R, vector<int>(C, -1)); // container id or -1\n    vector<int> recvNext(R, 0); // next index to place for receiving gate row i\n\n    vector<Crane> cranes(N);\n    for (int i = 0; i < N; i++) {\n        cranes[i].x = i;\n        cranes[i].y = 0;\n        cranes[i].holding = false;\n        cranes[i].holdId = -1;\n        cranes[i].bombed = false;\n    }\n\n    enum Mode { GO_PICK, GO_DISPATCH };\n    Mode mode = GO_PICK;\n\n    int curGate = 0;     // receiving gate row\n    int pickedFromGate = 0;\n    int dispatchRow = -1;\n    int T = 0;\n\n    long long dispatchedCount = 0;\n    vector<vector<int>> dispatchSeq(N);\n\n    // operations[crane] is the string to output\n    vector<string> ops(N);\n\n    auto inb = [&](int x, int y) {\n        return 0 <= x && x < R && 0 <= y && y < C;\n    };\n\n    // Simulation loop up to 10000 turns\n    for (; T < 10000; T++) {\n        // ---- step 1: place arriving containers on receiving gates (left edge) ----\n        for (int i = 0; i < N; i++) {\n            if (recvNext[i] >= N) continue;\n            if (grid[i][0] != -1) continue; // already has a container\n\n            bool block = false;\n            for (int k = 0; k < N; k++) {\n                if (cranes[k].bombed) continue;\n                if (cranes[k].holding && cranes[k].x == i && cranes[k].y == 0) {\n                    block = true;\n                    break;\n                }\n            }\n            if (block) continue;\n\n            grid[i][0] = A[i][recvNext[i]];\n            recvNext[i]++;\n        }\n\n        // ---- decide actions for each crane for step 2 ----\n        vector<char> act(N, '.');\n\n        // Small cranes (1..N-1) are bombed on turn 1 (T==0) and then do '.'\n        for (int i = 1; i < N; i++) {\n            if (!cranes[i].bombed) {\n                if (T == 0) act[i] = 'B';\n                else act[i] = '.';\n            } else {\n                act[i] = '.';\n            }\n        }\n\n        // Large crane (0)\n        if (!cranes[0].bombed) {\n            if (mode == GO_PICK) {\n                // target receiving square: (curGate, 0)\n                if (cranes[0].x == curGate && cranes[0].y == 0) {\n                    if (!cranes[0].holding) {\n                        if (grid[curGate][0] != -1) {\n                            act[0] = 'P';\n                        } else {\n                            act[0] = '.';\n                        }\n                    } else {\n                        // Shouldn't happen in GO_PICK\n                        act[0] = '.';\n                    }\n                } else {\n                    // move towards (curGate, 0) while not holding\n                    if (cranes[0].x < curGate) act[0] = 'D';\n                    else if (cranes[0].x > curGate) act[0] = 'U';\n                    else if (cranes[0].y > 0) act[0] = 'L';\n                    else act[0] = '.';\n                }\n            } else { // GO_DISPATCH\n                // target dispatch square: (dispatchRow, N-1)\n                int tx = dispatchRow, ty = N - 1;\n                if (cranes[0].x == tx && cranes[0].y == ty) {\n                    if (cranes[0].holding) {\n                        if (grid[tx][ty] == -1) act[0] = 'Q';\n                        else act[0] = '.';\n                    } else {\n                        act[0] = '.';\n                    }\n                } else {\n                    // while carrying, prefer \"right-first\": go to col 4 then vertical\n                    if (cranes[0].y < N - 1) act[0] = 'R';\n                    else {\n                        if (cranes[0].x < tx) act[0] = 'D';\n                        else act[0] = 'U';\n                    }\n                }\n            }\n        }\n\n        // Append ops\n        for (int i = 0; i < N; i++) ops[i].push_back(act[i]);\n\n        // ---- step 2: apply actions simultaneously (with legality checks) ----\n        // Determine destinations for movement and bombing.\n        vector<pair<int,int>> src(N), dest(N);\n        vector<bool> bombAfter(N, false), activeAfter(N, false);\n        for (int i = 0; i < N; i++) {\n            src[i] = {cranes[i].x, cranes[i].y};\n            dest[i] = src[i];\n        }\n\n        auto getDest = [&](int i, char a) -> pair<int,int> {\n            int x = cranes[i].x, y = cranes[i].y;\n            if (a == 'U') x--;\n            if (a == 'D') x++;\n            if (a == 'L') y--;\n            if (a == 'R') y++;\n            return {x, y};\n        };\n\n        for (int i = 0; i < N; i++) {\n            char a = act[i];\n            if (cranes[i].bombed) {\n                if (a != '.') {\n                    cerr << \"Illegal: bombed crane acted at turn \" << T+1 << \"\\n\";\n                    return 0;\n                }\n                continue;\n            }\n\n            if (a == 'B') {\n                if (cranes[i].holding) {\n                    cerr << \"Illegal: crane bombing while holding\\n\";\n                    return 0;\n                }\n                bombAfter[i] = true;\n                activeAfter[i] = false;\n                dest[i] = src[i];\n            } else if (a == 'U' || a == 'D' || a == 'L' || a == 'R') {\n                auto nd = getDest(i, a);\n                if (!inb(nd.first, nd.second)) {\n                    cerr << \"Illegal: out of bounds move\\n\";\n                    return 0;\n                }\n                dest[i] = nd;\n                activeAfter[i] = true;\n            } else {\n                // '.', 'P', 'Q': no movement\n                dest[i] = src[i];\n                activeAfter[i] = true;\n            }\n        }\n\n        // Overlap check (only consider cranes that remain after step 2, excluding those that bomb)\n        vector<int> remaining;\n        for (int i = 0; i < N; i++) {\n            if (!cranes[i].bombed && !bombAfter[i]) remaining.push_back(i);\n        }\n        // Unique destinations\n        {\n            set<pair<int,int>> used;\n            for (int i : remaining) {\n                if (used.count(dest[i])) {\n                    cerr << \"Illegal: overlap after step2\\n\";\n                    return 0;\n                }\n                used.insert(dest[i]);\n            }\n            // Swap check among remaining\n            for (int a = 0; a < (int)remaining.size(); a++) for (int b = a+1; b < (int)remaining.size(); b++) {\n                int i = remaining[a], j = remaining[b];\n                if (src[i] == dest[j] && src[j] == dest[i] && src[i] != src[j]) {\n                    cerr << \"Illegal: swap/pass move detected\\n\";\n                    return 0;\n                }\n            }\n        }\n\n        // Apply movements\n        for (int i = 0; i < N; i++) {\n            if (cranes[i].bombed) continue;\n            if (bombAfter[i]) continue;\n            cranes[i].x = dest[i].first;\n            cranes[i].y = dest[i].second;\n        }\n        // Apply bombing\n        for (int i = 0; i < N; i++) {\n            if (bombAfter[i]) cranes[i].bombed = true;\n        }\n\n        // Apply P/Q\n        for (int i = 0; i < N; i++) {\n            if (cranes[i].bombed) continue;\n            char a = act[i];\n            if (a == 'P') {\n                if (cranes[i].holding) {\n                    cerr << \"Illegal: P while holding\\n\";\n                    return 0;\n                }\n                int x = cranes[i].x, y = cranes[i].y;\n                if (grid[x][y] == -1) {\n                    cerr << \"Illegal: P on empty cell\\n\";\n                    return 0;\n                }\n                cranes[i].holding = true;\n                cranes[i].holdId = grid[x][y];\n                grid[x][y] = -1;\n            } else if (a == 'Q') {\n                if (!cranes[i].holding) {\n                    cerr << \"Illegal: Q without holding\\n\";\n                    return 0;\n                }\n                int x = cranes[i].x, y = cranes[i].y;\n                if (grid[x][y] != -1) {\n                    cerr << \"Illegal: Q on occupied cell\\n\";\n                    return 0;\n                }\n                grid[x][y] = cranes[i].holdId;\n                cranes[i].holdId = -1;\n                cranes[i].holding = false;\n            } else {\n                // '.', movement handled already\n            }\n        }\n\n        // ---- step 3: dispatch containers from dispatch gates (right edge) ----\n        for (int i = 0; i < N; i++) {\n            int x = i, y = N-1;\n            if (grid[x][y] != -1) {\n                int b = grid[x][y];\n                grid[x][y] = -1;\n                dispatchedCount++;\n                int expectGate = b / N;\n                if (expectGate != i) {\n                    // Should not happen in this strategy\n                    // Still keep simulation running.\n                }\n                dispatchSeq[i].push_back(b);\n            }\n        }\n\n        // ---- update mode and counters based on crane0 action ----\n        if (!cranes[0].bombed) {\n            if (mode == GO_PICK) {\n                if (act[0] == 'P') {\n                    // Just picked some container b\n                    // mode becomes GO_DISPATCH with correct dispatch gate row\n                    int b = cranes[0].holdId; // after P, holdId is set\n                    dispatchRow = b / N;\n                    mode = GO_DISPATCH;\n                }\n            } else { // GO_DISPATCH\n                if (act[0] == 'Q') {\n                    // Released a container at dispatch gate; it should have been dispatched in step3.\n                    pickedFromGate++;\n                    if (pickedFromGate == N) {\n                        curGate++;\n                        pickedFromGate = 0;\n                    }\n                    if (curGate == N) {\n                        // All gates done; GO_PICK won't be used.\n                    }\n                    mode = GO_PICK;\n                }\n            }\n        }\n\n        if (dispatchedCount == 1LL * N * N) break;\n    }\n\n    if (dispatchedCount != 1LL * N * N) {\n        // Still output what we have; but ideally shouldn't happen.\n        // In contest evaluation this could hurt M3 badly.\n        // We just exit.\n        // (No extra printing to keep output format correct.)\n    }\n\n    // Ensure all strings same length\n    int L = ops[0].size();\n    for (int i = 0; i < N; i++) {\n        // ops[i] should already have length L due to synchronous simulation loop\n        // Still be safe.\n        if ((int)ops[i].size() < L) ops[i] += string(L - ops[i].size(), '.');\n    }\n\n    for (int i = 0; i < N; i++) {\n        cout << ops[i] << \"\\n\";\n    }\n    return 0;\n}","ahc034":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic inline int manhattan(int r1, int c1, int r2, int c2) {\n    return abs(r1 - r2) + abs(c1 - c2);\n}\n\nstatic inline int cellId(int r, int c, int N) { return r * N + c; }\nstatic inline pair<int,int> cellRC(int id, int N) { return {id / N, id % N}; }\n\nstatic inline void movePath(int &r, int &c, int nr, int nc, vector<string> &ops) {\n    // shortest Manhattan path: vertical then horizontal\n    while (r < nr) { ops.push_back(\"D\"); r++; }\n    while (r > nr) { ops.push_back(\"U\"); r--; }\n    while (c < nc) { ops.push_back(\"R\"); c++; }\n    while (c > nc) { ops.push_back(\"L\"); c--; }\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++) for (int j = 0; j < N; j++) cin >> h[i][j];\n\n    vector<int> supplies; // ids of cells with h>0\n    vector<int> demands;  // ids of cells with h<0\n    vector<int> supplyAmt(N*N, 0), demandRem(N*N, 0);\n\n    for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) {\n        int id = cellId(i,j,N);\n        if (h[i][j] > 0) { supplies.push_back(id); supplyAmt[id] = h[i][j]; }\n        else if (h[i][j] < 0) { demands.push_back(id); demandRem[id] = -h[i][j]; }\n    }\n\n    if (supplies.empty()) {\n        // already all zero\n        return 0;\n    }\n\n    const int V = N*N;\n    vector<vector<int>> dist(V, vector<int>(V, 0));\n    for (int a = 0; a < V; a++) {\n        auto [ra, ca] = cellRC(a, N);\n        for (int b = 0; b < V; b++) {\n            auto [rb, cb] = cellRC(b, N);\n            dist[a][b] = abs(ra - rb) + abs(ca - cb);\n        }\n    }\n\n    // Jobs: one per supply cell\n    struct Job {\n        int sourceId;\n        int totalLoad; // == supplyAmt[sourceId]\n        vector<pair<int,int>> targets; // (demandId, amount)\n        vector<pair<int,int>> orderedTargets; // same, in visit order\n        long long internalCost = 0; // estimated\n    };\n\n    vector<Job> jobs;\n    jobs.reserve(supplies.size());\n    for (int sid : supplies) {\n        Job jb;\n        jb.sourceId = sid;\n        jb.totalLoad = supplyAmt[sid];\n        jobs.push_back(std::move(jb));\n    }\n\n    // Greedy matching from each source to nearest available demand (by manhattan).\n    // Note: demandRem is global; once depleted, not used by later sources.\n    // We'll map job index to source id in jobs[*].sourceId.\n    // For searching nearest demand, we scan all demand cells each time (N small).\n    // Tie-break: prefer larger remaining.\n    vector<int> demandList = demands;\n    // local mutable copy since we use demandRem global\n    // (already initialized to abs negative heights)\n    auto demandAvailable = [&](int did)->int { return demandRem[did]; };\n\n    for (auto &jb : jobs) {\n        int sid = jb.sourceId;\n        int srem = jb.totalLoad;\n\n        while (srem > 0) {\n            int bestDid = -1;\n            int bestDist = INT_MAX;\n            int bestRem = -1;\n\n            for (int did : demandList) {\n                int rem = demandAvailable(did);\n                if (rem <= 0) continue;\n                int d = dist[sid][did];\n                if (d < bestDist || (d == bestDist && rem > bestRem)) {\n                    bestDist = d;\n                    bestRem = rem;\n                    bestDid = did;\n                }\n            }\n\n            if (bestDid == -1) break; // should not happen because total sum is 0\n\n            int x = min(srem, demandRem[bestDid]);\n            jb.targets.push_back({bestDid, x});\n            srem -= x;\n            demandRem[bestDid] -= x;\n        }\n    }\n\n    // Random generator for internal ordering\n    std::mt19937 rng(1234567);\n\n    auto estimateInternal = [&](int sourceId, int totalLoad,\n                                 const vector<pair<int,int>> &visitSeq) -> long long {\n        // visitSeq: (targetId, amount), visited in this order\n        // Truck starts at source with load=totalLoad.\n        long long cost = 0;\n        int load = totalLoad;\n        int cur = sourceId;\n        for (auto [tid, amt] : visitSeq) {\n            int len = dist[cur][tid];\n            cost += 1LL * len * (100 + load); // move cost component\n            // load during unload decreases\n            load -= amt;\n            // unloading cost and loading cost\n            // We'll include unloading cost here as amt; loading is added later once.\n            cost += amt;\n            cur = tid;\n        }\n        // Loading cost totalLoad:\n        cost += totalLoad;\n        return cost;\n    };\n\n    auto decideInternalOrder = [&](Job &jb) {\n        int k = (int)jb.targets.size();\n        if (k == 0) {\n            jb.orderedTargets.clear();\n            jb.internalCost = 0;\n            return;\n        }\n        if (k == 1) {\n            jb.orderedTargets = jb.targets;\n            // estimate straightforward\n            jb.internalCost = estimateInternal(jb.sourceId, jb.totalLoad, jb.orderedTargets);\n            return;\n        }\n\n        // Prepare targets arrays for easier selection\n        vector<int> tids(k), amts(k);\n        for (int i = 0; i < k; i++) {\n            tids[i] = jb.targets[i].first;\n            amts[i] = jb.targets[i].second;\n        }\n\n        long long bestCost = (1LL<<62);\n        vector<pair<int,int>> bestSeq;\n\n        int trials = min(18, max(6, k/2));\n        for (int t = 0; t < trials; t++) {\n            vector<char> used(k, 0);\n            int cur = jb.sourceId;\n            int remCnt = k;\n            int remainingLoad = jb.totalLoad;\n\n            vector<pair<int,int>> seq;\n            seq.reserve(k);\n\n            while (remCnt > 0) {\n                // pick next among top 3 closest (with some randomness)\n                vector<pair<int,int>> cand; // (distance, idx)\n                cand.reserve(k);\n                for (int i = 0; i < k; i++) if (!used[i]) {\n                    cand.push_back({dist[cur][tids[i]], i});\n                }\n                sort(cand.begin(), cand.end());\n\n                int pickCount = min(3, (int)cand.size());\n                int pickIdx = (pickCount == 1) ? 0 : (int)(rng() % pickCount);\n                int idx = cand[pickIdx].second;\n\n                used[idx] = 1;\n                remCnt--;\n                seq.push_back({tids[idx], amts[idx]});\n                cur = tids[idx];\n                remainingLoad -= amts[idx];\n            }\n\n            long long est = estimateInternal(jb.sourceId, jb.totalLoad, seq);\n            if (est < bestCost) {\n                bestCost = est;\n                bestSeq = std::move(seq);\n            }\n        }\n\n        jb.orderedTargets = bestSeq;\n        jb.internalCost = bestCost;\n    };\n\n    for (auto &jb : jobs) decideInternalOrder(jb);\n\n    vector<string> ops;\n    ops.reserve(200000);\n\n    // Execute jobs in greedy order:\n    // choose job i minimizing 100*dist(cur, job.source) + job.internalCost\n    vector<char> done(jobs.size(), 0);\n    int doneCnt = 0;\n\n    int curR = 0, curC = 0;\n    int curId = cellId(curR, curC, N);\n\n    while (doneCnt < (int)jobs.size()) {\n        int bestJ = -1;\n        long long bestScore = (1LL<<62);\n\n        for (int j = 0; j < (int)jobs.size(); j++) if (!done[j]) {\n            long long ext = 1LL * 100 * dist[curId][jobs[j].sourceId]; // truck empty here\n            long long total = ext + jobs[j].internalCost;\n            if (total < bestScore) {\n                bestScore = total;\n                bestJ = j;\n            }\n        }\n        if (bestJ == -1) break;\n\n        Job &jb = jobs[bestJ];\n\n        // Move empty to source\n        auto [sr, sc] = cellRC(jb.sourceId, N);\n        movePath(curR, curC, sr, sc, ops);\n        curId = jb.sourceId;\n\n        // Load entire job amount once\n        if (jb.totalLoad > 0) {\n            ops.push_back(\"+\" + to_string(jb.totalLoad));\n        }\n\n        // Visit targets in predetermined order, unloading portions\n        int r = curR, c = curC;\n        for (auto [tid, amt] : jb.orderedTargets) {\n            auto [tr, tc] = cellRC(tid, N);\n            movePath(r, c, tr, tc, ops);\n            ops.push_back(\"-\" + to_string(amt));\n            curId = tid;\n            curR = tr; curC = tc;\n        }\n\n        done[bestJ] = 1;\n        doneCnt++;\n        if ((int)ops.size() > 100000) {\n            // Should be very unlikely with N=20, but keep safe:\n            // fallback: stop (would be illegal). Here we instead just break and output nothing extra.\n            // In contest, exceeding the limit causes WA, so we try to avoid it by construction.\n            // We'll return to avoid malformed output.\n            return 0;\n        }\n    }\n\n    for (auto &s : ops) cout << s << \"\\n\";\n    return 0;\n}","ahc035":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\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    const int seed_count = 2 * N * (N - 1);\n    const int C = N * N;\n\n    vector<vector<int>> X(seed_count, vector<int>(M));\n    for (int k = 0; k < seed_count; k++) {\n        for (int l = 0; l < M; l++) cin >> X[k][l];\n    }\n\n    auto id = [&](int i, int j) { return i * N + j; };\n\n    // Build edge list and incident edges for local search (fixed by N).\n    vector<pair<int,int>> edges;\n    edges.reserve(seed_count);\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (i + 1 < N) edges.push_back({id(i,j), id(i+1,j)});\n            if (j + 1 < N) edges.push_back({id(i,j), id(i,j+1)});\n        }\n    }\n    // edges.size() should equal seed_count.\n    // incident edge indices per cell\n    vector<vector<int>> incident(C);\n    for (int ei = 0; ei < (int)edges.size(); ei++) {\n        auto [u,v] = edges[ei];\n        incident[u].push_back(ei);\n        incident[v].push_back(ei);\n    }\n\n    mt19937_64 rng((uint64_t)chrono::high_resolution_clock::now().time_since_epoch().count());\n\n    auto solve_one_turn = [&]() -> vector<int> {\n        // Compute V and per-component maxima indices.\n        vector<int> V(seed_count, 0);\n        vector<int> maxIdx(M, 0);\n        vector<int> maxVal(M, -1);\n\n        for (int k = 0; k < seed_count; k++) {\n            int sum = 0;\n            for (int l = 0; l < M; l++) sum += X[k][l];\n            V[k] = sum;\n        }\n        for (int l = 0; l < M; l++) {\n            int bestk = 0;\n            int bestv = X[0][l];\n            for (int k = 1; k < seed_count; k++) {\n                if (X[k][l] > bestv) {\n                    bestv = X[k][l];\n                    bestk = k;\n                }\n            }\n            maxVal[l] = bestv;\n            maxIdx[l] = bestk;\n        }\n\n        // Precompute UB(a,b) and UB^2(a,b).\n        vector<vector<int>> UB(seed_count, vector<int>(seed_count, 0));\n        vector<vector<ll>> UB2(seed_count, vector<ll>(seed_count, 0));\n        for (int a = 0; a < seed_count; a++) {\n            for (int b = a; b < seed_count; b++) {\n                int ub = 0;\n                for (int l = 0; l < M; l++) ub += max(X[a][l], X[b][l]);\n                UB[a][b] = UB[b][a] = ub;\n                UB2[a][b] = UB2[b][a] = (ll)ub * (ll)ub;\n            }\n        }\n\n        // Candidate seeds: top by V + per-component argmax seeds.\n        vector<int> byV(seed_count);\n        iota(byV.begin(), byV.end(), 0);\n        sort(byV.begin(), byV.end(), [&](int a, int b){ return V[a] > V[b]; });\n\n        vector<int> cand;\n        cand.reserve(seed_count);\n        {\n            int TOPV = min(seed_count, 30);\n            for (int i = 0; i < TOPV; i++) cand.push_back(byV[i]);\n        }\n        for (int l = 0; l < M; l++) cand.push_back(maxIdx[l]);\n        sort(cand.begin(), cand.end());\n        cand.erase(unique(cand.begin(), cand.end()), cand.end());\n\n        // Use top subset for pair search by V to limit O(k^2).\n        vector<int> cand2 = cand;\n        sort(cand2.begin(), cand2.end(), [&](int a, int b){ return V[a] > V[b]; });\n        int K = min<int>(25, cand2.size());\n        cand2.resize(K);\n\n        // Best UB pair (a,b)\n        int bestA = cand2[0], bestB = cand2[1];\n        ll bestPairUB = -1;\n        for (int i = 0; i < K; i++) for (int j = i+1; j < K; j++) {\n            int a = cand2[i], b = cand2[j];\n            ll ub = UB[a][b];\n            if (ub > bestPairUB || (ub == bestPairUB && V[a] + V[b] > V[bestA] + V[bestB])) {\n                bestPairUB = ub;\n                bestA = a;\n                bestB = b;\n            }\n        }\n\n        // Select 36 seeds.\n        vector<int> chosen;\n        chosen.reserve(C);\n        chosen.push_back(bestA);\n        if (bestB != bestA) chosen.push_back(bestB);\n\n        vector<char> used(seed_count, 0);\n        used[bestA] = 1;\n        used[bestB] = 1;\n\n        struct Item { int k; ll score; };\n        vector<Item> items;\n        items.reserve(seed_count);\n        for (int k = 0; k < seed_count; k++) {\n            if (used[k]) continue;\n            // Score biased toward mixing with bestA/bestB.\n            ll score = (ll)V[k] * 10 + (ll)UB[bestA][k] + (ll)UB[bestB][k];\n            items.push_back({k, score});\n        }\n        sort(items.begin(), items.end(), [&](const Item& a, const Item& b){\n            return a.score > b.score;\n        });\n\n        for (auto &it : items) {\n            if ((int)chosen.size() >= C) break;\n            chosen.push_back(it.k);\n            used[it.k] = 1;\n        }\n        // Fallback if somehow not enough (shouldn't happen)\n        for (int k = 0; (int)chosen.size() < C && k < seed_count; k++) {\n            if (!used[k]) {\n                chosen.push_back(k);\n                used[k] = 1;\n            }\n        }\n\n        // Build initial placement A (size C, entries are seed indices distinct).\n        vector<int> A(C, -1);\n        auto place = [&](int i, int j, int seed) {\n            A[id(i,j)] = seed;\n        };\n\n        // Fixed positions near top-left (for N>=3, which is true here).\n        place(0,0,bestA);\n        if (N > 1) place(0,1,bestB);\n\n        // Used seeds in placement\n        vector<char> inPlace(seed_count, 0);\n        inPlace[bestA] = 1;\n        inPlace[bestB] = 1;\n\n        auto pickMaxWith = [&](int baseSeed, const vector<int>& pool)->int{\n            int arg = -1;\n            ll best = -1;\n            for (int k : pool) {\n                ll ub = UB[baseSeed][k];\n                if (ub > best) { best = ub; arg = k; }\n            }\n            return arg;\n        };\n\n        // Remaining pool\n        vector<int> pool;\n        pool.reserve(C);\n        for (int k : chosen) if (!inPlace[k]) pool.push_back(k);\n\n        // Place neighbor maximizing UB with bestA / bestB when possible\n        if (N > 1) {\n            if (int(pool.size()) > 0) {\n                // (1,0) is adjacent to (0,0)\n                int c = pickMaxWith(bestA, pool);\n                if (c != -1) {\n                    place(1,0,c);\n                    inPlace[c] = 1;\n                    pool.erase(find(pool.begin(), pool.end(), c));\n                }\n            }\n        }\n        if (N > 2) {\n            if (!pool.empty()) {\n                // (0,2) adjacent to (0,1)=bestB\n                int d = pickMaxWith(bestB, pool);\n                place(0,2,d);\n                inPlace[d] = 1;\n                pool.erase(find(pool.begin(), pool.end(), d));\n            }\n        }\n        if (N > 1) {\n            if (!pool.empty()) {\n                // (1,1) adjacent to (0,1)=bestB\n                int e = pickMaxWith(bestB, pool);\n                place(1,1,e);\n                inPlace[e] = 1;\n                pool.erase(find(pool.begin(), pool.end(), e));\n            }\n        }\n\n        // Collect remaining unfilled positions\n        vector<int> evenPos, oddPos;\n        for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) {\n            int p = id(i,j);\n            if (A[p] != -1) continue;\n            if ((i+j)%2==0) evenPos.push_back(p);\n            else oddPos.push_back(p);\n        }\n\n        // Remaining seeds from chosen not placed.\n        vector<int> remSeeds;\n        remSeeds.reserve(C);\n        for (int k : chosen) if (!inPlace[k]) remSeeds.push_back(k);\n        sort(remSeeds.begin(), remSeeds.end(), [&](int a, int b){ return V[a] > V[b]; });\n\n        // Fill remaining by alternating parity (to spread good seeds).\n        int ie = 0, io = 0;\n        for (int idx = 0; idx < (int)remSeeds.size(); idx++) {\n            int k = remSeeds[idx];\n            bool wantEven = (idx%2==0);\n            if (wantEven) {\n                if (ie < (int)evenPos.size()) A[evenPos[ie++]] = k;\n                else A[oddPos[io++]] = k;\n            } else {\n                if (io < (int)oddPos.size()) A[oddPos[io++]] = k;\n                else A[evenPos[ie++]] = k;\n            }\n        }\n\n        // Local search: maximize sum over edges UB^2.\n        auto calcObj = [&]() -> ll {\n            ll obj = 0;\n            for (int ei = 0; ei < (int)edges.size(); ei++) {\n                auto [u,v] = edges[ei];\n                int su = A[u], sv = A[v];\n                obj += UB2[su][sv];\n            }\n            return obj;\n        };\n\n        ll obj = calcObj();\n\n        int iters = 9000;\n        double temp0 = 7e6; // tuned for UB^2 magnitudes\n        uniform_real_distribution<double> uni(0.0, 1.0);\n\n        for (int it = 0; it < iters; it++) {\n            int p = (int)(rng() % C);\n            int q = (int)(rng() % C);\n            if (p == q) continue;\n\n            int sp = A[p], sq = A[q];\n            if (sp == sq) continue;\n\n            // affected edges: union of incident[p] and incident[q]\n            // since edges are small (60), simple marking is fine.\n            bool mark[100] = {};\n            vector<int> aff;\n            aff.reserve(12);\n            for (int ei : incident[p]) {\n                if (!mark[ei]) { mark[ei] = true; aff.push_back(ei); }\n            }\n            for (int ei : incident[q]) {\n                if (!mark[ei]) { mark[ei] = true; aff.push_back(ei); }\n            }\n\n            ll delta = 0;\n            for (int ei : aff) {\n                auto [u,v] = edges[ei];\n                // old seeds\n                int su_old = (u==p ? sp : (u==q ? sq : A[u]));\n                int sv_old = (v==p ? sp : (v==q ? sq : A[v]));\n                ll oldTerm = UB2[su_old][sv_old];\n\n                // new seeds after swapping p and q\n                int su_new = (u==p ? sq : (u==q ? sp : A[u]));\n                int sv_new = (v==p ? sq : (v==q ? sp : A[v]));\n                ll newTerm = UB2[su_new][sv_new];\n\n                delta += newTerm - oldTerm;\n            }\n\n            if (delta >= 0) {\n                swap(A[p], A[q]);\n                obj += delta;\n            } else {\n                double temp = temp0 * (1.0 - (double)it / iters) * (1.0 - (double)it / iters) + 1.0;\n                double prob = exp((double)delta / temp); // delta negative\n                if (uni(rng) < prob) {\n                    swap(A[p], A[q]);\n                    obj += delta;\n                }\n            }\n        }\n\n        return A;\n    };\n\n    for (int t = 0; t < T; t++) {\n        vector<int> A = solve_one_turn();\n\n        // Output grid A[i][j]\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                if (j) cout << ' ';\n                cout << A[id(i,j)];\n            }\n            cout << '\\n';\n        }\n        cout.flush();\n\n        // Read next seeds (judge provides them after seeing our output).\n        for (int k = 0; k < seed_count; k++) {\n            for (int l = 0; l < M; l++) cin >> X[k][l];\n        }\n    }\n    return 0;\n}","ahc038":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Pt { int x, y; };\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, V;\n    cin >> N >> M >> V;\n    vector<string> s(N), t(N);\n    for (int i = 0; i < N; i++) cin >> s[i];\n    for (int i = 0; i < N; i++) cin >> t[i];\n\n    vector<vector<int>> occ(N, vector<int>(N, 0));\n    for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) occ[i][j] = (s[i][j] == '1');\n\n    vector<Pt> A, B; // A: initial & !target (need move out), B: !initial & target (need fill)\n    for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) {\n        int si = (s[i][j] == '1');\n        int ti = (t[i][j] == '1');\n        if (si && !ti) A.push_back({i, j});\n        if (!si && ti) B.push_back({i, j});\n    }\n\n    // Arm design: V' = 2, root(0) -> fingertip(1), edge length 1\n    int Vp = 2;\n    cout << Vp << \"\\n\";\n    cout << 0 << \" \" << 1 << \"\\n\";\n\n    // Choose initial root (rx,ry) to reduce first moves.\n    // dir initial is right (0): fingertip = (rx, ry+1)\n    int rx = 0, ry = 0;\n    if (!A.empty()) {\n        int cx = N / 2, cy = N / 2;\n        long long bestScore = (1LL<<60);\n        Pt best = A[0];\n        for (auto &p : A) {\n            long long d = llabs(p.x - cx) + llabs(p.y - cy);\n            // prefer having the fingertip in-range when possible (ry <= N-2)\n            long long bonus = (p.y >= 1 && p.y <= N-1) ? 0 : 1;\n            long long score = d + 10 * bonus;\n            if (score < bestScore) {\n                bestScore = score;\n                best = p;\n            }\n        }\n        rx = best.x;\n        ry = max(0, min(N - 1, best.y - 1)); // fingertip y becomes best.y (if ry within range)\n    }\n    cout << rx << \" \" << ry << \"\\n\";\n\n    if (A.empty()) {\n        // No operations needed\n        return 0;\n    }\n\n    // State space: (root_x, root_y, dir)\n    // dir: 0=R, 1=D, 2=L, 3=U\n    array<int,4> dx{0, 1, 0, -1};\n    array<int,4> dy{1, 0, -1, 0};\n\n    int dir = 0; // initial edge extends to the right => fingertip direction = right\n\n    auto inRange = [&](int x, int y) {\n        return 0 <= x && x < N && 0 <= y && y < N;\n    };\n\n    auto encode = [&](int x, int y, int d) {\n        return ((x * N + y) * 4 + d);\n    };\n    auto decode = [&](int id, int &x, int &y, int &d) {\n        d = id % 4;\n        int p = id / 4;\n        x = p / N;\n        y = p % N;\n    };\n\n    int S = N * N * 4;\n\n    auto bfsBestSteps = [&](int startState, Pt target) -> vector<pair<char,char>> {\n        // candidates are states where fingertip(root,dir) == target\n        vector<int> cand;\n        for (int d = 0; d < 4; d++) {\n            int crx = target.x - dx[d];\n            int cry = target.y - dy[d];\n            if (inRange(crx, cry)) cand.push_back(encode(crx, cry, d));\n        }\n\n        vector<int> dist(S, -1), prevState(S, -1);\n        vector<char> prevMv(S, '?'), prevRot(S, '?');\n\n        queue<int> q;\n        dist[startState] = 0;\n        q.push(startState);\n\n        // move options: '.' U D L R\n        array<char,5> mvChar{'.','U','D','L','R'};\n        array<int,5> mvX{0,-1,1,0,0};\n        array<int,5> mvY{0,0,0,-1,1};\n\n        // rotate options: '.' L(CCW) R(CW)\n        array<char,3> rotChar{'.','L','R'};\n        auto applyRot = [&](int d, char rc)->int{\n            if (rc == 'L') return (d + 3) % 4; // CCW\n            if (rc == 'R') return (d + 1) % 4; // CW\n            return d;\n        };\n\n        while (!q.empty()) {\n            int v = q.front(); q.pop();\n            int vx, vy, vd;\n            decode(v, vx, vy, vd);\n\n            for (int mi = 0; mi < 5; mi++) {\n                int nx2 = vx + mvX[mi];\n                int ny2 = vy + mvY[mi];\n                if (!inRange(nx2, ny2)) continue;\n\n                for (int ri = 0; ri < 3; ri++) {\n                    char rc = rotChar[ri];\n                    int nd = applyRot(vd, rc);\n                    int u = encode(nx2, ny2, nd);\n                    if (dist[u] != -1) continue;\n                    dist[u] = dist[v] + 1;\n                    prevState[u] = v;\n                    prevMv[u] = mvChar[mi];\n                    prevRot[u] = rc;\n                    q.push(u);\n                }\n            }\n        }\n\n        int best = -1;\n        int bestDist = INT_MAX;\n        for (int id : cand) {\n            if (dist[id] != -1 && dist[id] < bestDist) {\n                bestDist = dist[id];\n                best = id;\n            }\n        }\n        // Must exist on a finite grid for reachable target\n        if (best == -1) return {};\n\n        // reconstruct steps from startState to best\n        vector<pair<char,char>> steps;\n        int cur = best;\n        while (cur != startState) {\n            steps.push_back({prevMv[cur], prevRot[cur]});\n            cur = prevState[cur];\n        }\n        reverse(steps.begin(), steps.end());\n        return steps;\n    };\n\n    bool holding = false;\n\n    auto toggleAt = [&](Pt p, bool wantPickup) {\n        if (wantPickup) {\n            // pick up from p\n            // legality: fingertip on p and occ[p]==1 and holding==false\n            if (holding) {\n                // should never happen\n                // cerr << \"pickup but holding\\n\";\n            }\n            // If occ mismatch, we'd break legality (but with correct A/B it shouldn't)\n            if (occ[p.x][p.y] != 1) {\n                // cerr << \"pickup occ mismatch\\n\";\n            }\n            occ[p.x][p.y] = 0;\n            holding = true;\n        } else {\n            // place to p\n            if (!holding) {\n                // cerr << \"release but not holding\\n\";\n            }\n            if (occ[p.x][p.y] != 0) {\n                // cerr << \"release occ mismatch\\n\";\n            }\n            occ[p.x][p.y] = 1;\n            holding = false;\n        }\n    };\n\n    vector<string> ops;\n    ops.reserve(90000);\n\n    auto goToAndToggle = [&](Pt target, bool pickup) {\n        int startState = encode(rx, ry, dir);\n        auto steps = bfsBestSteps(startState, target);\n\n        if (steps.empty()) {\n            // fingertip already on target, need one turn to perform P\n            string st;\n            st.push_back('.');\n            st.push_back('.');\n            st.push_back('.');\n            st.push_back('P');\n            ops.push_back(st);\n            toggleAt(target, pickup);\n            return;\n        }\n\n        for (int i = 0; i < (int)steps.size(); i++) {\n            char mv = steps[i].first;\n            char rot = steps[i].second;\n            bool last = (i == (int)steps.size() - 1);\n\n            string st;\n            st.push_back(mv);\n            st.push_back(rot);\n            st.push_back('.');        // vertex 0 is not a fingertip\n            st.push_back(last ? 'P' : '.'); // vertex 1 action\n\n            ops.push_back(st);\n\n            // simulate move\n            if (mv == 'U') rx--;\n            else if (mv == 'D') rx++;\n            else if (mv == 'L') ry--;\n            else if (mv == 'R') ry++;\n\n            // simulate rotation\n            if (rot == 'L') dir = (dir + 3) % 4;\n            else if (rot == 'R') dir = (dir + 1) % 4;\n\n            if (last) toggleAt(target, pickup);\n        }\n    };\n\n    // Main loop: move all A -> B\n    while (!A.empty()) {\n        int fx = rx + dx[dir];\n        int fy = ry + dy[dir];\n\n        // pick candidate sources closest to current fingertip\n        vector<int> idx(A.size());\n        iota(idx.begin(), idx.end(), 0);\n        sort(idx.begin(), idx.end(), [&](int i, int j) {\n            int di = abs(fx - A[i].x) + abs(fy - A[i].y);\n            int dj = abs(fx - A[j].x) + abs(fy - A[j].y);\n            return di < dj;\n        });\n\n        int Kcand = min<int>(25, idx.size());\n\n        long long bestCost = (1LL<<60);\n        int bestI = idx[0];\n        int bestJ = 0;\n\n        // heuristic cost: manhattan(fingertip, src) + manhattan(src, chosen dst)\n        for (int ci = 0; ci < Kcand; ci++) {\n            int i = idx[ci];\n            long long base = llabs(fx - A[i].x) + llabs(fy - A[i].y);\n\n            int nearJ = 0;\n            int nearD = INT_MAX;\n            for (int j = 0; j < (int)B.size(); j++) {\n                int d = abs(A[i].x - B[j].x) + abs(A[i].y - B[j].y);\n                if (d < nearD) {\n                    nearD = d;\n                    nearJ = j;\n                }\n            }\n            long long cost = base + nearD;\n            if (cost < bestCost) {\n                bestCost = cost;\n                bestI = i;\n                bestJ = nearJ;\n            }\n        }\n\n        Pt src = A[bestI];\n        Pt dst = B[bestJ];\n\n        // remove src from A, dst from B\n        A[bestI] = A.back(); A.pop_back();\n        B[bestJ] = B.back(); B.pop_back();\n\n        // move and toggle pickup/release\n        goToAndToggle(src, true);  // pick from src\n        goToAndToggle(dst, false); // place to dst\n    }\n\n    // If somehow exceeded limit, just terminate (shouldn't happen in practice)\n    if ((int)ops.size() > 100000) return 0;\n\n    for (auto &st : ops) cout << st << \"\\n\";\n    return 0;\n}","ahc039":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int MAXC = 100000;\nstatic constexpr int MAXN = 10000; // 2N, N=5000\n\nstruct Pt {\n    int x, y;\n    int w; // +1 mackerel, -1 sardine\n};\n\nstruct SplitMix64 {\n    uint64_t x;\n    explicit SplitMix64(uint64_t seed) : x(seed) {}\n    uint64_t next_u64() {\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 next_int(int mod) { return (int)(next_u64() % (uint64_t)mod); }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    cin >> N;\n    vector<Pt> pts;\n    pts.reserve(2 * N);\n    for (int i = 0; i < N; i++) {\n        int x, y;\n        cin >> x >> y;\n        pts.push_back({x, y, +1});\n    }\n    for (int i = 0; i < N; i++) {\n        int x, y;\n        cin >> x >> y;\n        pts.push_back({x, y, -1});\n    }\n\n    const int G = 90; // grid resolution\n    const int SZ = MAXC + 1; // 100001\n\n    auto cellOf = [&](int v) -> int {\n        // v in [0, MAXC]\n        // maps into [0, G-1]\n        return (int)((long long)v * G / SZ);\n    };\n\n    vector<vector<int>> A(G, vector<int>(G, 0)); // A[xCell][yCell]\n\n    for (auto &p : pts) {\n        int cx = cellOf(p.x);\n        int cy = cellOf(p.y);\n        A[cx][cy] += p.w;\n    }\n\n    // Find maximum-sum sub-rectangle in A using O(G^3):\n    // Fix x0..x1, reduce to 1D array over y and run Kadane.\n    long long bestCellSum = LLONG_MIN;\n    int bestX0 = 0, bestX1 = 0, bestY0 = 0, bestY1 = 0;\n\n    vector<long long> temp(G, 0);\n\n    auto kadane = [&](const vector<long long> &arr) -> tuple<long long,int,int> {\n        // maximum subarray sum (non-empty), return (sum, l, r)\n        long long cur = arr[0];\n        long long best = arr[0];\n        int curL = 0, bestL = 0, bestR = 0;\n        for (int i = 1; i < G; i++) {\n            if (cur < 0) {\n                cur = arr[i];\n                curL = i;\n            } else {\n                cur += arr[i];\n            }\n            if (cur > best) {\n                best = cur;\n                bestL = curL;\n                bestR = i;\n            }\n        }\n        return {best, bestL, bestR};\n    };\n\n    for (int x0 = 0; x0 < G; x0++) {\n        fill(temp.begin(), temp.end(), 0LL);\n        for (int x1 = x0; x1 < G; x1++) {\n            for (int y = 0; y < G; y++) temp[y] += A[x1][y];\n            auto [s, yl, yr] = kadane(temp);\n            if (s > bestCellSum) {\n                bestCellSum = s;\n                bestX0 = x0; bestX1 = x1;\n                bestY0 = yl; bestY1 = yr;\n            }\n        }\n    }\n\n    auto lowerBoundCell = [&](int c) -> int {\n        // c in [0,G-1]\n        return (int)((long long)c * SZ / G);\n    };\n    auto upperBoundCell = [&](int c) -> int {\n        // inclusive upper bound: (c+1)*SZ/G - 1\n        long long ub = (long long)(c + 1) * SZ / G - 1;\n        if (ub < 0) ub = 0;\n        if (ub > MAXC) ub = MAXC;\n        return (int)ub;\n    };\n\n    auto clampFixRect = [&](int &xL, int &xR, int &yB, int &yT) {\n        xL = max(0, min(MAXC, xL));\n        xR = max(0, min(MAXC, xR));\n        yB = max(0, min(MAXC, yB));\n        yT = max(0, min(MAXC, yT));\n        if (xL == xR) {\n            if (xR < MAXC) xR++;\n            else xL--;\n        }\n        if (yB == yT) {\n            if (yT < MAXC) yT++;\n            else yB--;\n        }\n        xL = max(0, min(MAXC, xL));\n        xR = max(0, min(MAXC, xR));\n        yB = max(0, min(MAXC, yB));\n        yT = max(0, min(MAXC, yT));\n        if (xL > xR) swap(xL, xR);\n        if (yB > yT) swap(yB, yT);\n        // Need strictly rectangle with area > 0 to avoid degenerate polygon\n        if (xL == xR) {\n            if (xL < MAXC) xR = xL + 1;\n            else xL = xR - 1;\n        }\n        if (yB == yT) {\n            if (yB < MAXC) yT = yB + 1;\n            else yB = yT - 1;\n        }\n    };\n\n    auto exactDiff = [&](int xL, int xR, int yB, int yT) -> long long {\n        long long diff = 0;\n        for (auto &p : pts) {\n            if (xL <= p.x && p.x <= xR && yB <= p.y && p.y <= yT) diff += p.w;\n        }\n        return diff;\n    };\n\n    int xL = lowerBoundCell(bestX0);\n    int xR = upperBoundCell(bestX1);\n    int yB = lowerBoundCell(bestY0);\n    int yT = upperBoundCell(bestY1);\n    clampFixRect(xL, xR, yB, yT);\n\n    long long bestDiff = exactDiff(xL, xR, yB, yT);\n    int ansX1 = xL, ansX2 = xR, ansY1 = yB, ansY2 = yT;\n\n    // Build candidate coordinate lists for local random search\n    vector<int> xs, ys;\n    xs.reserve(2 * N);\n    ys.reserve(2 * N);\n    for (auto &p : pts) {\n        xs.push_back(p.x);\n        ys.push_back(p.y);\n    }\n    sort(xs.begin(), xs.end());\n    xs.erase(unique(xs.begin(), xs.end()), xs.end());\n    sort(ys.begin(), ys.end());\n    ys.erase(unique(ys.begin(), ys.end()), ys.end());\n\n    auto makeCandidates = [&](const vector<int> &arr, int L, int R) {\n        L = max(0, L);\n        R = min(MAXC, R);\n        vector<int> cand;\n        for (int v : arr) {\n            if (L <= v && v <= R) cand.push_back(v);\n        }\n        // Ensure boundaries are possible too\n        cand.push_back(L);\n        cand.push_back(R);\n        cand.push_back(0);\n        cand.push_back(MAXC);\n        sort(cand.begin(), cand.end());\n        cand.erase(unique(cand.begin(), cand.end()), cand.end());\n        return cand;\n    };\n\n    vector<int> candX = makeCandidates(xs, ansX1 - 5000, ansX2 + 5000);\n    vector<int> candY = makeCandidates(ys, ansY1 - 5000, ansY2 + 5000);\n\n    SplitMix64 rng(123456789ULL);\n\n    auto tryUpdate = [&](int txL, int txR, int tyB, int tyT) {\n        if (txL < 0 || txR > MAXC || tyB < 0 || tyT > MAXC) return;\n        int L = txL, R = txR, B = tyB, T = tyT;\n        clampFixRect(L, R, B, T);\n        long long d = exactDiff(L, R, B, T);\n        if (d > bestDiff) {\n            bestDiff = d;\n            ansX1 = L; ansX2 = R;\n            ansY1 = B; ansY2 = T;\n        }\n    };\n\n    // Random local search\n    for (int it = 0; it < 500; it++) {\n        int a = candX[rng.next_int((int)candX.size())];\n        int b = candX[rng.next_int((int)candX.size())];\n        int L = min(a, b), R = max(a, b);\n        int c = candY[rng.next_int((int)candY.size())];\n        int d = candY[rng.next_int((int)candY.size())];\n        int B = min(c, d), T = max(c, d);\n\n        // Ensure strict rectangle width/height by clampFixRect\n        tryUpdate(L, R, B, T);\n    }\n\n    // Final safety fallback: full box (guaranteed legal)\n    // score would be 1 because a=b=N => a-b+1=1\n    // (still keep if bestDiff somehow became negative due to extreme adjustments)\n    if (bestDiff < 0) {\n        ansX1 = 0; ansX2 = MAXC;\n        ansY1 = 0; ansY2 = MAXC;\n    }\n\n    // Output rectangle as a simple axis-aligned polygon with 4 vertices\n    cout << 4 << '\\n';\n    // CCW: (xL,yB) -> (xR,yB) -> (xR,yT) -> (xL,yT)\n    cout << ansX1 << ' ' << ansY1 << '\\n';\n    cout << ansX2 << ' ' << ansY1 << '\\n';\n    cout << ansX2 << ' ' << ansY2 << '\\n';\n    cout << ansX1 << ' ' << ansY2 << '\\n';\n\n    return 0;\n}","ahc040":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct SplitMix64 {\n    uint64_t x;\n    explicit SplitMix64(uint64_t seed) : x(seed) {}\n    uint64_t next_u64() {\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 next_int(int l, int r) {\n        return l + (int)(next_u64() % (uint64_t)(r - l + 1));\n    }\n    double next_double() {\n        // [0,1)\n        return (next_u64() >> 11) * (1.0 / 9007199254740992.0);\n    }\n};\n\nstatic inline vector<int> bestRotForRowChain(const vector<long long>& wprime,\n                                              const vector<long long>& hprime) {\n    int N = (int)wprime.size();\n    // orientation 0: (w=w', h=h')\n    // orientation 1: (w=h', h=w')\n    vector<long long> h0(N), w0(N), h1(N), w1(N);\n    for (int i = 0; i < N; i++) {\n        w0[i] = wprime[i];\n        h0[i] = hprime[i];\n        w1[i] = hprime[i];\n        h1[i] = wprime[i];\n    }\n\n    vector<long long> cand;\n    cand.reserve(2 * N);\n    for (int i = 0; i < N; i++) {\n        cand.push_back(h0[i]);\n        cand.push_back(h1[i]);\n    }\n    sort(cand.begin(), cand.end());\n    cand.erase(unique(cand.begin(), cand.end()), cand.end());\n\n    const long long INF = (1LL << 62);\n    long long bestObj = INF;\n    long long bestTh = cand[0];\n\n    for (long long th : cand) {\n        long long sumW = 0;\n        bool ok = true;\n        for (int i = 0; i < N; i++) {\n            long long bestW = INF;\n            if (h0[i] <= th) bestW = min(bestW, w0[i]);\n            if (h1[i] <= th) bestW = min(bestW, w1[i]);\n            if (bestW == INF) { ok = false; break; }\n            sumW += bestW;\n        }\n        if (!ok) continue;\n        long long obj = sumW + th; // W + H upper-bounded by this th\n        if (obj < bestObj) {\n            bestObj = obj;\n            bestTh = th;\n        }\n    }\n\n    vector<int> rot(N, 0);\n    for (int i = 0; i < N; i++) {\n        long long bestW = INF;\n        int bestR = 0;\n        if (h0[i] <= bestTh) {\n            bestW = w0[i];\n            bestR = 0;\n        }\n        if (h1[i] <= bestTh) {\n            if (w1[i] < bestW) {\n                bestW = w1[i];\n                bestR = 1;\n            }\n        }\n        rot[i] = bestR;\n    }\n    return rot;\n}\n\nstatic inline vector<int> bestRotForColChain(const vector<long long>& wprime,\n                                              const vector<long long>& hprime) {\n    int N = (int)wprime.size();\n    // orientation 0: (w=w', h=h')\n    // orientation 1: (w=h', h=w')\n    vector<long long> h0(N), w0(N), h1(N), w1(N);\n    for (int i = 0; i < N; i++) {\n        w0[i] = wprime[i];\n        h0[i] = hprime[i];\n        w1[i] = hprime[i];\n        h1[i] = wprime[i];\n    }\n\n    vector<long long> cand;\n    cand.reserve(2 * N);\n    for (int i = 0; i < N; i++) {\n        cand.push_back(w0[i]);\n        cand.push_back(w1[i]);\n    }\n    sort(cand.begin(), cand.end());\n    cand.erase(unique(cand.begin(), cand.end()), cand.end());\n\n    const long long INF = (1LL << 62);\n    long long bestObj = INF;\n    long long bestTh = cand[0];\n\n    for (long long th : cand) {\n        long long sumH = 0;\n        bool ok = true;\n        for (int i = 0; i < N; i++) {\n            long long bestH = INF;\n            if (w0[i] <= th) bestH = min(bestH, h0[i]);\n            if (w1[i] <= th) bestH = min(bestH, h1[i]);\n            if (bestH == INF) { ok = false; break; }\n            sumH += bestH;\n        }\n        if (!ok) continue;\n        long long obj = sumH + th; // H + W upper-bounded by this th\n        if (obj < bestObj) {\n            bestObj = obj;\n            bestTh = th;\n        }\n    }\n\n    vector<int> rot(N, 0);\n    for (int i = 0; i < N; i++) {\n        long long bestH = INF;\n        int bestR = 0;\n        if (w0[i] <= bestTh) {\n            bestH = h0[i];\n            bestR = 0;\n        }\n        if (w1[i] <= bestTh) {\n            if (h1[i] < bestH) {\n                bestH = h1[i];\n                bestR = 1;\n            }\n        }\n        rot[i] = bestR;\n    }\n    return rot;\n}\n\nstatic inline long long predictedRowObj(const vector<long long>& wprime,\n                                          const vector<long long>& hprime,\n                                          const vector<int>& rot) {\n    long long W = 0;\n    long long H = 0;\n    int N = (int)wprime.size();\n    for (int i = 0; i < N; i++) {\n        if (rot[i] == 0) {\n            W += wprime[i];\n            H = max(H, hprime[i]);\n        } else {\n            W += hprime[i];\n            H = max(H, wprime[i]);\n        }\n    }\n    return W + H;\n}\n\nstatic inline long long predictedColObj(const vector<long long>& wprime,\n                                          const vector<long long>& hprime,\n                                          const vector<int>& rot) {\n    long long W = 0;\n    long long H = 0;\n    int N = (int)wprime.size();\n    for (int i = 0; i < N; i++) {\n        if (rot[i] == 0) {\n            W = max(W, wprime[i]);\n            H += hprime[i];\n        } else {\n            W = max(W, hprime[i]);\n            H += wprime[i];\n        }\n    }\n    return W + H;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, T;\n    long long sigma;\n    cin >> N >> T >> sigma;\n    vector<long long> wprime(N), hprime(N);\n    for (int i = 0; i < N; i++) cin >> wprime[i] >> hprime[i];\n\n    // Seed from input content for determinism per test instance.\n    uint64_t seed = 88172645463325252ULL;\n    for (int i = 0; i < N; i++) {\n        seed ^= (uint64_t)(wprime[i] + 1000003LL * hprime[i] + (i + 1) * 10007LL);\n        seed *= 1099511628211ULL;\n    }\n    seed ^= (uint64_t)N * 10000019ULL ^ (uint64_t)T * 1000003ULL ^ (uint64_t)sigma;\n    SplitMix64 rng(seed);\n\n    auto rotRow = bestRotForRowChain(wprime, hprime);\n    auto rotCol = bestRotForColChain(wprime, hprime);\n\n    long long predRow = predictedRowObj(wprime, hprime, rotRow);\n    long long predCol = predictedColObj(wprime, hprime, rotCol);\n\n    vector<char> dirRow(N, 'U');\n    vector<char> dirCol(N, 'L');\n\n    vector<char> bestDir;\n    vector<int> bestRot;\n\n    // Candidate list for the first few turns.\n    vector<pair<vector<char>, vector<int>>> initial;\n    initial.reserve(10);\n\n    if (predRow <= predCol) initial.push_back({dirRow, rotRow});\n    else initial.push_back({dirCol, rotCol});\n    if (predRow <= predCol) initial.push_back({dirCol, rotCol});\n    else initial.push_back({dirRow, rotRow});\n\n    auto chooseRotByDir = [&](int i, char d) -> int {\n        // d='U' -> try minimize width; d='L' -> try minimize height\n        long long w0 = wprime[i], h0 = hprime[i];\n        long long w1 = hprime[i], h1 = wprime[i];\n        if (d == 'U') {\n            return (w1 < w0) ? 1 : 0;\n        } else {\n            return (h1 < h0) ? 1 : 0;\n        }\n    };\n\n    int initExtra = min(T, 6) - (int)initial.size();\n    for (int k = 0; k < initExtra; k++) {\n        vector<char> dir(N);\n        vector<int> rot(N);\n        for (int i = 0; i < N; i++) {\n            dir[i] = (rng.next_int(0, 1) == 0 ? 'U' : 'L');\n            rot[i] = chooseRotByDir(i, dir[i]);\n            if (rng.next_int(0, 99) < 25) rot[i] ^= 1; // some randomness\n        }\n        initial.push_back({dir, rot});\n    }\n\n    auto buildOutput = [&](const vector<char>& dir, const vector<int>& rot) -> string {\n        string out;\n        out.reserve((size_t)N * 20);\n        out += to_string(N);\n        out += '\\n';\n        for (int i = 0; i < N; i++) {\n            out += to_string(i);\n            out += ' ';\n            out += to_string(rot[i]);\n            out += ' ';\n            out += dir[i];\n            out += ' ';\n            out += to_string(i == 0 ? -1 : i - 1);\n            out += '\\n';\n        }\n        return out;\n    };\n\n    long long bestMeas = (1LL << 62);\n    bool hasBest = false;\n\n    vector<char> currentDir, baseDir;\n    vector<int> currentRot, baseRot;\n\n    for (int t = 0; t < T; t++) {\n        vector<char> dir;\n        vector<int> rot;\n\n        if (t < (int)initial.size()) {\n            dir = initial[t].first;\n            rot = initial[t].second;\n        } else {\n            // Mutate around best; occasional mutation around the two baselines to avoid stagnation.\n            int pick = rng.next_int(0, 9);\n            if (!hasBest) {\n                dir = dirRow;\n                rot = rotRow;\n            } else if (pick == 0) {\n                dir = dirCol;\n                rot = rotCol;\n            } else if (pick <= 2) {\n                dir = dirRow;\n                rot = rotRow;\n            } else {\n                dir = bestDir;\n                rot = bestRot;\n            }\n\n            int m = (t < T / 3 ? 2 : 1);\n            for (int rep = 0; rep < m; rep++) {\n                int i = rng.next_int(0, N - 1);\n                if (rng.next_int(0, 1) == 0) {\n                    // flip direction\n                    dir[i] = (dir[i] == 'U' ? 'L' : 'U');\n                    if (rng.next_int(0, 99) < 70) {\n                        rot[i] = chooseRotByDir(i, dir[i]);\n                    }\n                } else {\n                    // flip rotation\n                    rot[i] ^= 1;\n                    if (rng.next_int(0, 99) < 30) {\n                        rot[i] = chooseRotByDir(i, dir[i]);\n                    }\n                }\n            }\n        }\n\n        cout << buildOutput(dir, rot) << flush;\n\n        long long Wm, Hm;\n        cin >> Wm >> Hm;\n        long long meas = Wm + Hm;\n\n        if (!hasBest || meas < bestMeas) {\n            hasBest = true;\n            bestMeas = meas;\n            bestDir = dir;\n            bestRot = rot;\n        }\n    }\n\n    return 0;\n}","ahc041":"#include <bits/stdc++.h>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, H;\n    cin >> N >> M >> H;\n    vector<long long> A(N);\n    for (int i = 0; i < N; i++) cin >> A[i];\n\n    vector<vector<int>> g(N);\n    for (int i = 0; i < M; i++) {\n        int u, v;\n        cin >> u >> v;\n        g[u].push_back(v);\n        g[v].push_back(u);\n    }\n    // coordinates are irrelevant for this heuristic\n    for (int i = 0; i < N; i++) {\n        int x, y;\n        cin >> x >> y;\n    }\n\n    using Clock = chrono::steady_clock;\n    auto t0 = Clock::now();\n    const double TL = 1.85; // seconds (safety margin)\n\n    mt19937 rng((uint32_t)chrono::steady_clock::now().time_since_epoch().count());\n\n    vector<int> bestParent(N, -1);\n    long long bestScore = LLONG_MIN;\n\n    vector<char> assigned(N);\n    vector<int> parent(N), depthv(N);\n\n    // Reusable BFS helpers\n    vector<int> seen(N, 0), dist(N, 0);\n    int timer = 1;\n\n    auto eval_component_score = [&](int s) -> long long {\n        // BFS inside currently-unassigned vertices only (including s)\n        timer++;\n        queue<int> q;\n        seen[s] = timer;\n        dist[s] = 0;\n        long long score = A[s]; // (0+1)*A[s]\n        q.push(s);\n\n        while (!q.empty()) {\n            int x = q.front(); q.pop();\n            int dx = dist[x];\n            if (dx == H) continue;\n            for (int y : g[x]) {\n                if (assigned[y]) continue; // blocked by already assigned vertices\n                if (seen[y] == timer) continue;\n                seen[y] = timer;\n                dist[y] = dx + 1;\n                score += (long long)(dist[y] + 1) * A[y];\n                q.push(y);\n            }\n        }\n        return score;\n    };\n\n    auto claim_component = [&](int s) {\n        // Build BFS tree from s in the induced subgraph of unassigned vertices\n        queue<int> q;\n        assigned[s] = 1;\n        parent[s] = -1;\n        depthv[s] = 0;\n        q.push(s);\n\n        while (!q.empty()) {\n            int x = q.front(); q.pop();\n            if (depthv[x] == H) continue;\n            for (int y : g[x]) {\n                if (!assigned[y]) {\n                    assigned[y] = 1;\n                    parent[y] = x;\n                    depthv[y] = depthv[x] + 1;\n                    q.push(y);\n                }\n            }\n        }\n    };\n\n    int attempts = 8;\n    for (int it = 0; it < attempts; it++) {\n        double elapsed = chrono::duration<double>(Clock::now() - t0).count();\n        if (elapsed > TL) break;\n\n        fill(assigned.begin(), assigned.end(), 0);\n        vector<int> curParent(N, -1);\n        vector<int> curDepth(N, -1);\n\n        long long totalScore = 0;\n\n        // Greedy forest construction\n        while (true) {\n            int start = -1;\n            // collect unassigned\n            int unassigned_cnt = 0;\n            for (int i = 0; i < N; i++) if (!assigned[i]) unassigned_cnt++;\n            if (unassigned_cnt == 0) break;\n\n            // find min-A unassigned vertex (always include it)\n            long long minA = (1LL<<60);\n            int minv = -1;\n            for (int i = 0; i < N; i++) {\n                if (!assigned[i] && A[i] < minA) {\n                    minA = A[i];\n                    minv = i;\n                }\n            }\n\n            // sample candidates\n            const int KCAND = 10;\n            vector<int> unassigned_list;\n            unassigned_list.reserve(unassigned_cnt);\n            for (int i = 0; i < N; i++) if (!assigned[i]) unassigned_list.push_back(i);\n\n            int K = min(KCAND, (int)unassigned_list.size());\n            vector<int> cands;\n            cands.push_back(minv);\n\n            // random distinct samples\n            uniform_int_distribution<int> distIdx(0, (int)unassigned_list.size() - 1);\n            unordered_set<int> used;\n            used.reserve(K * 2);\n            used.insert(minv);\n\n            while ((int)cands.size() < K) {\n                int v = unassigned_list[distIdx(rng)];\n                if (!used.count(v)) {\n                    used.insert(v);\n                    cands.push_back(v);\n                }\n            }\n\n            // choose best candidate by exact component score (within remaining unassigned subgraph)\n            long long bestCandScore = LLONG_MIN;\n            int bestCand = -1;\n            for (int c : cands) {\n                long long sc = eval_component_score(c);\n                if (sc > bestCandScore) {\n                    bestCandScore = sc;\n                    bestCand = c;\n                } else if (sc == bestCandScore) {\n                    // tie-break: smaller A (shallower root for good vertices), then random\n                    if (A[c] < A[bestCand] || (A[c] == A[bestCand] && (rng() & 1))) {\n                        bestCand = c;\n                    }\n                }\n            }\n\n            // Claim that component and add its attractiveness\n            // (We can reuse eval_component_score(bestCand) for exact score as well)\n            long long compScore = eval_component_score(bestCand);\n\n            // Apply BFS claim\n            // We need to write into curParent/curDepth\n            // temporarily use global parent/depthv\n            // (to keep code simple, claim_component writes into parent/depthv/assigned)\n            // First, map global parent/depthv into cur arrays after claim.\n            claim_component(bestCand);\n\n            for (int i = 0; i < N; i++) {\n                if (assigned[i]) { // assigned can only grow; but we need to copy newly assigned nodes.\n                    // Avoid O(N) copying each iteration by copying after BFS would be better,\n                    // but N=1000, iterations are limited; still fine.\n                    curParent[i] = parent[i];\n                    curDepth[i] = depthv[i];\n                }\n            }\n            totalScore += compScore;\n        }\n\n        if (totalScore > bestScore) {\n            bestScore = totalScore;\n            // Ensure bestParent is filled from the last attempt's curParent\n            // We must output a forest for all vertices; curParent has values for assigned vertices.\n            // Copy curParent into bestParent (curParent is already for full N at end).\n            // For correctness, just rebuild by running a final claim is unnecessary;\n            // curParent is maintained for assigned vertices; by the end all vertices are assigned.\n            // So copy.\n            // Note: curParent wasn't stored outside loop scope; reconstruct by running again would be redundant.\n            // We'll just re-run the attempt? Instead, store curParent/best immediately in the loop.\n        }\n    }\n\n    // The loop above updates bestScore but doesn't store bestParent due to scope.\n    // Re-run once more but this time keep best forest explicitly.\n    // (Still fast enough.)\n    bestScore = LLONG_MIN;\n    mt19937 rng2((uint32_t)chrono::steady_clock::now().time_since_epoch().count() ^ 0x9e3779b9);\n\n    for (int it = 0; it < attempts; it++) {\n        double elapsed = chrono::duration<double>(Clock::now() - t0).count();\n        if (elapsed > TL) break;\n\n        fill(assigned.begin(), assigned.end(), 0);\n        vector<int> curParent(N, -1);\n        vector<int> curDepth(N, -1);\n\n        long long totalScore = 0;\n\n        while (true) {\n            int unassigned_cnt = 0;\n            for (int i = 0; i < N; i++) if (!assigned[i]) unassigned_cnt++;\n            if (unassigned_cnt == 0) break;\n\n            long long minA = (1LL<<60);\n            int minv = -1;\n            for (int i = 0; i < N; i++) {\n                if (!assigned[i] && A[i] < minA) {\n                    minA = A[i];\n                    minv = i;\n                }\n            }\n\n            const int KCAND = 10;\n            vector<int> unassigned_list;\n            unassigned_list.reserve(unassigned_cnt);\n            for (int i = 0; i < N; i++) if (!assigned[i]) unassigned_list.push_back(i);\n\n            int K = min(KCAND, (int)unassigned_list.size());\n            vector<int> cands;\n            cands.push_back(minv);\n\n            unordered_set<int> used;\n            used.reserve(K * 2);\n            used.insert(minv);\n\n            uniform_int_distribution<int> distIdx(0, (int)unassigned_list.size() - 1);\n            while ((int)cands.size() < K) {\n                int v = unassigned_list[distIdx(rng2)];\n                if (!used.count(v)) {\n                    used.insert(v);\n                    cands.push_back(v);\n                }\n            }\n\n            long long bestCandScore = LLONG_MIN;\n            int bestCand = -1;\n            for (int c : cands) {\n                long long sc = eval_component_score(c);\n                if (sc > bestCandScore) {\n                    bestCandScore = sc;\n                    bestCand = c;\n                } else if (sc == bestCandScore) {\n                    if (A[c] < A[bestCand] || (A[c] == A[bestCand] && (rng2() & 1))) {\n                        bestCand = c;\n                    }\n                }\n            }\n\n            long long compScore = eval_component_score(bestCand);\n            claim_component(bestCand);\n\n            // Copy newly assigned nodes into curParent/curDepth\n            for (int i = 0; i < N; i++) {\n                if (assigned[i]) {\n                    curParent[i] = parent[i];\n                    curDepth[i] = depthv[i];\n                }\n            }\n            totalScore += compScore;\n        }\n\n        if (totalScore > bestScore) {\n            bestScore = totalScore;\n            bestParent = curParent;\n        }\n    }\n\n    // Output parent pointers\n    for (int i = 0; i < N; i++) {\n        cout << bestParent[i] << (i + 1 == N ? '\\n' : ' ');\n    }\n    return 0;\n}","ahc042":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int INF = 1e9;\n\nstruct Candidate {\n    vector<int> upLen, downLen, leftLen, rightLen;\n    long long T = (1LL<<60);\n    bool covered = false;\n};\n\nstruct OniCell {\n    int r, c;\n};\n\nenum Dir { UP=0, DOWN=1, LEFT=2, RIGHT=3 };\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<vector<char>> fuku(N, vector<char>(N, 0));\n    vector<OniCell> oni;\n    oni.reserve(2*N);\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (C[i][j] == 'o') fuku[i][j] = 1;\n            else if (C[i][j] == 'x') {\n                oniId[i][j] = (int)oni.size();\n                oni.push_back({i,j});\n            }\n        }\n    }\n\n    int M = (int)oni.size(); // should be 2N\n    // Precompute max safe lengths for each line-direction.\n    // upLen[j] can be at most number of rows before first fuku in column j.\n    // downLen[j] can be at most number of rows after last fuku in column j.\n    vector<int> maxUp(N), maxDown(N), maxLeft(N), maxRight(N);\n\n    for (int j = 0; j < N; j++) {\n        int first = N, last = -1;\n        for (int i = 0; i < N; i++) {\n            if (fuku[i][j]) {\n                first = min(first, i);\n                last = max(last, i);\n            }\n        }\n        maxUp[j] = first; // L <= first\n        maxDown[j] = (last == -1 ? N : (N - 1 - last)); // L <= N-1-last\n    }\n    for (int i = 0; i < N; i++) {\n        int first = N, last = -1;\n        for (int j = 0; j < N; j++) {\n            if (fuku[i][j]) {\n                first = min(first, j);\n                last = max(last, j);\n            }\n        }\n        maxLeft[i] = first; // L <= first\n        maxRight[i] = (last == -1 ? N : (N - 1 - last)); // L <= N-1-last\n    }\n\n    auto allCovered = [&](const Candidate& cand) -> bool {\n        for (int id = 0; id < M; id++) {\n            int i = oni[id].r, j = oni[id].c;\n            bool ok =\n                (i < cand.upLen[j]) ||\n                (i >= N - cand.downLen[j]) ||\n                (j < cand.leftLen[i]) ||\n                (j >= N - cand.rightLen[i]);\n            if (!ok) return false;\n        }\n        return true;\n    };\n\n    auto computeT = [&](const Candidate& cand) -> long long {\n        long long sum = 0;\n        for (int j = 0; j < N; j++) sum += cand.upLen[j] + cand.downLen[j];\n        for (int i = 0; i < N; i++) sum += cand.leftLen[i] + cand.rightLen[i];\n        return 2LL * sum;\n    };\n\n    auto prune = [&](Candidate cand, const vector<int>& orderUpDownLeftRight) -> Candidate {\n        // Local pruning: repeatedly try to decrease each variable by 1 if coverage remains.\n        // orderUpDownLeftRight encodes which variable index to try:\n        //   0..N-1: UP col\n        //   N..2N-1: DOWN col\n        //   2N..3N-1: LEFT row\n        //   3N..4N-1: RIGHT row\n        bool changed = true;\n        while (changed) {\n            changed = false;\n            for (int idx : orderUpDownLeftRight) {\n                auto canSet = [&](int newLen) -> bool {\n                    int before = newLen + 0; (void)before;\n                    // set temporarily and check coverage\n                    Candidate tmp = cand;\n                    int d = idx / N;\n                    int pos = idx % N;\n                    if (d == 0) tmp.upLen[pos] = newLen;\n                    else if (d == 1) tmp.downLen[pos] = newLen;\n                    else if (d == 2) tmp.leftLen[pos] = newLen;\n                    else tmp.rightLen[pos] = newLen;\n                    return allCovered(tmp);\n                };\n\n                int d = idx / N;\n                int pos = idx % N;\n                int curLen = 0;\n                if (d == 0) curLen = cand.upLen[pos];\n                else if (d == 1) curLen = cand.downLen[pos];\n                else if (d == 2) curLen = cand.leftLen[pos];\n                else curLen = cand.rightLen[pos];\n\n                while (curLen > 0) {\n                    int newLen = curLen - 1;\n                    if (!canSet(newLen)) break;\n                    curLen = newLen;\n                    if (d == 0) cand.upLen[pos] = newLen;\n                    else if (d == 1) cand.downLen[pos] = newLen;\n                    else if (d == 2) cand.leftLen[pos] = newLen;\n                    else cand.rightLen[pos] = newLen;\n                    changed = true;\n                }\n            }\n        }\n        cand.T = computeT(cand);\n        cand.covered = allCovered(cand);\n        return cand;\n    };\n\n    // Baseline: for each Oni, pick cheapest safe direction; then group by maximum required length.\n    auto baselineCandidate = [&]() -> Candidate {\n        Candidate cand;\n        cand.upLen.assign(N, 0);\n        cand.downLen.assign(N, 0);\n        cand.leftLen.assign(N, 0);\n        cand.rightLen.assign(N, 0);\n\n        for (int id = 0; id < M; id++) {\n            int i = oni[id].r, j = oni[id].c;\n            // required lengths\n            int reqU = (i+1 <= maxUp[j] ? i+1 : INF);\n            int reqD = (N-i <= maxDown[j] ? (N-i) : INF);\n            int reqL = (j+1 <= maxLeft[i] ? (j+1) : INF);\n            int reqR = (N-j <= maxRight[i] ? (N-j) : INF);\n\n            int best = min({reqU, reqD, reqL, reqR});\n            if (best == INF) {\n                // Should never happen due to guarantee.\n                // Fallback: do nothing here.\n                continue;\n            }\n            // tie-break order: U, D, L, R\n            if (reqU == best) cand.upLen[j] = max(cand.upLen[j], reqU);\n            else if (reqD == best) cand.downLen[j] = max(cand.downLen[j], reqD);\n            else if (reqL == best) cand.leftLen[i] = max(cand.leftLen[i], reqL);\n            else cand.rightLen[i] = max(cand.rightLen[i], reqR);\n        }\n\n        cand.T = computeT(cand);\n        cand.covered = allCovered(cand);\n        // Prune with a fixed order\n        vector<int> order;\n        order.reserve(4*N);\n        for (int idx = 0; idx < 4*N; idx++) order.push_back(idx);\n        cand = prune(cand, order);\n        return cand;\n    };\n\n    auto greedyAttempt = [&](int variant, std::mt19937& rng) -> Candidate {\n        // variant controls evaluation; all greedy attempts end with pruning.\n        vector<int> upLen(N,0), downLen(N,0), leftLen(N,0), rightLen(N,0);\n        vector<char> covered(M, 0);\n        int uncovered = M;\n\n        auto curLen = [&](Dir dir, int line) -> int {\n            if (dir == UP) return upLen[line];\n            if (dir == DOWN) return downLen[line];\n            if (dir == LEFT) return leftLen[line];\n            return rightLen[line];\n        };\n        auto& lenRef = [&](Dir dir, int line) -> int& {\n            if (dir == UP) return upLen[line];\n            if (dir == DOWN) return downLen[line];\n            if (dir == LEFT) return leftLen[line];\n            return rightLen[line];\n        };\n\n        auto computeGain = [&](Dir dir, int line, int newLen, int cur) -> int {\n            // gain = number of uncovered Oni newly removed by increasing cur -> newLen\n            int gain = 0;\n            if (cur == newLen) return 0;\n\n            if (dir == UP) {\n                int j = line;\n                for (int r = cur; r < newLen; r++) {\n                    int id = oniId[r][j];\n                    if (id != -1 && !covered[id]) gain++;\n                }\n            } else if (dir == DOWN) {\n                int j = line;\n                // newly included rows: [N-newLen, N-cur-1]\n                for (int r = N - newLen; r < N - cur; r++) {\n                    int id = oniId[r][j];\n                    if (id != -1 && !covered[id]) gain++;\n                }\n            } else if (dir == LEFT) {\n                int i = line;\n                for (int c = cur; c < newLen; c++) {\n                    int id = oniId[i][c];\n                    if (id != -1 && !covered[id]) gain++;\n                }\n            } else { // RIGHT\n                int i = line;\n                for (int c = N - newLen; c < N - cur; c++) {\n                    int id = oniId[i][c];\n                    if (id != -1 && !covered[id]) gain++;\n                }\n            }\n            return gain;\n        };\n\n        auto applyExtend = [&](Dir dir, int line, int newLen) {\n            int cur = curLen(dir, line);\n            if (newLen <= cur) return;\n            // Mark all newly covered Oni\n            if (dir == UP) {\n                int j = line;\n                for (int r = cur; r < newLen; r++) {\n                    int id = oniId[r][j];\n                    if (id != -1 && !covered[id]) {\n                        covered[id] = 1;\n                        uncovered--;\n                    }\n                }\n            } else if (dir == DOWN) {\n                int j = line;\n                for (int r = N - newLen; r < N - cur; r++) {\n                    int id = oniId[r][j];\n                    if (id != -1 && !covered[id]) {\n                        covered[id] = 1;\n                        uncovered--;\n                    }\n                }\n            } else if (dir == LEFT) {\n                int i = line;\n                for (int c = cur; c < newLen; c++) {\n                    int id = oniId[i][c];\n                    if (id != -1 && !covered[id]) {\n                        covered[id] = 1;\n                        uncovered--;\n                    }\n                }\n            } else {\n                int i = line;\n                for (int c = N - newLen; c < N - cur; c++) {\n                    int id = oniId[i][c];\n                    if (id != -1 && !covered[id]) {\n                        covered[id] = 1;\n                        uncovered--;\n                    }\n                }\n            }\n            lenRef(dir, line) = newLen;\n        };\n\n        struct Action {\n            Dir dir;\n            int line;\n            int req;\n            int gain;\n            long long costInc;\n            long double val;\n        };\n\n        while (uncovered > 0) {\n            long double bestVal = -1e100;\n            long long bestCost = (1LL<<60);\n            vector<Action> ties;\n\n            for (int id = 0; id < M; id++) {\n                if (covered[id]) continue;\n                int i = oni[id].r, j = oni[id].c;\n\n                // UP: req = i+1\n                {\n                    int req = i + 1;\n                    int cur = upLen[j];\n                    if (req <= maxUp[j] && cur < req) {\n                        int gain = computeGain(UP, j, req, cur);\n                        long long costInc = 2LL * (req - cur);\n                        long double val;\n                        if (variant == 0) val = (long double)gain / (long double)costInc;\n                        else if (variant == 1) val = (long double)gain * 1000.0L - (long double)costInc;\n                        else val = (long double)gain * gain / (long double)costInc;\n                        Action a{UP, j, req, gain, costInc, val};\n                        if (val > bestVal + 1e-15L) {\n                            bestVal = val;\n                            bestCost = costInc;\n                            ties.clear();\n                            ties.push_back(a);\n                        } else if (fabsl(val - bestVal) <= 1e-15L) {\n                            if (costInc < bestCost) {\n                                bestCost = costInc;\n                                ties.clear();\n                                ties.push_back(a);\n                            } else if (costInc == bestCost) {\n                                ties.push_back(a);\n                            } else {\n                                ties.push_back(a); // keep; tie list will be pruned by random pick\n                            }\n                        }\n                    }\n                }\n                // DOWN: req = N-i\n                {\n                    int req = N - i;\n                    int cur = downLen[j];\n                    if (req <= maxDown[j] && cur < req) {\n                        int gain = computeGain(DOWN, j, req, cur);\n                        long long costInc = 2LL * (req - cur);\n                        long double val;\n                        if (variant == 0) val = (long double)gain / (long double)costInc;\n                        else if (variant == 1) val = (long double)gain * 1000.0L - (long double)costInc;\n                        else val = (long double)gain * gain / (long double)costInc;\n                        Action a{DOWN, j, req, gain, costInc, val};\n                        if (val > bestVal + 1e-15L) {\n                            bestVal = val;\n                            bestCost = costInc;\n                            ties.clear();\n                            ties.push_back(a);\n                        } else if (fabsl(val - bestVal) <= 1e-15L) {\n                            if (costInc < bestCost) {\n                                bestCost = costInc;\n                                ties.clear();\n                                ties.push_back(a);\n                            } else if (costInc == bestCost) {\n                                ties.push_back(a);\n                            } else {\n                                ties.push_back(a);\n                            }\n                        }\n                    }\n                }\n                // LEFT: req = j+1\n                {\n                    int req = j + 1;\n                    int cur = leftLen[i];\n                    if (req <= maxLeft[i] && cur < req) {\n                        int gain = computeGain(LEFT, i, req, cur);\n                        long long costInc = 2LL * (req - cur);\n                        long double val;\n                        if (variant == 0) val = (long double)gain / (long double)costInc;\n                        else if (variant == 1) val = (long double)gain * 1000.0L - (long double)costInc;\n                        else val = (long double)gain * gain / (long double)costInc;\n                        Action a{LEFT, i, req, gain, costInc, val};\n                        if (val > bestVal + 1e-15L) {\n                            bestVal = val;\n                            bestCost = costInc;\n                            ties.clear();\n                            ties.push_back(a);\n                        } else if (fabsl(val - bestVal) <= 1e-15L) {\n                            if (costInc < bestCost) {\n                                bestCost = costInc;\n                                ties.clear();\n                                ties.push_back(a);\n                            } else if (costInc == bestCost) {\n                                ties.push_back(a);\n                            } else {\n                                ties.push_back(a);\n                            }\n                        }\n                    }\n                }\n                // RIGHT: req = N-j\n                {\n                    int req = N - j;\n                    int cur = rightLen[i];\n                    if (req <= maxRight[i] && cur < req) {\n                        int gain = computeGain(RIGHT, i, req, cur);\n                        long long costInc = 2LL * (req - cur);\n                        long double val;\n                        if (variant == 0) val = (long double)gain / (long double)costInc;\n                        else if (variant == 1) val = (long double)gain * 1000.0L - (long double)costInc;\n                        else val = (long double)gain * gain / (long double)costInc;\n                        Action a{RIGHT, i, req, gain, costInc, val};\n                        if (val > bestVal + 1e-15L) {\n                            bestVal = val;\n                            bestCost = costInc;\n                            ties.clear();\n                            ties.push_back(a);\n                        } else if (fabsl(val - bestVal) <= 1e-15L) {\n                            if (costInc < bestCost) {\n                                bestCost = costInc;\n                                ties.clear();\n                                ties.push_back(a);\n                            } else if (costInc == bestCost) {\n                                ties.push_back(a);\n                            } else {\n                                ties.push_back(a);\n                            }\n                        }\n                    }\n                }\n            }\n\n            // Choose among ties\n            Action chosen = ties[0];\n            if (!ties.empty()) {\n                if (variant == 0) {\n                    // random among best-value ties\n                    std::uniform_int_distribution<int> dist(0, (int)ties.size()-1);\n                    chosen = ties[dist(rng)];\n                } else {\n                    // deterministic: smallest costInc then largest gain\n                    chosen = *min_element(ties.begin(), ties.end(), [&](const Action& a, const Action& b){\n                        if (a.costInc != b.costInc) return a.costInc < b.costInc;\n                        if (a.gain != b.gain) return a.gain > b.gain;\n                        return a.req < b.req;\n                    });\n                }\n            }\n            applyExtend(chosen.dir, chosen.line, chosen.req);\n        }\n\n        Candidate cand;\n        cand.upLen = upLen;\n        cand.downLen = downLen;\n        cand.leftLen = leftLen;\n        cand.rightLen = rightLen;\n        cand.T = computeT(cand);\n        cand.covered = allCovered(cand);\n\n        // prune\n        vector<int> order;\n        order.reserve(4*N);\n        // fixed order for stability\n        for (int idx = 0; idx < 4*N; idx++) order.push_back(idx);\n        cand = prune(cand, order);\n        return cand;\n    };\n\n    Candidate best = baselineCandidate();\n\n    // Greedy attempts (bounded)\n    // N=20 => T limit is 1600, baseline should already be feasible, but we still improve score.\n    auto tryGreedy = [&](int variant, int tries) {\n        std::mt19937 rng(1234567 + variant*1000);\n        for (int t = 0; t < tries; t++) {\n            Candidate cand = greedyAttempt(variant, rng);\n            long long Tlimit = 4LL * N * N;\n            if (!cand.covered) continue;\n            if (cand.T > Tlimit) continue;\n            if (cand.T < best.T) best = cand;\n            // advance RNG\n            rng();\n        }\n    };\n\n    tryGreedy(0, 18);\n    tryGreedy(1, 6);\n    tryGreedy(2, 6);\n\n    // Output operations according to best lengths.\n    // Ensure within limit\n    long long Tlimit = 4LL * N * N;\n    if (!best.covered || best.T > Tlimit) {\n        // This should not happen; baseline should always be feasible.\n        // As a last resort, just output baseline without further pruning (but we already pruned).\n        best = baselineCandidate();\n    }\n\n    vector<pair<char,int>> ops;\n    ops.reserve((size_t)best.T);\n\n    for (int j = 0; j < N; j++) {\n        int L = best.upLen[j];\n        if (L > 0) {\n            for (int k = 0; k < L; k++) ops.push_back({'U', j});\n            for (int k = 0; k < L; k++) ops.push_back({'D', j});\n        }\n        int R = best.downLen[j];\n        if (R > 0) {\n            for (int k = 0; k < R; k++) ops.push_back({'D', j});\n            for (int k = 0; k < R; k++) ops.push_back({'U', j});\n        }\n    }\n    for (int i = 0; i < N; i++) {\n        int L = best.leftLen[i];\n        if (L > 0) {\n            for (int k = 0; k < L; k++) ops.push_back({'L', i});\n            for (int k = 0; k < L; k++) ops.push_back({'R', i});\n        }\n        int R = best.rightLen[i];\n        if (R > 0) {\n            for (int k = 0; k < R; k++) ops.push_back({'R', i});\n            for (int k = 0; k < R; k++) ops.push_back({'L', i});\n        }\n    }\n\n    if ((long long)ops.size() > Tlimit) {\n        // Should not happen; but safeguard\n        ops.resize((size_t)Tlimit);\n    }\n\n    cout << ops.size() << \"\\n\";\n    for (auto &[ch, p] : ops) {\n        cout << ch << \" \" << p << \"\\n\";\n    }\n    return 0;\n}","ahc044":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int MAXN = 100;\nstatic constexpr int L_CONST = 500000;\n\nstruct State {\n    long long err;\n    array<int, MAXN> cnt{};\n    array<int, MAXN> oddUse{};\n    array<int, MAXN> evenUse{};\n};\n\nstatic inline long long calcErrFromCnt(const array<int, MAXN>& cnt, const array<int, MAXN>& T, int N) {\n    long long e = 0;\n    for (int i = 0; i < N; i++) e += llabs((long long)cnt[i] - (long long)T[i]);\n    return e;\n}\n\nstatic long long simulate(const vector<int>& a, const vector<int>& b,\n                           const array<int, MAXN>& T,\n                           int N, int L,\n                           State &st) {\n    st.cnt.fill(0);\n    st.oddUse.fill(0);\n    st.evenUse.fill(0);\n\n    int x = 0;\n    st.cnt[x] = 1;\n    for (int week = 2; week <= L; week++) {\n        if (st.cnt[x] & 1) {\n            st.oddUse[x]++;\n            x = a[x];\n        } else {\n            st.evenUse[x]++;\n            x = b[x];\n        }\n        st.cnt[x]++;\n    }\n    st.err = calcErrFromCnt(st.cnt, T, N);\n    return st.err;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, L;\n    cin >> N >> L;\n    array<int, MAXN> T{};\n    for (int i = 0; i < N; i++) cin >> T[i];\n\n    // RNG\n    mt19937_64 rng((uint64_t)chrono::high_resolution_clock::now().time_since_epoch().count());\n\n    // Choose destination using residual rem (bigger is more desirable).\n    auto chooseCandidate = [&](const vector<long long>& rem) -> int {\n        const int K = min(25, N);\n        vector<pair<long long,int>> v;\n        v.reserve(N);\n        for (int i = 0; i < N; i++) v.push_back({rem[i], i});\n        nth_element(v.begin(), v.begin() + K, v.end(),\n                    [&](auto &p, auto &q){ return p.first > q.first; });\n        v.resize(K);\n        long long mn = v[0].first, mx = v[0].first;\n        for (auto &p : v) { mn = min(mn, p.first); mx = max(mx, p.first); }\n        long long offset = -mn + 1; // make weights positive\n        vector<long long> w(K);\n        long long sumw = 0;\n        for (int i = 0; i < K; i++) {\n            w[i] = v[i].first + offset;\n            if (w[i] < 1) w[i] = 1;\n            sumw += w[i];\n        }\n        uniform_int_distribution<long long> dist(1, sumw);\n        long long r = dist(rng);\n        for (int i = 0; i < K; i++) {\n            if (r <= w[i]) return v[i].second;\n            r -= w[i];\n        }\n        return v.back().second;\n    };\n\n    // Randomized greedy constructor (similar spirit to yours, but slightly stronger).\n    auto buildMapping = [&](int seedOffset) -> pair<long long, pair<vector<int>, vector<int>>> {\n        // unique seed per build\n        // (We can't reseed rng globally safely; we'll just use it as-is and vary behavior via seedOffset.)\n        vector<int> a(N, -1), b(N, -1);\n        vector<long long> rem(N);\n        for (int i = 0; i < N; i++) rem[i] = T[i];\n\n        array<int, MAXN> cnt{};\n        cnt.fill(0);\n\n        int x = 0;\n        cnt[x] = 1;\n        rem[x]--;\n\n        for (int week = 2; week <= L; week++) {\n            if (cnt[x] & 1) {\n                if (a[x] == -1) {\n                    // small random perturbation by swapping a little preference\n                    int y = chooseCandidate(rem);\n                    if ((seedOffset + week) % 17 == 0) {\n                        // diversify: sometimes pick a random among top 10 by rem\n                        vector<pair<long long,int>> v;\n                        v.reserve(N);\n                        for (int i = 0; i < N; i++) v.push_back({rem[i], i});\n                        sort(v.begin(), v.end(), [&](auto &p, auto &q){ return p.first > q.first; });\n                        int R = min(10, N);\n                        uniform_int_distribution<int> d(0, R-1);\n                        y = v[d(rng)].second;\n                    }\n                    a[x] = y;\n                }\n                x = a[x];\n            } else {\n                if (b[x] == -1) {\n                    int y = chooseCandidate(rem);\n                    if ((seedOffset + week) % 23 == 0) {\n                        vector<pair<long long,int>> v;\n                        v.reserve(N);\n                        for (int i = 0; i < N; i++) v.push_back({rem[i], i});\n                        sort(v.begin(), v.end(), [&](auto &p, auto &q){ return p.first > q.first; });\n                        int R = min(10, N);\n                        uniform_int_distribution<int> d(0, R-1);\n                        y = v[d(rng)].second;\n                    }\n                    b[x] = y;\n                }\n                x = b[x];\n            }\n            cnt[x]++;\n            rem[x]--;\n        }\n\n        for (int i = 0; i < N; i++) {\n            if (a[i] == -1) a[i] = 0;\n            if (b[i] == -1) b[i] = 0;\n        }\n\n        State st;\n        long long err = simulate(a, b, T, N, L, st);\n        return {err, {std::move(a), std::move(b)}};\n    };\n\n    // Time control\n    using Clock = chrono::steady_clock;\n    auto start = Clock::now();\n    auto elapsed = [&]() -> double {\n        return chrono::duration<double>(Clock::now() - start).count();\n    };\n    const double TL = 1.95; // leave a bit of margin\n\n    long long bestErr = (1LL<<62);\n    vector<int> bestA(N, 0), bestB(N, 0);\n\n    // Initial restarts\n    for (int it = 0; it < 40 && elapsed() < TL * 0.35; it++) {\n        auto [err, ab] = buildMapping(it * 100 + 7);\n        if (err < bestErr) {\n            bestErr = err;\n            bestA = std::move(ab.first);\n            bestB = std::move(ab.second);\n        }\n    }\n\n    // Simulated annealing\n    vector<int> curA = bestA, curB = bestB;\n\n    State curSt, newSt;\n    long long curErr = simulate(curA, curB, T, N, L, curSt);\n    bestErr = min(bestErr, curErr);\n\n    // residual arrays (computed from curSt.cnt)\n    auto computeResidualOrder = [&](const State& st) {\n        vector<pair<int,int>> under; under.reserve(N);\n        vector<pair<int,int>> all; all.reserve(N);\n        for (int i = 0; i < N; i++) {\n            int r = T[i] - st.cnt[i];\n            all.push_back({abs(r), i});\n            if (r > 0) under.push_back({r, i});\n        }\n        sort(under.begin(), under.end(), [&](auto &p, auto &q){ return p.first > q.first; });\n        sort(all.begin(), all.end(), [&](auto &p, auto &q){ return p.first > q.first; });\n        return pair<vector<pair<int,int>>, vector<pair<int,int>>>(under, all);\n    };\n\n    vector<pair<int,int>> underList, allAbsList;\n\n    size_t iter = 0;\n    while (elapsed() < TL) {\n        iter++;\n\n        // compute residual lists occasionally\n        if ((iter & 3) == 1) {\n            auto lists = computeResidualOrder(curSt);\n            underList = std::move(lists.first);\n            allAbsList = std::move(lists.second);\n        }\n\n        // choose i with roulette on abs residual (approx)\n        int i = 0;\n        {\n            long long sumAbs = 0;\n            array<long long, MAXN> absw{};\n            for (int k = 0; k < N; k++) {\n                long long r = (long long)T[k] - (long long)curSt.cnt[k];\n                long long w = llabs(r);\n                absw[k] = w;\n                sumAbs += w;\n            }\n            if (sumAbs == 0) {\n                i = uniform_int_distribution<int>(0, N-1)(rng);\n            } else {\n                uniform_int_distribution<long long> dist(1, sumAbs);\n                long long r = dist(rng);\n                for (int k = 0; k < N; k++) {\n                    if (r <= absw[k]) { i = k; break; }\n                    r -= absw[k];\n                }\n            }\n        }\n\n        // choose which edge to modify (a[i] if oddUse dominates)\n        bool changeAedge = true;\n        int ou = curSt.oddUse[i];\n        int eu = curSt.evenUse[i];\n        if (ou + eu == 0) {\n            changeAedge = (uniform_int_distribution<int>(0,1)(rng) == 0);\n        } else {\n            long long r = (long long)uniform_int_distribution<int>(0, 1000000)(rng);\n            changeAedge = (r % (ou + eu) < ou);\n        }\n\n        // choose destination j among underrepresented (prefer positive residual)\n        int curDest = changeAedge ? curA[i] : curB[i];\n\n        int j = curDest;\n        if (!underList.empty()) {\n            int K = min(20, (int)underList.size());\n            // pick among top K with weights proportional to (need+1)\n            long long sumw = 0;\n            for (int t = 0; t < K; t++) sumw += (long long)underList[t].first + 1;\n            uniform_int_distribution<long long> dist(1, sumw);\n            long long r = dist(rng);\n            for (int t = 0; t < K; t++) {\n                long long w = (long long)underList[t].first + 1;\n                if (r <= w) { j = underList[t].second; break; }\n                r -= w;\n            }\n        } else {\n            // fallback: pick from top abs residual indices\n            int K = min(20, (int)allAbsList.size());\n            j = allAbsList[uniform_int_distribution<int>(0, K-1)(rng)].second;\n        }\n\n        // make sure it's actually a change if possible\n        if (N > 1 && j == curDest) {\n            j = (j + 1) % N;\n        }\n\n        // propose change\n        vector<int> aTry = curA;\n        vector<int> bTry = curB;\n\n        if (changeAedge) aTry[i] = j;\n        else bTry[i] = j;\n\n        // occasional double-edge move to escape\n        if (uniform_int_distribution<int>(0, 9)(rng) == 0) {\n            int i2 = allAbsList.empty() ? uniform_int_distribution<int>(0, N-1)(rng)\n                                        : allAbsList[uniform_int_distribution<int>(0, min(30, N)-1)(rng)].second;\n            bool changeA2 = (uniform_int_distribution<int>(0,1)(rng) == 0);\n\n            int dest2 = changeA2 ? aTry[i2] : bTry[i2];\n            int needJ = dest2;\n            if (!underList.empty()) {\n                int K = min(20, (int)underList.size());\n                needJ = underList[uniform_int_distribution<int>(0, K-1)(rng)].second;\n            } else {\n                needJ = allAbsList[uniform_int_distribution<int>(0, min(30, N)-1)(rng)].second;\n            }\n            if (N > 1 && needJ == dest2) needJ = (needJ + 2) % N;\n\n            if (changeA2) aTry[i2] = needJ;\n            else bTry[i2] = needJ;\n        }\n\n        long long newErr = simulate(aTry, bTry, T, N, L, newSt);\n\n        // temperature schedule\n        double frac = elapsed() / TL;\n        double temp = 50000.0 * (1.0 - frac) + 2000.0; // decreases over time\n\n        bool accept = false;\n        if (newErr <= curErr) accept = true;\n        else {\n            double diff = (double)(curErr - newErr); // negative\n            double prob = exp(diff / temp); // exp(-delta/temp)\n            double u = uniform_real_distribution<double>(0.0, 1.0)(rng);\n            if (u < prob) accept = true;\n        }\n\n        if (accept) {\n            curA.swap(aTry);\n            curB.swap(bTry);\n            curErr = newErr;\n            curSt = std::move(newSt);\n            if (curErr < bestErr) {\n                bestErr = curErr;\n                bestA = curA;\n                bestB = curB;\n            }\n        }\n    }\n\n    // Output\n    for (int i = 0; i < N; i++) {\n        cout << bestA[i] << ' ' << bestB[i] << '\\n';\n    }\n    return 0;\n}","ahc045":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\n\nstatic inline uint64_t morton2d(uint32_t x, uint32_t y) {\n    // x,y < 2^14\n    uint64_t z = 0;\n    for (uint32_t i = 0; i < 14; i++) {\n        z |= (uint64_t)((x >> i) & 1u) << (2 * i + 1);\n        z |= (uint64_t)((y >> i) & 1u) << (2 * i);\n    }\n    return z;\n}\n\n// lower bound on squared distance between rectangles [lx,rx] x [ly,ry]\nstatic inline ll rectLowerBoundSq(int a, int b,\n                                   const vector<int>& lx, const vector<int>& rx,\n                                   const vector<int>& ly, const vector<int>& ry) {\n    ll dx = 0;\n    if (rx[a] < lx[b]) dx = (ll)lx[b] - rx[a];\n    else if (rx[b] < lx[a]) dx = (ll)lx[a] - rx[b];\n\n    ll dy = 0;\n    if (ry[a] < ly[b]) dy = (ll)ly[b] - ry[a];\n    else if (ry[b] < ly[a]) dy = (ll)ly[a] - ry[b];\n\n    return dx * dx + dy * dy;\n}\n\nstatic vector<int> reorderNearestNeighborProxy(\n    const vector<int>& ids,\n    const vector<int>& cx_i, const vector<int>& cy_i,\n    const vector<uint64_t>& mortonKey,\n    const vector<int>& lx, const vector<int>& rx,\n    const vector<int>& ly, const vector<int>& ry\n) {\n    int sz = (int)ids.size();\n    if (sz <= 2) return ids;\n\n    // Precompute proxy distances inside this group\n    vector<ll> dist(sz * sz, 0);\n    for (int i = 0; i < sz; i++) {\n        dist[i * sz + i] = 0;\n        for (int j = i + 1; j < sz; j++) {\n            ll w = rectLowerBoundSq(ids[i], ids[j], lx, rx, ly, ry);\n            dist[i * sz + j] = dist[j * sz + i] = w;\n        }\n    }\n\n    // Choose up to 3 different starts\n    int argMinKey = 0, argMaxKey = 0;\n    for (int i = 1; i < sz; i++) {\n        if (mortonKey[ids[i]] < mortonKey[ids[argMinKey]]) argMinKey = i;\n        if (mortonKey[ids[i]] > mortonKey[ids[argMaxKey]]) argMaxKey = i;\n    }\n\n    // closest to group midpoint center\n    double centerX = 0.0, centerY = 0.0;\n    for (int i = 0; i < sz; i++) {\n        centerX += cx_i[ids[i]];\n        centerY += cy_i[ids[i]];\n    }\n    centerX /= sz;\n    centerY /= sz;\n\n    int argMinCenter = 0;\n    {\n        double best = 1e300;\n        for (int i = 0; i < sz; i++) {\n            double dx = cx_i[ids[i]] - centerX;\n            double dy = cy_i[ids[i]] - centerY;\n            double v = dx * dx + dy * dy;\n            if (v < best) best = v, argMinCenter = i;\n        }\n    }\n\n    vector<int> starts = {argMinKey, argMaxKey, argMinCenter};\n    sort(starts.begin(), starts.end());\n    starts.erase(unique(starts.begin(), starts.end()), starts.end());\n\n    ll bestScore = (1LL<<62);\n    vector<int> bestPath;\n\n    for (int s : starts) {\n        vector<char> used(sz, 0);\n        int cur = s;\n        used[cur] = 1;\n\n        vector<int> path;\n        path.reserve(sz);\n        ll score = 0;\n\n        for (int step = 0; step < sz; step++) {\n            path.push_back(ids[cur]);\n            if (step == sz - 1) break;\n\n            int bestNext = -1;\n            ll bestW = (1LL<<62);\n            for (int j = 0; j < sz; j++) {\n                if (used[j]) continue;\n                ll w = dist[cur * sz + j];\n                if (w < bestW) {\n                    bestW = w;\n                    bestNext = j;\n                }\n            }\n            score += bestW;\n            cur = bestNext;\n            used[cur] = 1;\n        }\n\n        if (score < bestScore) {\n            bestScore = score;\n            bestPath.swap(path);\n        }\n    }\n\n    return bestPath;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, Q, L, W;\n    cin >> N >> M >> Q >> L >> W;\n\n    vector<int> G(M);\n    for (int i = 0; i < M; i++) cin >> G[i];\n\n    vector<int> lx(N), rx(N), ly(N), ry(N);\n    for (int i = 0; i < N; i++) {\n        cin >> lx[i] >> rx[i] >> ly[i] >> ry[i];\n    }\n\n    vector<int> cx_i(N), cy_i(N);\n    vector<uint64_t> mortonKey(N);\n    for (int i = 0; i < N; i++) {\n        cx_i[i] = (lx[i] + rx[i]) / 2;\n        cy_i[i] = (ly[i] + ry[i]) / 2;\n        uint32_t x = (uint32_t)cx_i[i];\n        uint32_t y = (uint32_t)cy_i[i];\n        mortonKey[i] = morton2d(x, y);\n    }\n\n    vector<int> cities(N);\n    iota(cities.begin(), cities.end(), 0);\n    sort(cities.begin(), cities.end(), [&](int a, int b) {\n        if (mortonKey[a] != mortonKey[b]) return mortonKey[a] < mortonKey[b];\n        return a < b;\n    });\n\n    // Assign cities to groups by contiguous segments in Morton order.\n    // We may permute which group index gets which segment (sizes must match).\n    vector<int> orderGroups(M);\n    iota(orderGroups.begin(), orderGroups.end(), 0);\n    sort(orderGroups.begin(), orderGroups.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>> groupCities(M);\n    int ptr = 0;\n    for (int gi : orderGroups) {\n        int sz = G[gi];\n        groupCities[gi].assign(cities.begin() + ptr, cities.begin() + ptr + sz);\n        ptr += sz;\n    }\n\n    int remainingQ = Q;\n\n    vector<vector<pair<int,int>>> roads(M);\n\n    // Reorder within each group for better locality\n    for (int gi = 0; gi < M; gi++) {\n        auto &vec = groupCities[gi];\n        if ((int)vec.size() <= 2) continue;\n        vec = reorderNearestNeighborProxy(vec, cx_i, cy_i, mortonKey, lx, rx, ly, ry);\n    }\n\n    for (int gi = 0; gi < M; gi++) {\n        auto &vec = groupCities[gi];\n        int sz = (int)vec.size();\n        roads[gi].clear();\n\n        if (sz <= 1) continue;\n        if (sz == 2) {\n            int u = vec[0], v = vec[1];\n            if (u > v) swap(u, v);\n            roads[gi].push_back({u, v});\n            continue;\n        }\n\n        int S = min(L, sz); // S >= 3 here\n        int idx = 0;        // next window start\n\n        while (idx + S <= sz && remainingQ > 0) {\n            cout << \"? \" << S;\n            for (int t = 0; t < S; t++) cout << ' ' << vec[idx + t];\n            cout << '\\n' << flush;\n\n            for (int t = 0; t < S - 1; t++) {\n                int a, b;\n                cin >> a >> b;\n                if (a > b) swap(a, b);\n                roads[gi].push_back({a, b});\n            }\n            remainingQ--;\n            idx += (S - 1); // overlap by 1 vertex\n        }\n\n        // Chain-finish the remaining tail\n        // idx is the first index after the last queried window start step,\n        // and vec[idx] is guaranteed to be included in the last queried window\n        // if at least one query was executed; otherwise it's just the first vertex.\n        for (int t = idx; t + 1 < sz; t++) {\n            int u = vec[t], v = vec[t + 1];\n            if (u > v) swap(u, v);\n            roads[gi].push_back({u, v});\n        }\n\n        // Safety: ensure exact edge count\n        if ((int)roads[gi].size() != sz - 1) {\n            roads[gi].clear();\n            for (int t = 1; t < sz; t++) {\n                int u = vec[t - 1], v = vec[t];\n                if (u > v) swap(u, v);\n                roads[gi].push_back({u, v});\n            }\n        }\n    }\n\n    cout << \"!\" << '\\n' << flush;\n\n    for (int gi = 0; gi < M; gi++) {\n        auto &vec = groupCities[gi];\n        for (int i = 0; i < (int)vec.size(); i++) {\n            if (i) cout << ' ';\n            cout << vec[i];\n        }\n        cout << '\\n';\n        for (auto [u, v] : roads[gi]) {\n            cout << u << ' ' << v << '\\n';\n        }\n    }\n    cout << flush;\n    return 0;\n}","ahc046":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const char ACT[3] = {'M', 'S', 'A'};\nstatic const char DIRC[4] = {'U', 'D', 'L', 'R'};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M;\n    cin >> N >> M;\n    vector<pair<int,int>> pos(M);\n    for (int k = 0; k < M; k++) cin >> pos[k].first >> pos[k].second;\n\n    const int Vpos = N * N;\n    const int Vblock = Vpos + 1;          // 0 = none, 1..Vpos = block at cell idx=(b-1)\n    const int VN = Vblock * Vpos;         // total states\n\n    // Direction indices: 0=U,1=D,2=L,3=R\n    int dx[4] = {-1, 1, 0, 0};\n    int dy[4] = {0, 0, -1, 1};\n\n    auto inside = [&](int x, int y) {\n        return 0 <= x && x < N && 0 <= y && y < N;\n    };\n\n    // Precompute neighbor for Move/Alter (if outside => -1)\n    vector<array<int,4>> neigh(Vpos);\n    for (int p = 0; p < Vpos; p++) {\n        int x = p / N, y = p % N;\n        for (int dir = 0; dir < 4; dir++) {\n            int nx = x + dx[dir], ny = y + dy[dir];\n            neigh[p][dir] = inside(nx, ny) ? (nx * N + ny) : -1;\n        }\n    }\n\n    // Precompute Slide stop positions:\n    // slideStop[pos][blockIdx][dir] => stopPos (pos idx), with blockIdx in [0..Vpos]\n    vector<uint16_t> slideStop(VN * 4);\n    auto slideIndex = [&](int blockIdx, int p, int dir) {\n        return ((blockIdx * Vpos + p) * 4 + dir);\n    };\n\n    for (int p = 0; p < Vpos; p++) {\n        int x = p / N, y = p % N;\n        for (int blockIdx = 0; blockIdx < Vblock; blockIdx++) {\n            int bx = -1, by = -1;\n            if (blockIdx != 0) {\n                int bcell = blockIdx - 1;\n                bx = bcell / N;\n                by = bcell % N;\n            }\n            for (int dir = 0; dir < 4; dir++) {\n                int stopX = x, stopY = y;\n\n                if (dir == 0) { // U\n                    if (blockIdx != 0 && y == by && bx < x) stopX = bx + 1;\n                    else stopX = 0;\n                    stopY = y;\n                } else if (dir == 1) { // D\n                    if (blockIdx != 0 && y == by && bx > x) stopX = bx - 1;\n                    else stopX = N - 1;\n                    stopY = y;\n                } else if (dir == 2) { // L\n                    if (blockIdx != 0 && x == bx && by < y) stopY = by + 1;\n                    else stopY = 0;\n                    stopX = x;\n                } else { // R\n                    if (blockIdx != 0 && x == bx && by > y) stopY = by - 1;\n                    else stopY = N - 1;\n                    stopX = x;\n                }\n\n                int stopPos = stopX * N + stopY;\n                slideStop[slideIndex(blockIdx, p, dir)] = (uint16_t)stopPos;\n            }\n        }\n    }\n\n    auto bfsTransition = [&](int sx, int sy, int tx, int ty) {\n        int sp = sx * N + sy;\n        int tp = tx * N + ty;\n\n        int start = 0 * Vpos + sp;     // block none\n        int goal  = 0 * Vpos + tp;    // block none\n\n        vector<int> dist(VN, -1);\n        vector<int> pre(VN, -1);\n        vector<unsigned short> preCode(VN, 0);\n\n        queue<int> q;\n        dist[start] = 0;\n        q.push(start);\n\n        while (!q.empty()) {\n            int v = q.front(); q.pop();\n            if (v == goal) break;\n\n            int bIdx = v / Vpos;\n            int pIdx = v % Vpos;\n\n            // Current x,y not explicitly needed due to precomputations except alter/goal logic\n            // but still we can decode for none.\n            for (int dir = 0; dir < 4; dir++) {\n                // 1) Move\n                int np = neigh[pIdx][dir];\n                if (np != -1) {\n                    if (!(bIdx != 0 && (np == (bIdx - 1)))) {\n                        int to = bIdx * Vpos + np;\n                        if (dist[to] == -1) {\n                            dist[to] = dist[v] + 1;\n                            pre[to] = v;\n                            preCode[to] = (0 * 4 + dir); // M\n                            q.push(to);\n                        }\n                    }\n                }\n\n                // 2) Slide\n                {\n                    int stopPos = (int)slideStop[slideIndex(bIdx, pIdx, dir)];\n                    int to = bIdx * Vpos + stopPos;\n                    if (dist[to] == -1) {\n                        dist[to] = dist[v] + 1;\n                        pre[to] = v;\n                        preCode[to] = (1 * 4 + dir); // S\n                        q.push(to);\n                    }\n                }\n\n                // 3) Alter (toggle adjacent block)\n                int ap = neigh[pIdx][dir];\n                if (ap != -1) {\n                    int nbIdx;\n                    if (bIdx == 0) nbIdx = 1 + ap;                // place\n                    else if (bIdx == 1 + ap) nbIdx = 0;         // remove\n                    else continue;                                // would create 2nd block (forbidden in this BFS)\n\n                    int to = nbIdx * Vpos + pIdx; // position unchanged\n                    if (dist[to] == -1) {\n                        dist[to] = dist[v] + 1;\n                        pre[to] = v;\n                        preCode[to] = (2 * 4 + dir); // A\n                        q.push(to);\n                    }\n                }\n            }\n        }\n\n        // Reconstruct\n        vector<pair<char,char>> res;\n        int cur = goal;\n        while (cur != start) {\n            unsigned short code = preCode[cur];\n            int prev = pre[cur];\n            int actIdx = code / 4;\n            int dirIdx = code % 4;\n            res.push_back({ACT[actIdx], DIRC[dirIdx]});\n            cur = prev;\n        }\n        reverse(res.begin(), res.end());\n        return res;\n    };\n\n    vector<pair<char,char>> actions;\n    actions.reserve(2000);\n\n    int cx = pos[0].first, cy = pos[0].second;\n    for (int k = 1; k < M; k++) {\n        int tx = pos[k].first, ty = pos[k].second;\n        auto part = bfsTransition(cx, cy, tx, ty);\n        for (auto &e : part) actions.push_back(e);\n        cx = tx; cy = ty;\n    }\n\n    int limit = 2 * N * M;\n    if ((int)actions.size() > limit) {\n        // Should not happen since Move-only path is always available,\n        // but just in case, truncate legality is not guaranteed; abort.\n        return 0;\n    }\n\n    for (auto &e : actions) {\n        cout << e.first << ' ' << e.second << \"\\n\";\n    }\n    return 0;\n}"},"4":{"ahc001":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\n\nstruct Company {\n    int x, y;\n    ll r;\n};\n\nstruct Rect {\n    int a, b, c, d; // [a,c) x [b,d)\n};\n\nstruct Cand {\n    int k;\n    ll costAbs; // |areaChild - sumRChild|\n};\n\nstatic double evalScore(const vector<Company>& comp, const vector<Rect>& rects) {\n    int n = (int)comp.size();\n    long double total = 0;\n    for (int i = 0; i < n; i++) {\n        ll s = 1LL * (rects[i].c - rects[i].a) * (rects[i].d - rects[i].b);\n        ll ri = comp[i].r;\n        ll mn = min(ri, s), mx = max(ri, s);\n        long double t = (long double)mn / (long double)mx;\n        long double p = 1.0L - (1.0L - t) * (1.0L - t); // 1-(1-t)^2\n        total += p;\n    }\n    return (double)total;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int n;\n    cin >> n;\n    vector<Company> comp(n);\n    for (int i = 0; i < n; i++) {\n        cin >> comp[i].x >> comp[i].y >> comp[i].r;\n    }\n\n    constexpr int N = 10000;\n    vector<Rect> bestRects(n);\n    double bestScore = -1e100;\n\n    auto startTime = chrono::steady_clock::now();\n\n    uint64_t baseSeed = chrono::steady_clock::now().time_since_epoch().count();\n    std::mt19937_64 rng(baseSeed);\n\n    // Heuristic parameters\n    const int TIME_LIMIT_MS = 4700;\n    const int TOPK = 10;\n    const long double ORI_ALPHA = 6.0L;  // orientation softmax strength\n    const long double K_BETA = 10.0L;    // cut-choice softmax strength\n\n    auto getCandidates = [&](const vector<int>& ids, int lx, int rx, int ly, int ry, bool vertical) -> vector<Cand> {\n        int m = (int)ids.size();\n        vector<Cand> cand;\n        if (m <= 1) return cand;\n\n        ll areaParent = 1LL * (rx - lx) * (ry - ly);\n        if (areaParent <= 0) return cand;\n\n        if (vertical) {\n            if (rx - lx <= 1) return cand;\n\n            vector<int> v = ids;\n            sort(v.begin(), v.end(), [&](int a, int b) { return comp[a].x < comp[b].x; });\n\n            // group by x, store xvals and sumR per group\n            vector<int> xs;\n            vector<ll> sumR;\n            xs.reserve(m);\n            sumR.reserve(m);\n\n            for (int i = 0; i < m; ) {\n                int j = i;\n                int xval = comp[v[i]].x;\n                ll s = 0;\n                while (j < m && comp[v[j]].x == xval) {\n                    s += comp[v[j]].r;\n                    j++;\n                }\n                xs.push_back(xval);\n                sumR.push_back(s);\n                i = j;\n            }\n\n            int G = (int)xs.size();\n            if (G <= 1) return cand;\n\n            // prefix sums by groups\n            vector<ll> pref(G + 1, 0);\n            for (int i = 0; i < G; i++) pref[i + 1] = pref[i] + sumR[i];\n\n            ll height = 1LL * (ry - ly);\n\n            for (int g = 0; g < G - 1; g++) {\n                int uL = xs[g];\n                int uR = xs[g + 1];\n\n                // k integer in [uL+1, uR] gives same split by x<k\n                int k_low = max(lx + 1, uL + 1);\n                int k_high = min(rx - 1, uR);\n                if (k_low > k_high) continue;\n\n                ll leftSum = pref[g + 1]; // groups [0..g]\n                // areaL(k) = (k-lx)*height\n                long double targetWidth = (long double)leftSum / (long double)height;\n                int k_opt = (int)llround((long double)lx + targetWidth);\n\n                auto addK = [&](int k) {\n                    if (k < k_low || k > k_high) return;\n                    ll areaL = 1LL * (k - lx) * height;\n                    ll diff = llabs(areaL - leftSum);\n                    cand.push_back({k, diff});\n                };\n\n                addK(k_opt);\n                addK(k_opt - 1);\n                addK(k_opt + 1);\n                addK(k_low);\n                addK(k_high);\n            }\n\n        } else {\n            if (ry - ly <= 1) return cand;\n\n            vector<int> v = ids;\n            sort(v.begin(), v.end(), [&](int a, int b) { return comp[a].y < comp[b].y; });\n\n            // group by y, store yvals and sumR per group\n            vector<int> ys;\n            vector<ll> sumR;\n            ys.reserve(m);\n            sumR.reserve(m);\n\n            for (int i = 0; i < m; ) {\n                int j = i;\n                int yval = comp[v[i]].y;\n                ll s = 0;\n                while (j < m && comp[v[j]].y == yval) {\n                    s += comp[v[j]].r;\n                    j++;\n                }\n                ys.push_back(yval);\n                sumR.push_back(s);\n                i = j;\n            }\n\n            int G = (int)ys.size();\n            if (G <= 1) return cand;\n\n            // prefix sums by groups\n            vector<ll> pref(G + 1, 0);\n            for (int i = 0; i < G; i++) pref[i + 1] = pref[i] + sumR[i];\n\n            ll width = 1LL * (rx - lx);\n\n            for (int g = 0; g < G - 1; g++) {\n                int uL = ys[g];\n                int uR = ys[g + 1];\n\n                // k integer in [uL+1, uR] gives same split by y<k\n                int k_low = max(ly + 1, uL + 1);\n                int k_high = min(ry - 1, uR);\n                if (k_low > k_high) continue;\n\n                ll bottomSum = pref[g + 1]; // groups [0..g]\n                // areaB(k) = (k-ly)*width\n                long double targetH = (long double)bottomSum / (long double)width;\n                int k_opt = (int)llround((long double)ly + targetH);\n\n                auto addK = [&](int k) {\n                    if (k < k_low || k > k_high) return;\n                    ll areaB = 1LL * (k - ly) * width;\n                    ll diff = llabs(areaB - bottomSum);\n                    cand.push_back({k, diff});\n                };\n\n                addK(k_opt);\n                addK(k_opt - 1);\n                addK(k_opt + 1);\n                addK(k_low);\n                addK(k_high);\n            }\n        }\n\n        if (cand.empty()) return cand;\n        sort(cand.begin(), cand.end(), [&](const Cand& A, const Cand& B) {\n            if (A.costAbs != B.costAbs) return A.costAbs < B.costAbs;\n            return A.k < B.k;\n        });\n\n        // Dedup by k keeping smallest cost\n        vector<Cand> ded;\n        ded.reserve(cand.size());\n        for (auto &c : cand) {\n            if (ded.empty() || ded.back().k != c.k) ded.push_back(c);\n        }\n        return ded;\n    };\n\n    // Main time-based restart loop\n    int it = 0;\n    while (true) {\n        auto now = chrono::steady_clock::now();\n        int elapsed = (int)chrono::duration_cast<chrono::milliseconds>(now - startTime).count();\n        if (elapsed >= TIME_LIMIT_MS) break;\n        it++;\n\n        // per-iteration RNG\n        uint64_t seed = baseSeed ^ (uint64_t)it * 0x9e3779b97f4a7c15ULL;\n        std::mt19937_64 rng2(seed);\n\n        vector<Rect> rects(n);\n\n        function<void(int,int,int,int,const vector<int>&)> build =\n            [&](int lx, int rx, int ly, int ry, const vector<int>& ids) {\n                if ((int)ids.size() == 1) {\n                    int id = ids[0];\n                    rects[id] = Rect{lx, ly, rx, ry};\n                    return;\n                }\n\n                ll areaParent = 1LL * (rx - lx) * (ry - ly);\n\n                auto candV = getCandidates(ids, lx, rx, ly, ry, true);\n                auto candH = getCandidates(ids, lx, rx, ly, ry, false);\n\n                bool chooseV;\n                if (candV.empty()) chooseV = false;\n                else if (candH.empty()) chooseV = true;\n                else {\n                    ll bestV = candV.front().costAbs;\n                    ll bestH = candH.front().costAbs;\n                    long double pV = expl(- (long double)bestV / (long double)(areaParent + 1) * ORI_ALPHA);\n                    long double pH = expl(- (long double)bestH / (long double)(areaParent + 1) * ORI_ALPHA);\n                    long double sum = pV + pH;\n                    if (sum <= 0) chooseV = (bestV <= bestH);\n                    else {\n                        long double u = (long double)(rng2() % 1000000) / 1000000.0L;\n                        chooseV = (u < pV / sum);\n                    }\n                }\n\n                if (chooseV) {\n                    // pick k among top candidates\n                    int top = min<int>(TOPK, (int)candV.size());\n                    vector<Cand> sub(candV.begin(), candV.begin() + top);\n\n                    // softmax over costs\n                    long double sumW = 0;\n                    vector<long double> w(top);\n                    for (int i = 0; i < top; i++) {\n                        w[i] = expl(- (long double)sub[i].costAbs / (long double)(areaParent + 1) * K_BETA);\n                        sumW += w[i];\n                    }\n                    int pick = 0;\n                    if (sumW <= 0) pick = 0;\n                    else {\n                        long double u = (long double)(rng2() % 1000000) / 1000000.0L * sumW;\n                        long double acc = 0;\n                        for (int i = 0; i < top; i++) {\n                            acc += w[i];\n                            if (u <= acc) { pick = i; break; }\n                        }\n                    }\n                    int k = sub[pick].k;\n\n                    vector<int> L, R;\n                    L.reserve(ids.size());\n                    R.reserve(ids.size());\n                    for (int id : ids) (comp[id].x < k ? L : R).push_back(id);\n\n                    if (L.empty() || R.empty()) {\n                        // fallback: median x split\n                        vector<int> v = ids;\n                        sort(v.begin(), v.end(), [&](int a, int b){ return comp[a].x < comp[b].x; });\n                        int mid = (int)v.size() / 2;\n                        k = comp[v[mid]].x;\n                        L.clear(); R.clear();\n                        for (int id : ids) (comp[id].x < k ? L : R).push_back(id);\n                        if (L.empty() || R.empty()) {\n                            // last resort: simple y split\n                            vector<int> v2 = ids;\n                            sort(v2.begin(), v2.end(), [&](int a, int b){ return comp[a].y < comp[b].y; });\n                            int mid2 = (int)v2.size()/2;\n                            int k2 = comp[v2[mid2]].y;\n                            vector<int> B, T;\n                            for (int id : ids) (comp[id].y < k2 ? B : T).push_back(id);\n                            if (!B.empty() && !T.empty()) {\n                                build(lx, rx, ly, k2, B);\n                                build(lx, rx, k2, ry, T);\n                                return;\n                            }\n                            // should not happen\n                            int id = ids[0];\n                            rects[id] = Rect{lx, ly, rx, ry};\n                            return;\n                        }\n                    }\n\n                    build(lx, k, ly, ry, L);\n                    build(k, rx, ly, ry, R);\n\n                } else {\n                    // horizontal cut\n                    int top = min<int>(TOPK, (int)candH.size());\n                    vector<Cand> sub(candH.begin(), candH.begin() + top);\n\n                    long double sumW = 0;\n                    vector<long double> w(top);\n                    for (int i = 0; i < top; i++) {\n                        w[i] = expl(- (long double)sub[i].costAbs / (long double)(areaParent + 1) * K_BETA);\n                        sumW += w[i];\n                    }\n                    int pick = 0;\n                    if (sumW <= 0) pick = 0;\n                    else {\n                        long double u = (long double)(rng2() % 1000000) / 1000000.0L * sumW;\n                        long double acc = 0;\n                        for (int i = 0; i < top; i++) {\n                            acc += w[i];\n                            if (u <= acc) { pick = i; break; }\n                        }\n                    }\n                    int k = sub[pick].k;\n\n                    vector<int> B, T;\n                    B.reserve(ids.size());\n                    T.reserve(ids.size());\n                    for (int id : ids) (comp[id].y < k ? B : T).push_back(id);\n\n                    if (B.empty() || T.empty()) {\n                        // fallback: median y split\n                        vector<int> v = ids;\n                        sort(v.begin(), v.end(), [&](int a, int b){ return comp[a].y < comp[b].y; });\n                        int mid = (int)v.size() / 2;\n                        k = comp[v[mid]].y;\n                        B.clear(); T.clear();\n                        for (int id : ids) (comp[id].y < k ? B : T).push_back(id);\n                        if (B.empty() || T.empty()) {\n                            // last resort: median x split\n                            vector<int> v2 = ids;\n                            sort(v2.begin(), v2.end(), [&](int a, int b){ return comp[a].x < comp[b].x; });\n                            int mid2 = (int)v2.size()/2;\n                            int k2 = comp[v2[mid2]].x;\n                            vector<int> L, R;\n                            for (int id : ids) (comp[id].x < k2 ? L : R).push_back(id);\n                            if (!L.empty() && !R.empty()) {\n                                build(lx, k2, ly, ry, L);\n                                build(k2, rx, ly, ry, R);\n                                return;\n                            }\n                            int id = ids[0];\n                            rects[id] = Rect{lx, ly, rx, ry};\n                            return;\n                        }\n                    }\n\n                    build(lx, rx, ly, k, B);\n                    build(lx, rx, k, ry, T);\n                }\n            };\n\n        vector<int> ids(n);\n        iota(ids.begin(), ids.end(), 0);\n        build(0, N, 0, N, ids);\n\n        double sc = evalScore(comp, rects);\n        if (sc > bestScore) {\n            bestScore = sc;\n            bestRects = rects;\n        }\n    }\n\n    for (int i = 0; i < n; i++) {\n        cout << bestRects[i].a << ' ' << bestRects[i].b << ' '\n             << bestRects[i].c << ' ' << bestRects[i].d << '\\n';\n    }\n    return 0;\n}","ahc002":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const int H = 50, W = 50;\nstatic const int N = H * W;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int si, sj;\n    cin >> si >> sj;\n    vector<int> tile(N);\n    for (int i = 0; i < H; i++) {\n        for (int j = 0; j < W; j++) {\n            cin >> tile[i * W + j];\n        }\n    }\n    vector<int> p(N);\n    for (int i = 0; i < H; i++) {\n        for (int j = 0; j < W; j++) {\n            cin >> p[i * W + j];\n        }\n    }\n\n    int M = 0;\n    for (int x : tile) M = max(M, x + 1);\n\n    int start = si * W + sj;\n\n    // Neighbors (4-neighborhood) on squares\n    vector<array<int, 4>> neigh(N);\n    vector<int> deg(N, 0);\n    for (int i = 0; i < H; i++) {\n        for (int j = 0; j < W; j++) {\n            int id = i * W + j;\n            array<int,4> arr;\n            arr.fill(-1);\n            int d = 0;\n            auto add = [&](int ni, int nj) {\n                if (0 <= ni && ni < H && 0 <= nj && nj < W) arr[d++] = ni * W + nj;\n            };\n            add(i-1, j);\n            add(i+1, j);\n            add(i, j-1);\n            add(i, j+1);\n            neigh[id] = arr;\n            deg[id] = d;\n        }\n    }\n\n    // Precompute for each square: how many distinct tile-ids appear among its neighbor squares (excluding same tile).\n    vector<int> cntAdjDistinct(N, 0);\n    for (int id = 0; id < N; id++) {\n        int ti = tile[id];\n        int seen[4]; int sc = 0;\n        for (int k = 0; k < 4; k++) {\n            int nb = neigh[id][k];\n            if (nb < 0) continue;\n            int tb = tile[nb];\n            if (tb == ti) continue;\n            bool ok = true;\n            for (int q = 0; q < sc; q++) if (seen[q] == tb) ok = false;\n            if (ok) seen[sc++] = tb;\n        }\n        cntAdjDistinct[id] = sc;\n    }\n\n    auto coordOf = [&](int id) -> pair<int,int> {\n        return {id / W, id % W};\n    };\n\n    auto dirBetween = [&](int a, int b) -> char {\n        int ai = a / W, aj = a % W;\n        int bi = b / W, bj = b % W;\n        if (bi == ai - 1 && bj == aj) return 'U';\n        if (bi == ai + 1 && bj == aj) return 'D';\n        if (bi == ai && bj == aj - 1) return 'L';\n        if (bi == ai && bj == aj + 1) return 'R';\n        // Should not happen if b is a 4-neighbor of a\n        return '?';\n    };\n\n    // One random stochastic greedy walk.\n    auto runWalk = [&](mt19937_64 &rng, bool storePath) {\n        vector<char> used(M, 0);\n        vector<int> curPath;\n        curPath.reserve(M);\n\n        used[tile[start]] = 1;\n        int cur = start;\n        long long score = p[cur];\n        curPath.push_back(cur);\n\n        const double beta = 0.85;   // lookahead weight\n        const double gamma = 0.35;  // distinct-neighbor bias\n        while (true) {\n            vector<pair<int,double>> cand; // (next, value)\n            cand.reserve(4);\n            for (int k = 0; k < 4; k++) {\n                int nb = neigh[cur][k];\n                if (nb < 0) continue;\n                int tnb = tile[nb];\n                if (used[tnb]) continue;\n                int futureMax = 0;\n                // one-step lookahead from nb\n                for (int kk = 0; kk < 4; kk++) {\n                    int nn = neigh[nb][kk];\n                    if (nn < 0) continue;\n                    int tnn = tile[nn];\n                    if (used[tnn]) continue;\n                    futureMax = max(futureMax, p[nn]);\n                }\n                double val = (double)p[nb] + beta * (double)futureMax + gamma * (double)cntAdjDistinct[nb];\n                // small noise to diversify\n                val += (double)(uniform_int_distribution<int>(0, 999)(rng)) * 1e-6; // up to ~0.001\n                cand.push_back({nb, val});\n            }\n            if (cand.empty()) break;\n\n            sort(cand.begin(), cand.end(), [&](auto &x, auto &y){ return x.second > y.second; });\n            int K = min<int>(3, (int)cand.size());\n\n            if (K == 1) {\n                int nxt = cand[0].first;\n                used[tile[nxt]] = 1;\n                cur = nxt;\n                score += p[cur];\n                curPath.push_back(cur);\n            } else {\n                double base = cand[K-1].second;\n                vector<double> w(K);\n                double sumw = 0;\n                for (int i = 0; i < K; i++) {\n                    w[i] = (cand[i].second - base) + 1.0; // positive\n                    sumw += w[i];\n                }\n                double r = uniform_real_distribution<double>(0.0, sumw)(rng);\n                int pick = 0;\n                while (pick < K && r >= w[pick]) {\n                    r -= w[pick];\n                    pick++;\n                }\n                if (pick >= K) pick = K - 1;\n                int nxt = cand[pick].first;\n                used[tile[nxt]] = 1;\n                cur = nxt;\n                score += p[cur];\n                curPath.push_back(cur);\n            }\n        }\n\n        if (storePath) {\n            return pair<long long, vector<int>>(score, curPath);\n        } else {\n            return pair<long long, vector<int>>(score, {});\n        }\n    };\n\n    // Time control\n    auto t0 = chrono::steady_clock::now();\n    double TIME_LIMIT = 1.88; // seconds\n\n    mt19937_64 rng((uint64_t)chrono::steady_clock::now().time_since_epoch().count());\n\n    long long bestScore = -1;\n    vector<int> bestPath;\n\n    // Multi-start stochastic greedy\n    while (true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - t0).count();\n        if (elapsed > TIME_LIMIT) break;\n\n        bool store = false;\n        // only store path if it might improve, to reduce copying\n        // We'll quickly estimate by running without storing? (but then path missing)\n        // Simpler: always store; with small sizes it\u2019s okay. Keep it conditional:\n        // run twice? too much. We'll store every time.\n        auto [sc, path] = runWalk(rng, true);\n        if (sc > bestScore) {\n            bestScore = sc;\n            bestPath = std::move(path);\n        }\n    }\n\n    // Tail extension from best prefix (a few tries)\n    // Use remaining time.\n    auto now = chrono::steady_clock::now();\n    double elapsed = chrono::duration<double>(now - t0).count();\n    int tries = 0;\n    while (elapsed < TIME_LIMIT && tries < 60) {\n        tries++;\n\n        int L = (int)bestPath.size();\n        if (L <= 1) break;\n\n        uniform_int_distribution<int> distCut(0, max(0, L - 1));\n        // Prefer cutting near the end\n        int cut = max(0, L - 1 - (int)uniform_int_distribution<int>(0, min(120, L - 1))(rng));\n        if (cut < 0) cut = 0;\n\n        vector<char> used(M, 0);\n        long long score = 0;\n        for (int i = 0; i <= cut; i++) {\n            int sq = bestPath[i];\n            used[tile[sq]] = 1;\n            score += p[sq];\n        }\n        int cur = bestPath[cut];\n\n        vector<int> newPart;\n        newPart.reserve(M - cut);\n\n        // run extension with current used/cur\n        const double beta = 0.85, gamma = 0.35;\n        vector<int> curPath2;\n        curPath2.reserve(M);\n        curPath2.push_back(cur); // starting at cur\n\n        long long sc2 = score;\n\n        while (true) {\n            vector<pair<int,double>> cand;\n            for (int k = 0; k < 4; k++) {\n                int nb = neigh[cur][k];\n                if (nb < 0) continue;\n                if (used[tile[nb]]) continue;\n                int futureMax = 0;\n                for (int kk = 0; kk < 4; kk++) {\n                    int nn = neigh[nb][kk];\n                    if (nn < 0) continue;\n                    if (used[tile[nn]]) continue;\n                    futureMax = max(futureMax, p[nn]);\n                }\n                double val = (double)p[nb] + beta * (double)futureMax + gamma * (double)cntAdjDistinct[nb];\n                val += (double)(uniform_int_distribution<int>(0, 999)(rng)) * 1e-6;\n                cand.push_back({nb, val});\n            }\n            if (cand.empty()) break;\n\n            sort(cand.begin(), cand.end(), [&](auto &x, auto &y){ return x.second > y.second; });\n            int K = min<int>(3, (int)cand.size());\n            int nxt;\n            if (K == 1) nxt = cand[0].first;\n            else {\n                double base = cand[K-1].second;\n                vector<double> w(K);\n                double sumw = 0;\n                for (int i = 0; i < K; i++) {\n                    w[i] = (cand[i].second - base) + 1.0;\n                    sumw += w[i];\n                }\n                double r = uniform_real_distribution<double>(0.0, sumw)(rng);\n                int pick = 0;\n                while (pick < K && r >= w[pick]) {\n                    r -= w[pick];\n                    pick++;\n                }\n                if (pick >= K) pick = K - 1;\n                nxt = cand[pick].first;\n            }\n\n            used[tile[nxt]] = 1;\n            cur = nxt;\n            sc2 += p[cur];\n            curPath2.push_back(cur);\n        }\n\n        if (sc2 > bestScore) {\n            vector<int> merged;\n            merged.reserve(L - (cut + 1) + (int)curPath2.size());\n            for (int i = 0; i <= cut; i++) merged.push_back(bestPath[i]);\n            // append curPath2 excluding the first element (it equals bestPath[cut])\n            for (int i = 1; i < (int)curPath2.size(); i++) merged.push_back(curPath2[i]);\n            bestScore = sc2;\n            bestPath = std::move(merged);\n        }\n\n        now = chrono::steady_clock::now();\n        elapsed = chrono::duration<double>(now - t0).count();\n    }\n\n    // Output directions string\n    string ans;\n    if (!bestPath.empty()) {\n        ans.reserve(max(0, (int)bestPath.size() - 1));\n        for (int i = 1; i < (int)bestPath.size(); i++) {\n            ans.push_back(dirBetween(bestPath[i-1], bestPath[i]));\n        }\n    }\n    cout << ans << \"\\n\";\n    return 0;\n}","ahc003":"#include <bits/stdc++.h>\nusing namespace std;\n\n// Grid constants\nstatic constexpr int H = 30;\nstatic constexpr int W = 30;\nstatic constexpr int N = H * W;\n\n// Horizontal edges: between (i,j) and (i,j+1), i in [0..29], j in [0..28]\nstatic constexpr int HOR = H * (W - 1); // 30*29 = 870\n// Vertical edges: between (i,j) and (i+1,j), i in [0..28], j in [0..29]\nstatic constexpr int VER = (H - 1) * W; // 29*30 = 870\nstatic constexpr int ECOUNT = HOR + VER;\n\nstatic inline int idx_node(int i, int j) { return i * W + j; }\nstatic inline int idx_horizontal_edge(int i, int j) { return i * (W - 1) + j; }         // j in [0..28]\nstatic inline int idx_vertical_edge(int i, int j) { return HOR + i * W + j; }            // i in [0..28], j in [0..29]\n\nstruct PathResult {\n    string moves;\n    vector<int> usedEdges;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // Build adjacency list with edge indices\n    vector<vector<pair<int,int>>> adj(N); // (to, edgeIdx)\n    for (int i = 0; i < H; i++) {\n        for (int j = 0; j < W; j++) {\n            int u = idx_node(i,j);\n            if (j + 1 < W) {\n                int v = idx_node(i, j + 1);\n                int e = idx_horizontal_edge(i, j);\n                adj[u].push_back({v, e});\n                adj[v].push_back({u, e});\n            }\n            if (i + 1 < H) {\n                int v = idx_node(i + 1, j);\n                int e = idx_vertical_edge(i, j);\n                adj[u].push_back({v, e});\n                adj[v].push_back({u, e});\n            }\n        }\n    }\n\n    // Estimated edge weights\n    const double LO_W = 500.0;\n    const double HI_W = 9500.0;\n    vector<double> w_hat(ECOUNT, 5000.0);\n\n    // RNG\n    std::mt19937_64 rng(123456789ULL);\n    auto rand01 = [&]() -> double {\n        return (rng() >> 11) * (1.0 / 9007199254740992.0);\n    };\n    std::normal_distribution<double> gauss(0.0, 1.0);\n\n    const double INF = 1e100;\n\n    // Reusable arrays for Dijkstra\n    vector<double> dist(N);\n    vector<int> parent(N);\n    vector<int> parentEdge(N);\n\n    auto build_path = [&](int s, int t) -> PathResult {\n        PathResult res;\n        if (s == t) return res;\n\n        vector<char> revMoves;\n        vector<int> revEdges;\n\n        int cur = t;\n        while (cur != s) {\n            int p = parent[cur];\n            int e = parentEdge[cur];\n            if (p < 0 || e < 0) return PathResult{};\n\n            int pi = p / W, pj = p % W;\n            int ci = cur / W, cj = cur % W;\n\n            char mv;\n            if (ci == pi - 1 && cj == pj) mv = 'U';\n            else if (ci == pi + 1 && cj == pj) mv = 'D';\n            else if (ci == pi && cj == pj - 1) mv = 'L';\n            else if (ci == pi && cj == pj + 1) mv = 'R';\n            else mv = '?';\n\n            revMoves.push_back(mv);\n            revEdges.push_back(e);\n            cur = p;\n        }\n\n        reverse(revMoves.begin(), revMoves.end());\n        reverse(revEdges.begin(), revEdges.end());\n\n        res.moves.assign(revMoves.begin(), revMoves.end());\n        res.usedEdges = std::move(revEdges);\n        return res;\n    };\n\n    auto dijkstra_path = [&](int s, int t, const vector<double>* w_use_ptr) -> PathResult {\n        const vector<double>& w_use = w_use_ptr ? *w_use_ptr : w_hat;\n\n        for (int i = 0; i < N; i++) {\n            dist[i] = INF;\n            parent[i] = -1;\n            parentEdge[i] = -1;\n        }\n\n        struct NodeState {\n            double d;\n            int v;\n            bool operator>(const NodeState& o) const { return d > o.d; }\n        };\n\n        priority_queue<NodeState, vector<NodeState>, greater<NodeState>> pq;\n        dist[s] = 0.0;\n        parent[s] = s;\n        pq.push({0.0, s});\n\n        const double EPS = 1e-12;\n\n        while (!pq.empty()) {\n            auto [dcur, u] = pq.top(); pq.pop();\n            if (dcur != dist[u]) continue;\n            if (u == t) break;\n\n            for (auto [to, e] : adj[u]) {\n                double nd = dcur + w_use[e];\n                if (nd + EPS < dist[to]) {\n                    dist[to] = nd;\n                    parent[to] = u;\n                    parentEdge[to] = e;\n                    pq.push({nd, to});\n                } else if (fabs(nd - dist[to]) <= EPS) {\n                    if (rand01() < 0.5) {\n                        parent[to] = u;\n                        parentEdge[to] = e;\n                        pq.push({nd, to});\n                    }\n                }\n            }\n        }\n        return build_path(s, t);\n    };\n\n    // Monotone fallback (always simple path)\n    auto monotone_path = [&](int s, int t) -> PathResult {\n        int si = s / W, sj = s % W;\n        int ti = t / W, tj = t % W;\n        int i = si, j = sj;\n\n        PathResult res;\n        while (i != ti || j != tj) {\n            bool canV = (i != ti);\n            bool canH = (j != tj);\n            bool doV;\n            if (canV && canH) doV = (rand01() < 0.5);\n            else doV = canV;\n\n            if (doV) {\n                if (ti > i) { // down\n                    int e = idx_vertical_edge(i, j);\n                    res.usedEdges.push_back(e);\n                    res.moves.push_back('D');\n                    i++;\n                } else { // up\n                    int e = idx_vertical_edge(i - 1, j);\n                    res.usedEdges.push_back(e);\n                    res.moves.push_back('U');\n                    i--;\n                }\n            } else {\n                if (tj > j) { // right\n                    int e = idx_horizontal_edge(i, j);\n                    res.usedEdges.push_back(e);\n                    res.moves.push_back('R');\n                    j++;\n                } else { // left\n                    int e = idx_horizontal_edge(i, j - 1);\n                    res.usedEdges.push_back(e);\n                    res.moves.push_back('L');\n                    j--;\n                }\n            }\n        }\n        return res;\n    };\n\n    auto smooth_rows_cols = [&](int k) {\n        if (k < 80) return;\n        if (k % 25 != 0) return;\n\n        const double alpha = 0.12;\n        const double TH = 0.80;\n\n        // Horizontal smoothing per row i over edges j=0..28 (29 edges)\n        for (int i = 0; i < H; i++) {\n            int n = W - 1; // 29\n            double sum = 0.0, sumsq = 0.0;\n            array<double, W> a{}; // size 30\n            for (int j = 0; j < n; j++) {\n                int e = idx_horizontal_edge(i, j);\n                a[j] = w_hat[e];\n                sum += a[j];\n                sumsq += a[j] * a[j];\n            }\n\n            double mean1 = sum / n;\n            double cost1 = sumsq - (double)n * mean1 * mean1;\n\n            // ---- FIX: proper initialization for std::array ----\n            array<double, W> pref{};  // size 30, indices [0..29] used\n            array<double, W> pref2{};\n            pref[0] = 0.0; pref2[0] = 0.0;\n            for (int j = 0; j < n; j++) {\n                pref[j+1] = pref[j] + a[j];\n                pref2[j+1] = pref2[j] + a[j]*a[j];\n            }\n\n            double bestCost = cost1;\n            int bestX = 0;\n            double bestMeanL = mean1, bestMeanR = mean1;\n\n            for (int x = 1; x <= n-1; x++) {\n                int nl = x;\n                int nr = n - x;\n                double sumL = pref[x], sumR = pref[n] - pref[x];\n                double sumsqL = pref2[x], sumsqR = pref2[n] - pref2[x];\n\n                double meanL = sumL / nl;\n                double meanR = sumR / nr;\n\n                double costL = sumsqL - (double)nl * meanL * meanL;\n                double costR = sumsqR - (double)nr * meanR * meanR;\n                double cost = costL + costR;\n\n                if (cost < bestCost) {\n                    bestCost = cost;\n                    bestX = x;\n                    bestMeanL = meanL;\n                    bestMeanR = meanR;\n                }\n            }\n\n            if (bestCost < cost1 * TH) {\n                for (int j = 0; j < n; j++) {\n                    int e = idx_horizontal_edge(i, j);\n                    double target = (j < bestX ? bestMeanL : bestMeanR);\n                    w_hat[e] = (1.0 - alpha) * w_hat[e] + alpha * target;\n                    w_hat[e] = min(HI_W, max(LO_W, w_hat[e]));\n                }\n            } else {\n                for (int j = 0; j < n; j++) {\n                    int e = idx_horizontal_edge(i, j);\n                    w_hat[e] = (1.0 - alpha) * w_hat[e] + alpha * mean1;\n                    w_hat[e] = min(HI_W, max(LO_W, w_hat[e]));\n                }\n            }\n        }\n\n        // Vertical smoothing per column j over edges i=0..28 (29 edges)\n        for (int j = 0; j < W; j++) {\n            int n = H - 1; // 29\n            double sum = 0.0, sumsq = 0.0;\n            array<double, H> a{}; // size 30\n            for (int i = 0; i < n; i++) {\n                int e = idx_vertical_edge(i, j);\n                a[i] = w_hat[e];\n                sum += a[i];\n                sumsq += a[i] * a[i];\n            }\n\n            double mean1 = sum / n;\n            double cost1 = sumsq - (double)n * mean1 * mean1;\n\n            // ---- FIX: proper initialization for std::array ----\n            array<double, H> pref{};   // indices [0..29] used\n            array<double, H> pref2{};\n            pref[0] = 0.0; pref2[0] = 0.0;\n            for (int i = 0; i < n; i++) {\n                pref[i+1] = pref[i] + a[i];\n                pref2[i+1] = pref2[i] + a[i]*a[i];\n            }\n\n            double bestCost = cost1;\n            int bestY = 0;\n            double bestMeanT = mean1, bestMeanB = mean1;\n\n            for (int y = 1; y <= n-1; y++) {\n                int nt = y;\n                int nb = n - y;\n                double sumT = pref[y], sumB = pref[n] - pref[y];\n                double sumsqT = pref2[y], sumsqB = pref2[n] - pref2[y];\n\n                double meanT = sumT / nt;\n                double meanB = sumB / nb;\n\n                double costT = sumsqT - (double)nt * meanT * meanT;\n                double costB = sumsqB - (double)nb * meanB * meanB;\n                double cost = costT + costB;\n\n                if (cost < bestCost) {\n                    bestCost = cost;\n                    bestY = y;\n                    bestMeanT = meanT;\n                    bestMeanB = meanB;\n                }\n            }\n\n            if (bestCost < cost1 * TH) {\n                for (int i = 0; i < n; i++) {\n                    int e = idx_vertical_edge(i, j);\n                    double target = (i < bestY ? bestMeanT : bestMeanB);\n                    w_hat[e] = (1.0 - alpha) * w_hat[e] + alpha * target;\n                    w_hat[e] = min(HI_W, max(LO_W, w_hat[e]));\n                }\n            } else {\n                for (int i = 0; i < n; i++) {\n                    int e = idx_vertical_edge(i, j);\n                    w_hat[e] = (1.0 - alpha) * w_hat[e] + alpha * mean1;\n                    w_hat[e] = min(HI_W, max(LO_W, w_hat[e]));\n                }\n            }\n        }\n    };\n\n    for (int k = 0; k < 1000; k++) {\n        int si, sj, ti, tj;\n        if (!(cin >> si >> sj >> ti >> tj)) return 0;\n        int s = idx_node(si, sj);\n        int t = idx_node(ti, tj);\n\n        // Exploration schedule: prefer noisy Dijkstra early-mid\n        double pNoisy;\n        if (k < 200) pNoisy = 0.35;\n        else if (k < 500) pNoisy = 0.18;\n        else pNoisy = 0.07;\n\n        bool doNoisy = (rand01() < pNoisy);\n        bool doMonoFallback = (!doNoisy && rand01() < 0.03 && k < 250);\n\n        PathResult pr;\n        if (doMonoFallback) {\n            pr = monotone_path(s, t);\n        } else if (doNoisy) {\n            double sigma = 900.0 * (1.0 - min(1.0, (double)k / 700.0)) + 180.0;\n            vector<double> w_noisy(ECOUNT);\n            for (int e = 0; e < ECOUNT; e++) {\n                double w = w_hat[e] + gauss(rng) * sigma;\n                if (w < LO_W) w = LO_W;\n                if (w > HI_W) w = HI_W;\n                w_noisy[e] = w;\n            }\n            pr = dijkstra_path(s, t, &w_noisy);\n            if (pr.moves.empty()) pr = monotone_path(s, t);\n        } else {\n            pr = dijkstra_path(s, t, nullptr);\n            if (pr.moves.empty()) pr = monotone_path(s, t);\n        }\n\n        // Output path\n        cout << pr.moves << '\\n' << flush;\n\n        long long y_int;\n        if (!(cin >> y_int)) return 0;\n\n        int m = (int)pr.usedEdges.size();\n        if (m == 0) continue;\n\n        long double y = (long double)y_int;\n\n        long double pred = 0.0L;\n        for (int e : pr.usedEdges) pred += (long double)w_hat[e];\n\n        long double err = y - pred;\n\n        // Clamp error\n        long double bound = 0.35L * max((long double)1.0L, pred);\n        if (err > bound) err = bound;\n        if (err < -bound) err = -bound;\n\n        // Learning rate\n        long double eta = 0.28L / sqrt((long double)(k + 1));\n        if (eta < 0.003L) eta = 0.003L;\n\n        long double delta = eta * err / (long double)m;\n        if (!isfinite((double)delta)) continue;\n\n        for (int e : pr.usedEdges) {\n            double nw = (double)((long double)w_hat[e] + delta);\n            if (nw < LO_W) nw = LO_W;\n            if (nw > HI_W) nw = HI_W;\n            w_hat[e] = nw;\n        }\n\n        smooth_rows_cols(k);\n    }\n\n    return 0;\n}","ahc004":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 20;\nstatic constexpr int ALPHA = 8; // A..H\n\n// SplitMix64 hash\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 uint64_t keyOfString(const vector<uint8_t>& v) {\n    int len = (int)v.size();\n    uint64_t enc = 0;\n    for (uint8_t x : v) enc = (enc << 3) | (uint64_t)x; // base 8 packing\n    return (uint64_t(len) << 48) | enc;\n}\n\nstruct Solver {\n    int M;\n    vector<string> S;\n    vector<vector<uint8_t>> scodes;\n    vector<int> slen;\n    vector<uint64_t> skey;\n\n    // distinct string keys (exact sequences by length+content)\n    int K;\n    vector<int> mult;     // multiplicity per key id\n    vector<int> occ;      // occurrence count per key in current grid\n    long long curC = 0;   // sum mult[id] where occ[id] > 0\n    int bestC = -1;\n    array<array<uint8_t, N>, N> g{};\n    array<array<uint8_t, N>, N> bestG{};\n\n    unordered_map<uint64_t, int, decltype(&splitmix64)> idByKey;\n\n    bool needLen[13]{};\n    vector<int> neededLens;\n    uint64_t maskLower[13]{};\n\n    // overlap maps for greedy construction\n    // prefixCand[ov][prefEnc] -> list of indices whose prefix of length ov equals prefEnc\n    // suffixCand[ov][sufEnc] -> list of indices whose suffix of length ov equals sufEnc\n    vector<unordered_map<uint64_t, vector<int>, decltype(&splitmix64)>> prefixCand, suffixCand;\n\n    mt19937_64 rng;\n\n    Solver() : rng((uint64_t)chrono::steady_clock::now().time_since_epoch().count()),\n               idByKey(1024, splitmix64) {}\n\n    uint8_t charToCode(char c) { return (uint8_t)(c - 'A'); }\n\n    uint64_t encFromSeq(const vector<uint8_t>& v, int l, int r) {\n        uint64_t enc = 0;\n        for (int i = l; i < r; i++) enc = (enc << 3) | v[i];\n        return enc;\n    }\n\n    void buildObjectiveStructures() {\n        idByKey.clear();\n        mult.clear();\n\n        for (int k = 0; k <= 12; k++) needLen[k] = false;\n\n        K = 0;\n        for (int i = 0; i < M; i++) {\n            uint64_t key = skey[i];\n            auto it = idByKey.find(key);\n            if (it == idByKey.end()) {\n                int id = K++;\n                idByKey.emplace(key, id);\n                mult.push_back(1);\n            } else {\n                mult[it->second]++;\n            }\n            needLen[slen[i]] = true;\n        }\n        neededLens.clear();\n        for (int k = 2; k <= 12; k++) if (needLen[k]) neededLens.push_back(k);\n\n        // Precompute masks for sliding\n        for (int k = 2; k <= 12; k++) {\n            int bits = 3 * (k - 1);\n            maskLower[k] = (bits >= 64) ? ~0ULL : ((1ULL << bits) - 1ULL);\n        }\n        occ.assign(K, 0);\n    }\n\n    void buildOverlapMaps() {\n        prefixCand.assign(13, unordered_map<uint64_t, vector<int>, decltype(&splitmix64)>(0, splitmix64));\n        suffixCand.assign(13, unordered_map<uint64_t, vector<int>, decltype(&splitmix64)>(0, splitmix64));\n\n        for (int i = 0; i < M; i++) {\n            int L = slen[i];\n            for (int ov = 2; ov <= L - 1; ov++) {\n                uint64_t pref = encFromSeq(scodes[i], 0, ov);\n                uint64_t suf  = encFromSeq(scodes[i], L - ov, L);\n                prefixCand[ov][pref].push_back(i);\n                suffixCand[ov][suf].push_back(i);\n            }\n        }\n    }\n\n    inline void updateLine(bool isRow, int idx, int delta) {\n        // delta: +1 (add contributions) or -1 (remove contributions) for that line only\n        uint8_t ext[2 * N];\n        if (isRow) {\n            for (int t = 0; t < 2 * N; t++) ext[t] = g[idx][t % N];\n        } else {\n            for (int t = 0; t < 2 * N; t++) ext[t] = g[t % N][idx];\n        }\n\n        for (int k : neededLens) {\n            uint64_t enc = 0;\n            for (int t = 0; t < k; t++) enc = (enc << 3) | (uint64_t)ext[t];\n\n            for (int start = 0; start < N; start++) {\n                uint64_t key = (uint64_t(k) << 48) | enc;\n                auto it = idByKey.find(key);\n                if (it != idByKey.end()) {\n                    int id = it->second;\n                    int before = occ[id];\n                    if (delta == +1) {\n                        occ[id] = before + 1;\n                        if (before == 0) curC += mult[id];\n                    } else {\n                        occ[id] = before - 1;\n                        if (before == 1) curC -= mult[id];\n                    }\n                }\n                if (start == N - 1) break;\n                enc = ((enc & maskLower[k]) << 3) | (uint64_t)ext[start + k];\n            }\n        }\n    }\n\n    void computeInitialCounts() {\n        fill(occ.begin(), occ.end(), 0);\n        curC = 0;\n\n        // rows\n        for (int i = 0; i < N; i++) updateLine(true, i, +1);\n        // columns\n        for (int j = 0; j < N; j++) updateLine(false, j, +1);\n\n        // IMPORTANT FIX:\n        // do NOT overwrite global bestC/bestG here.\n    }\n\n    inline void setCell(int i, int j, uint8_t nv) {\n        uint8_t old = g[i][j];\n        if (old == nv) return;\n\n        updateLine(true, i, -1);\n        updateLine(false, j, -1);\n\n        g[i][j] = nv;\n\n        updateLine(true, i, +1);\n        updateLine(false, j, +1);\n    }\n\n    void randomFillRow(array<uint8_t, N>& row) {\n        for (int j = 0; j < N; j++) row[j] = (uint8_t)(rng() % ALPHA);\n    }\n\n    void buildInitialGridGreedy() {\n        // Build a decent starting point by row assembly.\n        // coveredKeys[k] stores cyclic horizontal substrings of length k already present.\n        vector<unordered_set<uint64_t, decltype(&splitmix64)>> coveredKeys(13, unordered_set<uint64_t, decltype(&splitmix64)>(0, splitmix64));\n        vector<char> coveredInput(M, 0);\n\n        for (int k = 2; k <= 12; k++) if (needLen[k]) {\n            coveredKeys[k] = unordered_set<uint64_t, decltype(&splitmix64)>(0, splitmix64);\n            coveredKeys[k].reserve(1 << 12);\n        }\n\n        auto addRowToCovered = [&](int rowIdx, const array<uint8_t, N>& row) {\n            for (int k : neededLens) {\n                uint64_t enc = 0;\n                for (int t = 0; t < k; t++) enc = (enc << 3) | row[t];\n                for (int start = 0; start < N; start++) {\n                    uint64_t key = (uint64_t(k) << 48) | enc;\n                    coveredKeys[k].insert(key);\n                    if (start == N - 1) break;\n                    enc = ((enc & maskLower[k]) << 3) | row[(start + k) % N];\n                }\n            }\n        };\n\n        auto updateCoveredInputFromRowSets = [&]() {\n            for (int i = 0; i < M; i++) {\n                if (coveredInput[i]) continue;\n                int k = slen[i];\n                uint64_t key = skey[i];\n                if (coveredKeys[k].find(key) != coveredKeys[k].end()) coveredInput[i] = 1;\n            }\n        };\n\n        int minOverlap = 2;\n\n        for (int i = 0; i < N; i++) {\n            // choose seed string not yet horizontally covered, prefer longer\n            int bestL = -1;\n            vector<int> bestIdx;\n            for (int idx = 0; idx < M; idx++) {\n                if (coveredInput[idx]) continue;\n                if (slen[idx] > bestL) {\n                    bestL = slen[idx];\n                    bestIdx.clear();\n                    bestIdx.push_back(idx);\n                } else if (slen[idx] == bestL) {\n                    bestIdx.push_back(idx);\n                }\n            }\n\n            array<uint8_t, N> row{};\n            if (bestL < 0) {\n                randomFillRow(row);\n                for (int j = 0; j < N; j++) g[i][j] = row[j];\n                addRowToCovered(i, row);\n                updateCoveredInputFromRowSets();\n                continue;\n            }\n\n            int seed = bestIdx[rng() % (int)bestIdx.size()];\n            vector<uint8_t> seq = scodes[seed];\n\n            // Expand to length N by overlapping with input strings\n            while ((int)seq.size() < N) {\n                int curLen = (int)seq.size();\n                int maxOv = min(curLen - 1, 11);\n\n                int bestRightLen = curLen, bestRightIdx = -1, bestRightOv = -1;\n                for (int ov = maxOv; ov >= minOverlap; ov--) {\n                    uint64_t sufEnc = 0;\n                    for (int t = curLen - ov; t < curLen; t++) sufEnc = (sufEnc << 3) | seq[t];\n                    auto it = prefixCand[ov].find(sufEnc);\n                    if (it == prefixCand[ov].end()) continue;\n                    for (int candIdx : it->second) {\n                        if (slen[candIdx] <= ov) continue;\n                        int newLen = curLen + slen[candIdx] - ov;\n                        if (newLen <= N && newLen > bestRightLen) {\n                            bestRightLen = newLen;\n                            bestRightIdx = candIdx;\n                            bestRightOv = ov;\n                        }\n                    }\n                }\n\n                int bestLeftLen = curLen, bestLeftIdx = -1, bestLeftOv = -1;\n                for (int ov = maxOv; ov >= minOverlap; ov--) {\n                    uint64_t prefEnc = 0;\n                    for (int t = 0; t < ov; t++) prefEnc = (prefEnc << 3) | seq[t];\n                    auto it = suffixCand[ov].find(prefEnc);\n                    if (it == suffixCand[ov].end()) continue;\n                    for (int candIdx : it->second) {\n                        if (slen[candIdx] <= ov) continue;\n                        int newLen = curLen + slen[candIdx] - ov;\n                        if (newLen <= N && newLen > bestLeftLen) {\n                            bestLeftLen = newLen;\n                            bestLeftIdx = candIdx;\n                            bestLeftOv = ov;\n                        }\n                    }\n                }\n\n                int finalLen = max(bestRightLen, bestLeftLen);\n                if (finalLen == curLen) break;\n\n                bool takeRight;\n                if (bestRightLen > bestLeftLen) takeRight = true;\n                else if (bestLeftLen > bestRightLen) takeRight = false;\n                else takeRight = (rng() & 1);\n\n                if (takeRight) {\n                    auto& cv = scodes[bestRightIdx];\n                    int ov = bestRightOv;\n                    for (int t = ov; t < (int)cv.size() && (int)seq.size() < N; t++) seq.push_back(cv[t]);\n                } else {\n                    auto& cv = scodes[bestLeftIdx];\n                    int ov = bestLeftOv;\n                    vector<uint8_t> nseq;\n                    nseq.reserve(N);\n                    for (int t = 0; t < (int)cv.size() - ov && (int)nseq.size() < N; t++) nseq.push_back(cv[t]);\n                    for (uint8_t x : seq) {\n                        if ((int)nseq.size() >= N) break;\n                        nseq.push_back(x);\n                    }\n                    seq.swap(nseq);\n                }\n            }\n\n            while ((int)seq.size() < N) seq.push_back((uint8_t)(rng() % ALPHA));\n            for (int j = 0; j < N; j++) {\n                row[j] = seq[j];\n                g[i][j] = row[j];\n            }\n\n            addRowToCovered(i, row);\n            updateCoveredInputFromRowSets();\n        }\n    }\n\n    void solveOneRun(int steps, long double Tstart, long double Tmin, chrono::steady_clock::time_point deadline) {\n        long double T = Tstart;\n        long double alpha = pow((double)(Tmin / Tstart), 1.0L / (long double)steps);\n\n        for (int it = 0; it < steps; it++) {\n            if (chrono::steady_clock::now() >= deadline) break;\n\n            int i = (int)(rng() % N);\n            int j = (int)(rng() % N);\n\n            uint8_t old = g[i][j];\n            uint8_t nv = old;\n            while (nv == old) nv = (uint8_t)(rng() % ALPHA);\n\n            long long beforeC = curC;\n            setCell(i, j, nv);\n            long long afterC = curC;\n\n            bool accept = false;\n            if (afterC >= beforeC) {\n                accept = true;\n            } else {\n                long double prob = expl((long double)(afterC - beforeC) / T);\n                long double r = (long double)(rng() % 1000000) / 1000000.0L;\n                if (r < prob) accept = true;\n            }\n\n            if (accept) {\n                if (afterC > bestC) {\n                    bestC = (int)afterC;\n                    bestG = g;\n                }\n            } else {\n                // revert\n                setCell(i, j, old);\n            }\n\n            T *= alpha;\n            if (T < 1e-7L) T = 1e-7L;\n        }\n    }\n\n    void run() {\n        ios::sync_with_stdio(false);\n        cin.tie(nullptr);\n\n        int Nread;\n        cin >> Nread >> M; // N fixed to 20 but read anyway\n\n        S.resize(M);\n        for (int i = 0; i < M; i++) cin >> S[i];\n\n        scodes.assign(M, {});\n        slen.assign(M, 0);\n        skey.assign(M, 0);\n\n        for (int i = 0; i < M; i++) {\n            const string& s = S[i];\n            slen[i] = (int)s.size();\n            vector<uint8_t> v(s.size());\n            for (int t = 0; t < (int)s.size(); t++) v[t] = charToCode(s[t]);\n            scodes[i] = std::move(v);\n            skey[i] = keyOfString(scodes[i]);\n        }\n\n        buildObjectiveStructures();\n        buildOverlapMaps();\n\n        // Initialize grid\n        buildInitialGridGreedy();\n        auto baseG = g;\n\n        // improve expected performance: reserve more buckets\n        idByKey.reserve((size_t)K * 2);\n\n        bestC = -1;\n        bestG = g;\n\n        const auto globalStart = chrono::steady_clock::now();\n        const auto deadline = globalStart + chrono::milliseconds(2850); // keep margin\n\n        int restarts = 6;\n        for (int r = 0; r < restarts; r++) {\n            if (chrono::steady_clock::now() >= deadline) break;\n\n            g = baseG;\n\n            int perturb = (r == 0 ? 0 : 30 + 15 * r);\n            for (int t = 0; t < perturb; t++) {\n                int i = (int)(rng() % N);\n                int j = (int)(rng() % N);\n                uint8_t nv = (uint8_t)(rng() % ALPHA);\n                if (nv == g[i][j]) nv = (nv + 1) % ALPHA;\n                g[i][j] = nv;\n            }\n\n            computeInitialCounts();\n            if (curC > bestC) {\n                bestC = (int)curC;\n                bestG = g;\n            }\n\n            // Remaining steps adapt to time\n            int steps = 120000 + 20000 * r;\n            solveOneRun(steps, 4.0L, 0.10L, deadline);\n        }\n\n        for (int i = 0; i < N; i++) {\n            string row;\n            row.reserve(N);\n            for (int j = 0; j < N; j++) row.push_back(char('A' + bestG[i][j]));\n            cout << row << '\\n';\n        }\n    }\n};\n\nint main() {\n    Solver s;\n    s.run();\n    return 0;\n}","ahc005":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct DSU {\n    int n;\n    vector<int> p, r;\n    DSU(int n=0): n(n), p(n), r(n,0) { iota(p.begin(), p.end(), 0); }\n    int find(int x){ return p[x]==x? x : p[x]=find(p[x]); }\n    bool unite(int a,int b){\n        a=find(a); b=find(b);\n        if(a==b) return false;\n        if(r[a]<r[b]) swap(a,b);\n        p[b]=a;\n        if(r[a]==r[b]) r[a]++;\n        return true;\n    }\n};\n\nstruct Edge {\n    int u, v;\n    int baseCost; // w[u]+w[v]\n    int id;        // undirected edge id in the component graph\n};\n\nstatic inline char dirChar(pair<int,int> a, pair<int,int> b){\n    int ar=a.first, ac=a.second, br=b.first, bc=b.second;\n    if(br==ar-1 && bc==ac) return 'U';\n    if(br==ar+1 && bc==ac) return 'D';\n    if(br==ar && bc==ac-1) return 'L';\n    return 'R'; // br==ar && bc==ac+1\n}\n\nstruct TourResult{\n    bool ok=false;\n    long long t = (1LL<<62);\n    string route;\n};\n\nstatic TourResult doubledTreeTour(\n    int m, int sidx,\n    const vector<vector<int>>& treeAdj,\n    const vector<pair<int,int>>& cells,\n    const vector<int>& wts\n){\n    if(m==1){\n        TourResult res; res.ok=true; res.t=0; res.route=\"\"; return res;\n    }\n\n    // Build route by DFS doubling edges: parent->child then return.\n    string route;\n    route.reserve(2*(m-1));\n\n    struct Frame{ int u,p; int it; };\n    vector<Frame> st;\n    st.reserve(m);\n    st.push_back({sidx, -1, 0});\n\n    vector<int> iters(m,0);\n\n    // For speed compute t via formula:\n    // doubled-tree tour uses both directions of each tree edge exactly once:\n    // t = sum_{(u,v) in treeEdges} (w[u] + w[v])\n    // We'll compute by summing degrees/2 edges via iterating adj with u<v.\n    // But we don't have list of edges here; still can compute from adjacency: sum w[u]*deg?:\n    // Each vertex u participates in cost proportional to w[u]*deg(u) in tree.\n    // In doubled tour, each undirected tree edge contributes entering both endpoints once.\n    // So total t = sum_u w[u] * deg_tree(u).\n    long long t = 0;\n    for(int u=0;u<m;u++) t += 1LL*wts[u] * (long long)treeAdj[u].size();\n\n    while(!st.empty()){\n        auto &top = st.back();\n        int u = top.u;\n\n        if(top.it < (int)treeAdj[u].size()){\n            int v = treeAdj[u][top.it++];\n            if(v==top.p) continue;\n            route.push_back(dirChar(cells[u], cells[v]));\n            st.push_back({v, u, 0});\n        }else{\n            int p = top.p;\n            st.pop_back();\n            if(!st.empty()){\n                // return to parent p (which is current stack top)\n                int parent = st.back().u;\n                route.push_back(dirChar(cells[u], cells[parent]));\n            }\n        }\n    }\n\n    // Basic sanity: closed walk\n    // (For doubled DFS on tree it must start/end at sidx)\n    return TourResult{true, t, route};\n}\n\nstatic TourResult augmentedEulerTour(\n    int m, int sidx,\n    const vector<pair<int,int>>& cells,\n    const vector<int>& wts,\n    const vector<vector<pair<int,int>>>& adj2, // (neighbor, edgeId)\n    const vector<int>& eu,\n    const vector<int>& ev,\n    const vector<Edge>& allEdges, // undirected edges with ids\n    const vector<int>& mstEdgeIds, // tree edges selected in this attempt\n    const vector<int>& mstDeg // degrees in MST\n){\n    // Build list of odd vertices in MST\n    vector<int> odd;\n    odd.reserve(m);\n    for(int u=0;u<m;u++){\n        if(mstDeg[u] % 2 == 1) odd.push_back(u);\n    }\n    if(odd.empty()){\n        // impossible for a tree with m>1, but handle\n        TourResult res;\n        res.ok = true;\n        res.route = \"\";\n        res.t = 0;\n        return res;\n    }\n\n    int E = (int)eu.size();\n    // Multi-source Dijkstra on symmetric costs baseCost = w[u]+w[v]\n    const long long INF = (1LL<<60);\n    vector<long long> dist(m, INF);\n    vector<int> src(m, -1);\n    vector<int> parent(m, -1);\n\n    // PQ entries: (dist, node)\n    using P = pair<long long,int>;\n    priority_queue<P, vector<P>, greater<P>> pq;\n    for(int s : odd){\n        dist[s] = 0;\n        src[s] = s;\n        parent[s] = -1;\n        pq.push({0, s});\n    }\n\n    while(!pq.empty()){\n        auto [d,u] = pq.top(); pq.pop();\n        if(d != dist[u]) continue;\n        for(auto [v, eid] : adj2[u]){\n            (void)eid;\n            long long nd = d + (long long)wts[u] + (long long)wts[v];\n            if(nd < dist[v]){\n                dist[v] = nd;\n                src[v] = src[u];\n                parent[v] = u;\n                pq.push({nd, v});\n            }\n        }\n    }\n\n    for(int u=0;u<m;u++){\n        if(src[u]==-1) return TourResult(); // should not happen\n    }\n\n    // Candidate pairs from edges crossing different source regions\n    struct Cand {\n        long long cost;\n        int a,b;\n        int meetX, meetY;\n        bool operator<(Cand const& other) const{\n            if(cost != other.cost) return cost < other.cost;\n            if(a != other.a) return a < other.a;\n            if(b != other.b) return b < other.b;\n            return meetX < other.meetX;\n        }\n    };\n    vector<Cand> cands;\n    cands.reserve(E);\n\n    for(int eid=0; eid<E; eid++){\n        int a0 = eu[eid], b0 = ev[eid];\n        int sa = src[a0], sb = src[b0];\n        if(sa==-1 || sb==-1 || sa==sb) continue;\n        // candidate path using edge (a0,b0)\n        long long cost = dist[a0] + dist[b0] + (long long)wts[a0] + (long long)wts[b0];\n        cands.push_back({cost, sa, sb, a0, b0});\n    }\n    sort(cands.begin(), cands.end());\n\n    vector<char> matched(m, 0);\n    vector<int> partner(m, -1);\n\n    struct PairInfo{ int a,b; int meetX, meetY; };\n    vector<PairInfo> pairs;\n    pairs.reserve(odd.size()/2);\n\n    for(auto &cd : cands){\n        int a = cd.a, b = cd.b;\n        if(a<0 || b<0) continue;\n        if(!matched[a] && !matched[b]){\n            matched[a]=matched[b]=1;\n            partner[a]=b;\n            partner[b]=a;\n            pairs.push_back({a,b,cd.meetX,cd.meetY});\n        }\n    }\n\n    // Fallback matching for any remaining unmatched odds\n    vector<int> rem;\n    rem.reserve(odd.size());\n    for(int u : odd) if(!matched[u]) rem.push_back(u);\n\n    auto addMul = [&](vector<long long>& cnt, int x, int y){\n        // find edgeId between x and y by scanning small degree list\n        for(auto [to, eid] : adj2[x]){\n            if(to==y){\n                cnt[eid]++;\n                return;\n            }\n        }\n        // should never happen\n        assert(false);\n    };\n\n    vector<long long> cnt(E, 0);\n    // base: include each MST edge once\n    for(int eid : mstEdgeIds) cnt[eid] = 1;\n\n    // Add paths for matched pairs using multi-source parent chains + the meeting edge\n    for(auto &pr : pairs){\n        int a = pr.a, b = pr.b;\n        int x = pr.meetX, y = pr.meetY;\n\n        // Ensure src[x]=a and src[y]=b (by construction). Still safe to use parent chains.\n        int cur = x;\n        while(cur != a){\n            int p = parent[cur];\n            assert(p!=-1);\n            addMul(cnt, cur, p);\n            cur = p;\n        }\n        addMul(cnt, x, y);\n        cur = y;\n        while(cur != b){\n            int p = parent[cur];\n            assert(p!=-1);\n            addMul(cnt, cur, p);\n            cur = p;\n        }\n    }\n\n    // Now handle remaining odds\n    // Pair them greedily by closest odd via single-source Dijkstra\n    while(rem.size() >= 2){\n        int a = rem.back(); rem.pop_back();\n\n        // Dijkstra from a (symmetric costs) to compute distances + parent\n        vector<long long> d2(m, INF);\n        vector<int> par2(m, -1);\n        priority_queue<P, vector<P>, greater<P>> pq2;\n        d2[a]=0; par2[a]=-1; pq2.push({0,a});\n\n        vector<char> isOddRem(m,0);\n        for(int u : rem) isOddRem[u]=1;\n\n        int bestB = -1;\n        long long bestD = INF;\n\n        while(!pq2.empty()){\n            auto [d,u]=pq2.top(); pq2.pop();\n            if(d!=d2[u]) continue;\n            if(d >= bestD) continue;\n            if(isOddRem[u]){\n                bestD = d;\n                bestB = u;\n                // we can break because PQ gives increasing dist\n                break;\n            }\n            for(auto [v, eid] : adj2[u]){\n                (void)eid;\n                long long nd = d + (long long)wts[u] + (long long)wts[v];\n                if(nd < d2[v]){\n                    d2[v]=nd;\n                    par2[v]=u;\n                    pq2.push({nd, v});\n                }\n            }\n        }\n        if(bestB==-1) return TourResult(); // should not happen in connected component\n\n        // Remove bestB from rem\n        {\n            int idx = -1;\n            for(int i=0;i<(int)rem.size();i++){\n                if(rem[i]==bestB){ idx=i; break; }\n            }\n            assert(idx!=-1);\n            rem[idx] = rem.back();\n            rem.pop_back();\n        }\n\n        // Add shortest path from bestB to a using par2 chain\n        int cur = bestB;\n        while(cur != a){\n            int p = par2[cur];\n            assert(p!=-1);\n            addMul(cnt, cur, p);\n            cur = p;\n        }\n    }\n\n    if(!rem.empty()){\n        // Odd count must be even; should never leave one unmatched\n        return TourResult();\n    }\n\n    // Build incidence list for Euler with edge IDs\n    vector<vector<int>> inc(m);\n    inc.assign(m, {});\n    for(int eid=0; eid<E; eid++){\n        inc[eu[eid]].push_back(eid);\n        inc[ev[eid]].push_back(eid);\n    }\n\n    // Ensure Euler circuit exists: all degrees even in multigraph\n    // We'll just check parity quickly\n    vector<int> deg(m,0);\n    for(int eid=0; eid<E; eid++){\n        if(cnt[eid]==0) continue;\n        long long k = cnt[eid];\n        // Each of the two endpoints degree += k (each parallel edge adds 1 incident degree)\n        deg[eu[eid]] += (int)(k % 2);\n        deg[ev[eid]] += (int)(k % 2);\n    }\n    for(int u=0;u<m;u++){\n        if(deg[u]%2 != 0) return TourResult();\n    }\n\n    // Hierholzer with multiplicities\n    vector<int> ptr(m,0);\n    vector<int> stackV;\n    vector<int> circuitRev;\n    stackV.reserve(1);\n    circuitRev.reserve(1);\n\n    stackV.push_back(sidx);\n\n    auto otherEnd = [&](int eid, int u)->int{\n        return (u==eu[eid]? ev[eid] : eu[eid]);\n    };\n\n    while(!stackV.empty()){\n        int u = stackV.back();\n        auto &vec = inc[u];\n        while(ptr[u] < (int)vec.size() && cnt[vec[ptr[u]]] == 0) ptr[u]++;\n        if(ptr[u] == (int)vec.size()){\n            circuitRev.push_back(u);\n            stackV.pop_back();\n        }else{\n            int eid = vec[ptr[u]];\n            // use one unit of this edge\n            cnt[eid]--;\n            int v = otherEnd(eid, u);\n            stackV.push_back(v);\n        }\n    }\n\n    if(circuitRev.empty()) return TourResult();\n    reverse(circuitRev.begin(), circuitRev.end());\n\n    if(circuitRev.front() != sidx || circuitRev.back() != sidx) return TourResult();\n\n    // compute time t = sum w[nextVertex]\n    long long t = 0;\n    for(int i=1;i<(int)circuitRev.size();i++){\n        int v = circuitRev[i];\n        t += wts[v];\n    }\n\n    // build route string\n    string route;\n    route.reserve(max(0, (int)circuitRev.size()-1));\n    for(int i=0;i+1<(int)circuitRev.size();i++){\n        int a = circuitRev[i], b = circuitRev[i+1];\n        route.push_back(dirChar(cells[a], cells[b]));\n    }\n\n    return TourResult{true, t, route};\n}\n\nint main(){\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, si, sj;\n    cin >> N >> si >> sj;\n    vector<string> g(N);\n    for(int i=0;i<N;i++) cin >> g[i];\n\n    auto inside = [&](int r,int c){ return 0<=r && r<N && 0<=c && c<N; };\n\n    // Build road component reachable from (si,sj)\n    vector<vector<int>> idx(N, vector<int>(N, -1));\n    vector<pair<int,int>> cells;\n    vector<int> wts;\n\n    queue<pair<int,int>> q;\n    vector<vector<char>> vis(N, vector<char>(N, 0));\n    q.push({si,sj});\n    vis[si][sj]=1;\n\n    int dr[4]={-1,1,0,0};\n    int dc[4]={0,0,-1,1};\n\n    while(!q.empty()){\n        auto [r,c]=q.front(); q.pop();\n        int id = (int)cells.size();\n        idx[r][c]=id;\n        cells.push_back({r,c});\n        wts.push_back(g[r][c]-'0');\n\n        for(int k=0;k<4;k++){\n            int nr=r+dr[k], nc=c+dc[k];\n            if(!inside(nr,nc)) continue;\n            if(vis[nr][nc]) continue;\n            if(g[nr][nc]=='#') continue;\n            vis[nr][nc]=1;\n            q.push({nr,nc});\n        }\n    }\n\n    int m = (int)cells.size();\n    int sidx = idx[si][sj];\n\n    if(m==1){\n        cout << \"\\n\";\n        return 0;\n    }\n\n    // Build component graph adjacency with edge IDs\n    vector<vector<pair<int,int>>> adj2(m); // (neighbor, edgeId)\n    vector<int> eu, ev;\n    eu.reserve(2*m);\n    ev.reserve(2*m);\n\n    auto addAdjEdge = [&](int u,int v){\n        // create undirected edge id once (only call with u<v)\n        int eid = (int)eu.size();\n        eu.push_back(u);\n        ev.push_back(v);\n        adj2[u].push_back({v,eid});\n        adj2[v].push_back({u,eid});\n    };\n\n    for(int u=0;u<m;u++){\n        auto [r,c]=cells[u];\n        const int rr[4]={r-1,r+1,r,r};\n        const int cc[4]={c,c,c-1,c+1};\n        for(int k=0;k<4;k++){\n            int nr=rr[k], nc=cc[k];\n            if(!inside(nr,nc)) continue;\n            int v = idx[nr][nc];\n            if(v==-1) continue;\n            if(u < v) addAdjEdge(u,v);\n        }\n    }\n\n    int E = (int)eu.size();\n    // Build edge list for MST Kruskal\n    vector<Edge> allEdges;\n    allEdges.reserve(E);\n    for(int eid=0; eid<E; eid++){\n        int a=eu[eid], b=ev[eid];\n        int cost = wts[a] + wts[b];\n        allEdges.push_back({a,b,cost,eid});\n    }\n\n    // Baseline: choose an MST (deterministic) and do doubled-tree tour\n    auto buildMST = [&](mt19937_64 &rng, bool randomTies)->pair<vector<int>, vector<int>>{\n        // returns (mstEdgeIds, mstDeg)\n        vector<int> ord(allEdges.size());\n        iota(ord.begin(), ord.end(), 0);\n\n        vector<int> noise(allEdges.size(),0);\n        if(randomTies){\n            for(int i=0;i<(int)allEdges.size();i++){\n                noise[i] = (int)(rng()%3); // small tie perturb\n            }\n        }\n\n        sort(ord.begin(), ord.end(), [&](int i, int j){\n            const auto &ei = allEdges[i];\n            const auto &ej = allEdges[j];\n            if(ei.baseCost != ej.baseCost) return ei.baseCost < ej.baseCost;\n            if(randomTies) return noise[i] < noise[j];\n            return ei.id < ej.id;\n        });\n\n        DSU dsu(m);\n        vector<int> mstEdgeIds;\n        mstEdgeIds.reserve(m-1);\n        vector<int> mstDeg(m,0);\n\n        for(int idxE : ord){\n            auto &e = allEdges[idxE];\n            if(dsu.unite(e.u, e.v)){\n                mstEdgeIds.push_back(e.id);\n                mstDeg[e.u]++; mstDeg[e.v]++;\n                if((int)mstEdgeIds.size()==m-1) break;\n            }\n        }\n        if((int)mstEdgeIds.size()!=m-1){\n            // should not happen (component connected)\n            // return empty invalid\n            return {vector<int>(), vector<int>()};\n        }\n        return {mstEdgeIds, mstDeg};\n    };\n\n    auto buildTreeAdjFromEdges = [&](const vector<int>& mstEdgeIds){\n        vector<vector<int>> treeAdj(m);\n        for(int eid : mstEdgeIds){\n            int a=eu[eid], b=ev[eid];\n            treeAdj[a].push_back(b);\n            treeAdj[b].push_back(a);\n        }\n        return treeAdj;\n    };\n\n    mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());\n\n    // baseline MST\n    {\n        auto [mstEdgeIds, mstDeg] = buildMST(rng, false);\n        auto treeAdj = buildTreeAdjFromEdges(mstEdgeIds);\n        TourResult base = doubledTreeTour(m, sidx, treeAdj, cells, wts);\n        // We'll still attempt augmented and take best.\n        TourResult best = base;\n\n        int attempts = 7; // baseline + attempts\n        for(int it=0; it<attempts; it++){\n            auto [mstEdgeIds2, mstDeg2] = buildMST(rng, true);\n            if(mstEdgeIds2.empty()) continue;\n\n            TourResult aug = augmentedEulerTour(\n                m, sidx, cells, wts, adj2, eu, ev,\n                allEdges, mstEdgeIds2, mstDeg2\n            );\n            if(aug.ok && aug.t < best.t){\n                best = std::move(aug);\n            }\n        }\n        cout << best.route << \"\\n\";\n        return 0;\n    }\n}","future-contest-2022-qual":"#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, K, R;\n    cin >> N >> M >> K >> R;\n\n    vector<double> p(N, 0.0);      // sqrt(sum d^2)\n    vector<long long> p2(N, 0LL); // sum d^2 (for tie-break)\n\n    for (int i = 0; i < N; i++) {\n        long long sum = 0;\n        for (int k = 0; k < K; k++) {\n            long long x;\n            cin >> x;\n            sum += x * x;\n        }\n        p2[i] = sum;\n        p[i] = sqrt((double)sum);\n    }\n\n    vector<vector<int>> out(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        out[u].push_back(v);\n        indeg[v]++;\n    }\n\n    // ---- Static time-based criticality (integer scaled) ----\n    // Use a global ability guess A0 to build a rough proxy duration.\n    const double A0 = 35.0;\n    const long long SCALE = 1000LL;\n\n    vector<long long> timeProxyInt(N);\n    for (int i = 0; i < N; i++) {\n        double diff = p[i] - A0;\n        double wprime = max(0.0, diff);\n        double tproxy = 1.0 + wprime; // consistent with proxy used for scoring\n        timeProxyInt[i] = (long long)llround(tproxy * (double)SCALE);\n    }\n\n    vector<long long> critInt(N, 0);\n    for (int i = N - 1; i >= 0; i--) {\n        long long bestChild = 0;\n        for (int v : out[i]) bestChild = max(bestChild, critInt[v]);\n        critInt[i] = timeProxyInt[i] + bestChild;\n    }\n    long long maxCritInt = 0;\n    for (int i = 0; i < N; i++) maxCritInt = max(maxCritInt, critInt[i]);\n\n    // Ready set ordered by: higher criticality, then smaller difficulty norm, then id.\n    struct Comp {\n        const vector<long long>* crit;\n        const vector<long long>* p2;\n        bool operator()(int a, int b) const {\n            if ((*crit)[a] != (*crit)[b]) return (*crit)[a] > (*crit)[b];\n            if ((*p2)[a] != (*p2)[b]) return (*p2)[a] < (*p2)[b];\n            return a < b;\n        }\n    };\n    Comp comp{&critInt, &p2};\n    set<int, Comp> ready(comp);\n\n    vector<char> state(N, 0); // 0 unstarted, 1 running, 2 done\n    for (int i = 0; i < N; i++) if (indeg[i] == 0) ready.insert(i);\n\n    vector<int> curTask(M, -1);\n    vector<int> startDay(M, -1);\n\n    // ---- Learning parameters per member ----\n    // param[j] ~ threshold on p such that deficit ~ max(0, p_i - param[j])\n    // Bounds LB/UB maintained by observations.\n    const double NEG_INF = -1e100, POS_INF = 1e100;\n    vector<double> LB(M, NEG_INF), UB(M, POS_INF);\n    vector<double> param(M, A0);\n\n    auto recomputeParam = [&](int j) {\n        double lb = LB[j], ub = UB[j];\n        double x;\n        bool lbOk = (lb > NEG_INF/2);\n        bool ubOk = (ub < POS_INF/2);\n        if (!lbOk && !ubOk) x = A0;\n        else if (!lbOk) x = ub - 2.5;\n        else if (!ubOk) x = lb + 2.5;\n        else x = 0.5 * (lb + ub);\n\n        x = min(100.0, max(0.0, x));\n        param[j] = x;\n    };\n\n    // Estimate expected duration under proxy: E[t] ~ 1 + max(0, p_i - param[j])\n    auto estimateExpected = [&](int j, int task) -> double {\n        double diff = p[task] - param[j];\n        double wprime = max(0.0, diff);\n        return 1.0 + wprime;\n    };\n\n    // Score: shorter expected time is better; also favor critical tasks.\n    auto estimateScore = [&](int j, int task) -> double {\n        double expT = estimateExpected(j, task);\n        double critNorm = (maxCritInt ? (double)critInt[task] / (double)maxCritInt : 0.0);\n        const double beta = 2.0;\n        double denom = 1.0 + beta * critNorm;\n        return expT / denom;\n    };\n\n    mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());\n\n    int day = 1;\n    const int LCAND = 200; // improved from ~60\n\n    while (day <= 2000) {\n        vector<int> idle;\n        idle.reserve(M);\n        for (int j = 0; j < M; j++) if (curTask[j] == -1) idle.push_back(j);\n\n        // Stronger first (larger param => easier tasks => smaller deficit)\n        sort(idle.begin(), idle.end(), [&](int a, int b) {\n            if (param[a] != param[b]) return param[a] > param[b];\n            return a < b;\n        });\n\n        vector<pair<int,int>> assign; // (member, task)\n        assign.reserve(M);\n\n        // For each idle member choose best task from top LCAND of ready-set.\n        for (int j : idle) {\n            if (ready.empty()) break;\n\n            int bestTask = -1;\n            double bestScore = 1e100;\n            auto itBest = ready.end();\n\n            int cnt = 0;\n            for (auto it = ready.begin(); it != ready.end() && cnt < LCAND; ++it, ++cnt) {\n                int t = *it;\n                // (state[t] should be 0 here, but safe)\n                if (state[t] != 0) continue;\n\n                double sc = estimateScore(j, t);\n\n                // tiny random tie-breaker\n                sc += uniform_real_distribution<double>(0.0, 1e-7)(rng);\n\n                if (sc < bestScore) {\n                    bestScore = sc;\n                    bestTask = t;\n                    itBest = it;\n                }\n            }\n\n            if (bestTask == -1) break;\n\n            // commit\n            state[bestTask] = 1;\n            curTask[j] = bestTask;\n            startDay[j] = day;\n            ready.erase(itBest);\n            assign.emplace_back(j, bestTask);\n        }\n\n        // Output\n        cout << assign.size();\n        for (auto [j, t] : assign) {\n            cout << ' ' << (j + 1) << ' ' << (t + 1);\n        }\n        cout << \"\\n\" << flush;\n\n        // Read completion status\n        int ncomp;\n        cin >> ncomp;\n        if (ncomp == -1) return 0;\n\n        for (int i = 0; i < ncomp; i++) {\n            int f;\n            cin >> f;\n            --f; // member index\n            int task = curTask[f];\n            if (task < 0) continue; // should not happen\n\n            curTask[f] = -1;\n            state[task] = 2;\n\n            int dur = day - startDay[f] + 1;\n\n            // ---- Update bounds for param[f] using duration ----\n            // Proxy deficit: w' = max(0, p[task] - param[f])\n            // Actual model: t = max(1, w + r), r in [-3,3]\n            //\n            // We use: if dur >= 2 then w' must be > 0 => p - param = w' roughly in [dur-3, dur+3].\n            // Convert to param interval:\n            //   param in [p - (dur+3), p - (dur-3)]\n            // Clamp and update LB/UB accordingly.\n            double pi = p[task];\n\n            if (dur <= 1) {\n                // If observed 1 day, it's likely w' is very small; allow param close to pi.\n                // Conservative: param >= pi - 1 (not too strict)\n                LB[f] = max(LB[f], pi - 1.0);\n            } else {\n                double lowW = max(1.0, (double)dur - 3.0);\n                double highW = (double)dur + 3.0;\n\n                // w' in [lowW, highW] => param in [pi-highW, pi-lowW]\n                LB[f] = max(LB[f], pi - highW);\n                UB[f] = min(UB[f], pi - lowW);\n            }\n\n            // If bounds inverted due to noise, slightly relax by merging towards midpoint.\n            if (LB[f] > UB[f]) {\n                double mid = 0.5 * (LB[f] + UB[f]);\n                LB[f] = mid;\n                UB[f] = mid;\n            }\n\n            // recompute param\n            recomputeParam(f);\n\n            // Update dependencies\n            for (int v : out[task]) {\n                indeg[v]--;\n                if (indeg[v] == 0 && state[v] == 0) {\n                    ready.insert(v);\n                }\n            }\n        }\n\n        day++;\n    }\n\n    return 0;\n}","ahc006":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic inline int manhattan(int x1, int y1, int x2, int y2) {\n    return abs(x1 - x2) + abs(y1 - y2);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    const int NORD = 1000;\n    const int W = 1000; // matrix stride\n    const int XOFF = 400, YOFF = 400;\n    const int M = 50;\n\n    vector<int> px(NORD), py(NORD), dx(NORD), dy(NORD);\n    for (int i = 0; i < NORD; i++) {\n        int a, b, c, d;\n        cin >> a >> b >> c >> d;\n        px[i] = a; py[i] = b;\n        dx[i] = c; dy[i] = d;\n    }\n\n    // Precompute distances needed\n    vector<int> internal(NORD), startDist(NORD), endDist(NORD);\n    // trans[i][j] = dist(drop_i, pick_j)\n    vector<int> trans(NORD * W);\n    // pickDist[i][j] = dist(pick_i, pick_j)\n    vector<int> pickDist(NORD * W);\n    // dropDist[i][j] = dist(drop_i, drop_j)\n    vector<int> dropDist(NORD * W);\n\n    for (int i = 0; i < NORD; i++) {\n        internal[i] = manhattan(px[i], py[i], dx[i], dy[i]);\n        startDist[i] = manhattan(XOFF, YOFF, px[i], py[i]);\n        endDist[i] = manhattan(dx[i], dy[i], XOFF, YOFF);\n    }\n\n    for (int i = 0; i < NORD; i++) {\n        int dix = dx[i], diy = dy[i];\n        for (int j = 0; j < NORD; j++) {\n            trans[i * W + j] = manhattan(dix, diy, px[j], py[j]);\n            pickDist[i * W + j] = manhattan(px[i], py[i], px[j], py[j]);\n            dropDist[i * W + j] = manhattan(dix, diy, dx[j], dy[j]);\n        }\n    }\n\n    auto getTrans = [&](int i, int j) -> int { return trans[i * W + j]; };\n    auto getPickDist = [&](int i, int j) -> int { return pickDist[i * W + j]; };\n    auto getDropDist = [&](int i, int j) -> int { return dropDist[i * W + j]; };\n\n    vector<long long> weight(NORD);\n    for (int i = 0; i < NORD; i++) {\n        weight[i] = (long long)internal[i] + startDist[i] + endDist[i];\n    }\n\n    auto computeMacroTotal = [&](const vector<int>& orderSeq, long long internalSum) -> long long {\n        long long cost = startDist[orderSeq[0]];\n        cost += endDist[orderSeq.back()];\n        for (int i = 0; i + 1 < (int)orderSeq.size(); i++) {\n            cost += getTrans(orderSeq[i], orderSeq[i + 1]); // drop_i -> pick_next\n        }\n        return internalSum + cost;\n    };\n\n    auto buildMacroRoute = [&](const vector<int>& orderSeq) -> vector<pair<int,int>> {\n        vector<pair<int,int>> route;\n        route.reserve(2 * M + 2);\n        route.push_back({XOFF, YOFF});\n        for (int ord : orderSeq) {\n            route.push_back({px[ord], py[ord]});\n            route.push_back({dx[ord], dy[ord]});\n        }\n        route.push_back({XOFF, YOFF});\n        return route;\n    };\n\n    auto nearestNeighborMacroForward = [&](const vector<int>& subset, long long internalSum) -> pair<long long, vector<int>> {\n        vector<char> used(NORD, 0);\n        vector<int> orderSeq;\n        orderSeq.reserve(M);\n\n        int first = subset[0];\n        for (int v : subset) if (startDist[v] < startDist[first]) first = v;\n        orderSeq.push_back(first);\n        used[first] = 1;\n\n        while ((int)orderSeq.size() < M) {\n            int cur = orderSeq.back();\n            int best = -1;\n            int bestCost = INT_MAX;\n            for (int cand : subset) if (!used[cand]) {\n                int cst = getTrans(cur, cand); // drop_cur -> pick_cand\n                if (cst < bestCost) {\n                    bestCost = cst;\n                    best = cand;\n                }\n            }\n            used[best] = 1;\n            orderSeq.push_back(best);\n        }\n\n        long long t = computeMacroTotal(orderSeq, internalSum);\n        return {t, orderSeq};\n    };\n\n    auto nearestNeighborMacroBackward = [&](const vector<int>& subset, long long internalSum) -> pair<long long, vector<int>> {\n        vector<char> used(NORD, 0);\n        vector<int> orderSeq(M);\n\n        int last = subset[0];\n        for (int v : subset) if (endDist[v] < endDist[last]) last = v;\n        orderSeq[M - 1] = last;\n        used[last] = 1;\n\n        for (int pos = M - 2; pos >= 0; pos--) {\n            int cur = orderSeq[pos + 1]; // in forward order: prev -> cur\n            int best = -1;\n            int bestCost = INT_MAX;\n            for (int cand : subset) if (!used[cand]) {\n                int cst = getTrans(cand, cur); // drop_cand -> pick_cur\n                if (cst < bestCost) {\n                    bestCost = cst;\n                    best = cand;\n                }\n            }\n            used[best] = 1;\n            orderSeq[pos] = best;\n        }\n\n        long long t = computeMacroTotal(orderSeq, internalSum);\n        return {t, orderSeq};\n    };\n\n    auto optimizeMacroForSubset = [&](const vector<int>& subset) -> pair<long long, vector<pair<int,int>>> {\n        long long internalSum = 0;\n        for (int v : subset) internalSum += internal[v];\n\n        auto fwd = nearestNeighborMacroForward(subset, internalSum);\n        auto bwd = nearestNeighborMacroBackward(subset, internalSum);\n\n        vector<int> bestSeq = (fwd.first <= bwd.first) ? fwd.second : bwd.second;\n        long long bestT = min(fwd.first, bwd.first);\n\n        // Local search: swap best-improvement sweeps\n        const int SWAP_SWEEPS = 2;\n        for (int sweep = 0; sweep < SWAP_SWEEPS; sweep++) {\n            bool improved = false;\n            long long curT = bestT;\n            int bi = -1, bj = -1;\n\n            for (int i = 0; i < M; i++) {\n                for (int j = i + 1; j < M; j++) {\n                    swap(bestSeq[i], bestSeq[j]);\n                    long long t = computeMacroTotal(bestSeq, internalSum);\n                    if (t < curT) {\n                        curT = t;\n                        bi = i; bj = j;\n                        improved = true;\n                    }\n                    swap(bestSeq[i], bestSeq[j]);\n                }\n            }\n            if (!improved) break;\n            swap(bestSeq[bi], bestSeq[bj]);\n            bestT = curT;\n        }\n\n        // Local search: insertion (best-improvement) one sweep\n        {\n            long long curT = bestT;\n            int bestI = -1, bestJ = -1;\n            for (int i = 0; i < M; i++) {\n                for (int j = 0; j < M; j++) if (j != i) {\n                    vector<int> tmp = bestSeq;\n                    int val = tmp[i];\n                    tmp.erase(tmp.begin() + i);\n                    tmp.insert(tmp.begin() + j, val);\n                    long long t = computeMacroTotal(tmp, internalSum);\n                    if (t < curT) {\n                        curT = t;\n                        bestI = i; bestJ = j;\n                    }\n                }\n            }\n            if (bestI != -1) {\n                int val = bestSeq[bestI];\n                bestSeq.erase(bestSeq.begin() + bestI);\n                bestSeq.insert(bestSeq.begin() + bestJ, val);\n                bestT = curT;\n            }\n        }\n\n        return {bestT, buildMacroRoute(bestSeq)};\n    };\n\n    auto computeTwoStageTotal = [&](const vector<int>& pickupOrder, const vector<int>& destOrder) -> long long {\n        long long cost = startDist[pickupOrder[0]];\n        for (int i = 0; i + 1 < M; i++) {\n            cost += getPickDist(pickupOrder[i], pickupOrder[i + 1]);\n        }\n        // pickup_last -> drop_first\n        cost += getTrans(destOrder[0], pickupOrder.back()); // dist(pick_last, drop_first)\n        for (int i = 0; i + 1 < M; i++) {\n            cost += getDropDist(destOrder[i], destOrder[i + 1]);\n        }\n        cost += endDist[destOrder.back()];\n        return cost;\n    };\n\n    auto buildTwoStageRouteGreedy = [&](const vector<int>& subset) -> pair<long long, vector<pair<int,int>>> {\n        // Greedy pickup order by nearest neighbor on pickDist\n        vector<char> used(NORD, 0);\n        vector<int> pickupOrder;\n        pickupOrder.reserve(M);\n\n        int first = subset[0];\n        for (int v : subset) if (startDist[v] < startDist[first]) first = v;\n        pickupOrder.push_back(first);\n        used[first] = 1;\n\n        while ((int)pickupOrder.size() < M) {\n            int cur = pickupOrder.back();\n            int best = -1, bestC = INT_MAX;\n            for (int cand : subset) if (!used[cand]) {\n                int cst = getPickDist(cur, cand);\n                if (cst < bestC) { bestC = cst; best = cand; }\n            }\n            used[best] = 1;\n            pickupOrder.push_back(best);\n        }\n\n        // Greedy destination order by nearest neighbor on dropDist, starting from last pickup\n        vector<char> used2(NORD, 0);\n        vector<int> destOrder;\n        destOrder.reserve(M);\n\n        int lastPick = pickupOrder.back();\n        int firstDest = -1, bestC = INT_MAX;\n        for (int v : subset) if (!used2[v]) {\n            int cst = getTrans(v, lastPick); // dist(drop_v, pick_last) == dist(pick_last, drop_v)\n            if (cst < bestC) { bestC = cst; firstDest = v; }\n        }\n        destOrder.push_back(firstDest);\n        used2[firstDest] = 1;\n\n        while ((int)destOrder.size() < M) {\n            int cur = destOrder.back();\n            int best = -1, bestD = INT_MAX;\n            for (int cand : subset) if (!used2[cand]) {\n                int cst = getDropDist(cur, cand);\n                if (cst < bestD) { bestD = cst; best = cand; }\n            }\n            used2[best] = 1;\n            destOrder.push_back(best);\n        }\n\n        long long total = computeTwoStageTotal(pickupOrder, destOrder);\n\n        vector<pair<int,int>> route;\n        route.reserve(2 * M + 2);\n        route.push_back({XOFF, YOFF});\n        for (int ord : pickupOrder) route.push_back({px[ord], py[ord]});\n        for (int ord : destOrder) route.push_back({dx[ord], dy[ord]});\n        route.push_back({XOFF, YOFF});\n        return {total, route};\n    };\n\n    // Candidate subset pools\n    vector<int> ids(NORD);\n    iota(ids.begin(), ids.end(), 0);\n    sort(ids.begin(), ids.end(), [&](int i, int j){ return weight[i] < weight[j]; });\n\n    vector<int> pool;\n    int TOP = 350;\n    for (int i = 0; i < TOP; i++) pool.push_back(ids[i]);\n\n    // Add randomness from the remainder\n    mt19937 rng((uint32_t)chrono::steady_clock::now().time_since_epoch().count());\n    uniform_int_distribution<int> uniAll(0, NORD - 1);\n    while ((int)pool.size() < 500) {\n        int v = uniAll(rng);\n        if (find(pool.begin(), pool.end(), v) == pool.end()) pool.push_back(v);\n    }\n\n    sort(pool.begin(), pool.end());\n    pool.erase(unique(pool.begin(), pool.end()), pool.end());\n\n    auto sampleSubsetWeightedNoReplace = [&](int k) -> vector<int> {\n        // Exponential race sampling without replacement:\n        // key = -log(u) / rate, choose smallest k keys.\n        // We want smaller weight more likely => rate = 1/(weight+1).\n        vector<pair<long double,int>> keys;\n        keys.reserve(pool.size());\n        uniform_real_distribution<long double> ur(1e-12L, 1.0L);\n        for (int v : pool) {\n            long double u = ur(rng);\n            long double rate = 1.0L / ( (long double)weight[v] + 1.0L );\n            long double key = -log(u) / rate;\n            keys.push_back({key, v});\n        }\n        nth_element(keys.begin(), keys.begin() + k, keys.end(),\n                    [](auto &p1, auto &p2){ return p1.first < p2.first; });\n        vector<int> subset;\n        subset.reserve(k);\n        for (int i = 0; i < k; i++) subset.push_back(keys[i].second);\n        return subset;\n    };\n\n    // Global best\n    long long bestT = (1LL<<62);\n    vector<int> bestSubset;\n    vector<pair<int,int>> bestRoute;\n\n    auto trySubset = [&](const vector<int>& subset) {\n        if ((int)subset.size() != M) return;\n\n        auto macro = optimizeMacroForSubset(subset);\n        if (macro.first < bestT) {\n            bestT = macro.first;\n            bestSubset = subset;\n            bestRoute = move(macro.second);\n        }\n\n        auto twoStage = buildTwoStageRouteGreedy(subset);\n        if (twoStage.first < bestT) {\n            bestT = twoStage.first;\n            bestSubset = subset;\n            bestRoute = move(twoStage.second);\n        }\n    };\n\n    // Try a few deterministic subsets first\n    auto pickTopKBy = [&](auto getter) -> vector<int> {\n        vector<int> v = ids;\n        sort(v.begin(), v.end(), [&](int i, int j){ return getter(i) < getter(j); });\n        v.resize(M);\n        return v;\n    };\n\n    trySubset(pickTopKBy([&](int i){ return (long long)internal[i]; }));\n    trySubset(pickTopKBy([&](int i){ return (long long)startDist[i]; }));\n    trySubset(pickTopKBy([&](int i){ return (long long)endDist[i]; }));\n    trySubset(pickTopKBy([&](int i){ return weight[i]; }));\n\n    // Multi-start random subsets\n    auto t0 = chrono::steady_clock::now();\n    int iter = 0;\n    while (true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - t0).count();\n        if (elapsed > 1.75) break;\n        if (iter++ > 90) break;\n\n        vector<int> subset = sampleSubsetWeightedNoReplace(M);\n        // small chance to ensure diversity: occasionally replace one element with a nearby-best one\n        if (iter % 7 == 0) {\n            // Replace the worst-weight element inside subset by something better from top ids (if not present).\n            int wi = -1, worst = -1;\n            for (int t = 0; t < M; t++) {\n                int v = subset[t];\n                if (worst == -1 || weight[v] > weight[subset[wi]]) wi = t;\n            }\n            // find better not in subset\n            sort(subset.begin(), subset.end());\n            vector<char> in(NORD, 0);\n            for (int v : subset) in[v] = 1;\n            int repl = -1;\n            for (int u : ids) {\n                if (!in[u]) { repl = u; break; }\n            }\n            if (repl != -1) subset[wi] = repl;\n            // restore permutation size still M\n        }\n\n        trySubset(subset);\n    }\n\n    // Output best result\n    // Header: chosen order indices\n    cout << M << \"\\n\";\n    // bestSubset may be empty if something went wrong; but should not.\n    if ((int)bestSubset.size() != M) {\n        // fallback: just output first M ids by weight and a trivial macro route ordering\n        vector<int> fallback = ids;\n        fallback.resize(M);\n        bestSubset = fallback;\n        vector<int> seq = fallback;\n        // trivial order: by increasing startDist\n        sort(seq.begin(), seq.end(), [&](int i, int j){ return startDist[i] < startDist[j]; });\n        bestRoute = buildMacroRoute(seq);\n    }\n    for (int i = 0; i < M; i++) {\n        if (i) cout << ' ';\n        cout << (bestSubset[i] + 1);\n    }\n    cout << \"\\n\";\n\n    cout << bestRoute.size() << \"\\n\";\n    for (auto [x, y] : bestRoute) {\n        cout << x << \" \" << y << \" \";\n    }\n    cout << \"\\n\";\n    return 0;\n}","ahc007":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct DSU {\n    int n;\n    vector<int> p, sz;\n    int comps;\n    DSU() : n(0), comps(0) {}\n    explicit DSU(int n_) { init(n_); }\n    void init(int n_) {\n        n = n_;\n        p.resize(n);\n        sz.assign(n, 1);\n        iota(p.begin(), p.end(), 0);\n        comps = n;\n    }\n    inline int find(int x) {\n        while (p[x] != x) {\n            p[x] = p[p[x]];\n            x = p[x];\n        }\n        return x;\n    }\n    inline 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        comps--;\n        return true;\n    }\n};\n\nstatic inline int distRound(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    double d = sqrt((double)dx * dx + (double)dy * dy);\n    return (int)llround(d);\n}\n\n// Feasible iff (accepted edges so far) + (all remaining edges remIdx..M-1) is connected.\nstatic bool feasibleSkip(int N, int remIdx, DSU &curDSU,\n                          const vector<vector<uint16_t>> &sufRoot) {\n    if (curDSU.comps == 1) return true;\n\n    vector<int> rootToId(N, -1);\n    vector<int> compId(N);\n    int k = 0;\n\n    for (int v = 0; v < N; v++) {\n        int r = curDSU.find(v);\n        int &id = rootToId[r];\n        if (id == -1) id = k++;\n        compId[v] = id;\n    }\n    if (k <= 1) return true;\n\n    DSU comb(k);\n    vector<int> firstA(N, -1); // maps suffix-root -> first component-id that appears\n\n    for (int v = 0; v < N; v++) {\n        int a = compId[v];\n        int bRoot = (int)sufRoot[remIdx][v]; // in [0..N-1]\n        int &f = firstA[bRoot];\n        if (f == -1) f = a;\n        else comb.unite(a, f);\n\n        if (comb.comps == 1) return true;\n    }\n    return comb.comps == 1;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // Robust input parsing:\n    // Some formats start with \"N M\", others directly start with coordinates.\n    int a, b;\n    if (!(cin >> a >> b)) return 0;\n\n    int N, M;\n    vector<int> x, y;\n    vector<int> U, V;\n\n    // Heuristic: in the fixed scoring setting, M=1995 (>800).\n    // If the second number is > 800, treat first line as \"N M\".\n    if (b > 800) {\n        N = a;\n        M = b;\n        x.assign(N, 0);\n        y.assign(N, 0);\n        for (int i = 0; i < N; i++) cin >> x[i] >> y[i];\n\n        U.assign(M, 0);\n        V.assign(M, 0);\n        for (int i = 0; i < M; i++) cin >> U[i] >> V[i];\n    } else {\n        // Assume fixed format without N M in input.\n        N = 400;\n        M = 1995;\n        x.assign(N, 0);\n        y.assign(N, 0);\n        x[0] = a;\n        y[0] = b;\n        for (int i = 1; i < N; i++) cin >> x[i] >> y[i];\n\n        U.assign(M, 0);\n        V.assign(M, 0);\n        for (int i = 0; i < M; i++) cin >> U[i] >> V[i];\n    }\n\n    vector<int> d(M);\n    for (int i = 0; i < M; i++) {\n        d[i] = distRound(x[U[i]], y[U[i]], x[V[i]], y[V[i]]);\n        if (d[i] == 0) d[i] = 1;\n    }\n\n    // Offline MST on proxy weights d[i] (only for heuristic bias).\n    vector<int> ord(M);\n    iota(ord.begin(), ord.end(), 0);\n    sort(ord.begin(), ord.end(), [&](int i, int j) {\n        if (d[i] != d[j]) return d[i] < d[j];\n        return i < j;\n    });\n    DSU dsuTmp(N);\n    vector<char> inMST(M, 0);\n    for (int idx : ord) {\n        if (dsuTmp.unite(U[idx], V[idx])) inMST[idx] = 1;\n    }\n\n    // Precompute suffix roots:\n    // sufRoot[i][v] = DSU root of v using edges i..M-1 only\n    vector<vector<uint16_t>> sufRoot(M + 1, vector<uint16_t>(N));\n    DSU sufDSU(N);\n    for (int v = 0; v < N; v++) sufRoot[M][v] = (uint16_t)v;\n    for (int i = M - 1; i >= 0; i--) {\n        sufDSU.unite(U[i], V[i]);\n        for (int v = 0; v < N; v++) sufRoot[i][v] = (uint16_t)sufDSU.find(v);\n    }\n\n    // Online decisions\n    DSU curDSU(N);\n\n    for (int i = 0; i < M; i++) {\n        long long li;\n        if (!(cin >> li)) break; // safety\n\n        int ru = curDSU.find(U[i]);\n        int rv = curDSU.find(V[i]);\n\n        if (ru == rv) {\n            cout << 0 << \"\\n\" << flush;\n            continue;\n        }\n\n        double progress = (M <= 1 ? 1.0 : (double)i / (double)(M - 1));\n        double lambda = 1.6 + 1.4 * progress; // [1.6, 3.0]\n        if (inMST[i]) lambda += 0.2;\n        else lambda -= 0.1;\n        lambda = max(1.0, min(3.0, lambda));\n\n        bool accept = ((long double)li <= (long double)lambda * (long double)d[i]);\n\n        if (!accept) {\n            // Only skip if still feasible to finish connected.\n            bool ok = feasibleSkip(N, i + 1, curDSU, sufRoot);\n            if (!ok) accept = true;\n        }\n\n        if (accept) {\n            curDSU.unite(ru, rv);\n            cout << 1 << \"\\n\" << flush;\n        } else {\n            cout << 0 << \"\\n\" << flush;\n        }\n    }\n    return 0;\n}","ahc008":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const int H = 30, W = 30;\nstatic const int V = H * W;\nstatic inline int id(int x, int y) { return x * W + y; }\nstatic inline bool inb(int x, int y) { return 0 <= x && x < H && 0 <= y && y < W; }\n\nstatic const int dx4[4] = {-1, 1, 0, 0};\nstatic const int dy4[4] = {0, 0, -1, 1};\n\nstatic char moveChar(int from, int to) {\n    int fx = from / W, fy = from % W;\n    int tx = to / W, ty = to % W;\n    if (tx == fx - 1 && ty == fy) return 'U';\n    if (tx == fx + 1 && ty == fy) return 'D';\n    if (tx == fx && ty == fy - 1) return 'L';\n    if (tx == fx && ty == fy + 1) return 'R';\n    return '.';\n}\n\nstatic char blockChar(int from, int to) {\n    int fx = from / W, fy = from % W;\n    int tx = to / W, ty = to % W;\n    if (tx == fx - 1 && ty == fy) return 'u';\n    if (tx == fx + 1 && ty == fy) return 'd';\n    if (tx == fx && ty == fy - 1) return 'l';\n    if (tx == fx && ty == fy + 1) return 'r';\n    return '.';\n}\n\nstatic bool isAdj(int a, int b) {\n    int ax = a / W, ay = a % W;\n    int bx = b / W, by = b % W;\n    return abs(ax - bx) + abs(ay - by) == 1;\n}\n\n// NOTE: rng is NON-const now (compile fix)\nstatic vector<int> computeWallPathVerticalOrHorizontal(\n    bool vertical,\n    const vector<char>& humanInitAt,\n    const vector<char>& petInitAt,\n    mt19937& rng // <-- changed from const mt19937&\n) {\n    const int INF = 1e9;\n    vector<int> cellCost(V, 1);\n\n    for (int x = 0; x < H; x++) for (int y = 0; y < W; y++) {\n        int c = id(x, y);\n        if (humanInitAt[c]) { cellCost[c] = INF; continue; }\n\n        int cost = 1;\n        if (petInitAt[c]) cost += 300;\n\n        int petAdj = 0;\n        for (int k = 0; k < 4; k++) {\n            int nx = x + dx4[k], ny = y + dy4[k];\n            if (!inb(nx, ny)) continue;\n            if (petInitAt[id(nx, ny)]) petAdj++;\n        }\n        cost += petAdj * 90;\n\n        // tiny randomness\n        cost += (int)(rng() % 3); // <-- now valid\n        cellCost[c] = cost;\n    }\n\n    using P = pair<long long,int>;\n    vector<long long> dist(V, (long long)INF * INF);\n    vector<int> parent(V, -1);\n    priority_queue<P, vector<P>, greater<P>> pq;\n\n    if (vertical) {\n        for (int y = 0; y < W; y++) {\n            int s = id(0, y);\n            if (cellCost[s] >= INF) continue;\n            dist[s] = cellCost[s];\n            parent[s] = -2;\n            pq.push({dist[s], s});\n        }\n    } else {\n        for (int x = 0; x < H; x++) {\n            int s = id(x, 0);\n            if (cellCost[s] >= INF) continue;\n            dist[s] = cellCost[s];\n            parent[s] = -2;\n            pq.push({dist[s], s});\n        }\n    }\n\n    int bestGoal = -1;\n    long long bestDist = (long long)INF * INF;\n\n    while (!pq.empty()) {\n        auto [d, u] = pq.top(); pq.pop();\n        if (d != dist[u]) continue;\n\n        int ux = u / W, uy = u % W;\n        if (vertical) {\n            if (ux == H - 1) {\n                if (d < bestDist) { bestDist = d; bestGoal = u; }\n            }\n        } else {\n            if (uy == W - 1) {\n                if (d < bestDist) { bestDist = d; bestGoal = u; }\n            }\n        }\n\n        for (int k = 0; k < 4; k++) {\n            int vx = ux + dx4[k], vy = uy + dy4[k];\n            if (!inb(vx, vy)) continue;\n            int v = id(vx, vy);\n            if (cellCost[v] >= INF) continue;\n            long long nd = d + cellCost[v];\n            if (nd < dist[v]) {\n                dist[v] = nd;\n                parent[v] = u;\n                pq.push({nd, v});\n            }\n        }\n    }\n\n    if (bestGoal == -1) {\n        // fallback straight line\n        vector<int> path;\n        if (vertical) {\n            int ymid = W / 2;\n            for (int x = 0; x < H; x++) path.push_back(id(x, ymid));\n        } else {\n            int xmid = H / 2;\n            for (int y = 0; y < W; y++) path.push_back(id(xmid, y));\n        }\n        return path;\n    }\n\n    vector<int> path;\n    int cur = bestGoal;\n    while (true) {\n        path.push_back(cur);\n        int p = parent[cur];\n        if (p == -2) break;\n        cur = p;\n        if (cur < 0) break;\n    }\n    reverse(path.begin(), path.end());\n    return path;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    mt19937 rng((uint32_t)chrono::steady_clock::now().time_since_epoch().count());\n\n    int N;\n    cin >> N;\n    vector<int> petPos(N);\n    vector<char> petInitAt(V, 0);\n    for (int i = 0; i < N; i++) {\n        int px, py, pt;\n        cin >> px >> py >> pt;\n        --px; --py;\n        petPos[i] = id(px, py);\n        petInitAt[petPos[i]] = 1;\n    }\n\n    int M;\n    cin >> M;\n    vector<int> humanPos(M);\n    vector<char> humanInitAt(V, 0);\n    for (int i = 0; i < M; i++) {\n        int hx, hy;\n        cin >> hx >> hy;\n        --hx; --hy;\n        humanPos[i] = id(hx, hy);\n        humanInitAt[humanPos[i]] = 1;\n    }\n\n    // Choose wall orientation\n    auto evaluateWall = [&](const vector<int>& wall) -> double {\n        vector<char> wallSet(V, 0);\n        for (int c : wall) wallSet[c] = 1;\n\n        vector<int> compId(V, -1);\n        int compCnt = 0;\n        vector<int> compSize;\n        queue<int> q;\n\n        for (int s = 0; s < V; s++) {\n            if (wallSet[s]) continue;\n            if (compId[s] != -1) continue;\n            compId[s] = compCnt;\n            int sz = 0;\n            q.push(s);\n            while (!q.empty()) {\n                int u = q.front(); q.pop();\n                sz++;\n                int ux = u / W, uy = u % W;\n                for (int k = 0; k < 4; k++) {\n                    int vx = ux + dx4[k], vy = uy + dy4[k];\n                    if (!inb(vx, vy)) continue;\n                    int v = id(vx, vy);\n                    if (wallSet[v]) continue;\n                    if (compId[v] != -1) continue;\n                    compId[v] = compCnt;\n                    q.push(v);\n                }\n            }\n            compSize.push_back(sz);\n            compCnt++;\n        }\n\n        vector<int> petCnt(compCnt, 0);\n        for (int i = 0; i < N; i++) {\n            int p = petPos[i];\n            if (wallSet[p]) continue;\n            int c = compId[p];\n            if (c >= 0) petCnt[c]++;\n        }\n\n        const int PETCAP = 6;\n        vector<double> compScore(compCnt, 0.0);\n        for (int c = 0; c < compCnt; c++) {\n            int n = min(petCnt[c], PETCAP);\n            compScore[c] = (double)compSize[c] / 900.0 * pow(0.5, n);\n        }\n\n        vector<double> top = compScore;\n        sort(top.begin(), top.end(), greater<double>());\n\n        int use = min(M, (int)top.size());\n        double sum = 0;\n        for (int i = 0; i < use; i++) sum += top[i];\n        for (int i = use; i < M; i++) sum += (top.empty() ? 0 : top[0]);\n        return sum / M;\n    };\n\n    vector<int> wallV = computeWallPathVerticalOrHorizontal(true, humanInitAt, petInitAt, rng);\n    vector<int> wallH = computeWallPathVerticalOrHorizontal(false, humanInitAt, petInitAt, rng);\n    vector<int> wall = (evaluateWall(wallV) >= evaluateWall(wallH) ? wallV : wallH);\n\n    // final wall\n    vector<char> wallSet(V, 0);\n    vector<int> wallIndex(V, -1);\n    for (int i = 0; i < (int)wall.size(); i++) {\n        wallSet[wall[i]] = 1;\n        wallIndex[wall[i]] = i;\n    }\n    int L = (int)wall.size();\n\n    // components in final-wall obstacle world\n    vector<int> compId(V, -1);\n    vector<vector<int>> compCells;\n    queue<int> q;\n    for (int s = 0; s < V; s++) {\n        if (wallSet[s] || compId[s] != -1) continue;\n        int cid = (int)compCells.size();\n        compId[s] = cid;\n        compCells.push_back({});\n        q.push(s);\n        while (!q.empty()) {\n            int u = q.front(); q.pop();\n            compCells[cid].push_back(u);\n            int ux = u / W, uy = u % W;\n            for (int k = 0; k < 4; k++) {\n                int vx = ux + dx4[k], vy = uy + dy4[k];\n                if (!inb(vx, vy)) continue;\n                int v = id(vx, vy);\n                if (wallSet[v] || compId[v] != -1) continue;\n                compId[v] = cid;\n                q.push(v);\n            }\n        }\n    }\n    int compCnt = (int)compCells.size();\n\n    vector<int> compSize(compCnt, 0);\n    for (int c = 0; c < compCnt; c++) compSize[c] = (int)compCells[c].size();\n\n    // distInterior: distance to nearest wall cell\n    vector<int> distInterior(V, -1);\n    queue<int> q2;\n    for (int c = 0; c < V; c++) if (wallSet[c]) {\n        distInterior[c] = 0;\n        q2.push(c);\n    }\n    while (!q2.empty()) {\n        int u = q2.front(); q2.pop();\n        int ux = u / W, uy = u % W;\n        for (int k = 0; k < 4; k++) {\n            int vx = ux + dx4[k], vy = uy + dy4[k];\n            if (!inb(vx, vy)) continue;\n            int v = id(vx, vy);\n            if (wallSet[v]) continue;\n            if (distInterior[v] != -1) continue;\n            distInterior[v] = distInterior[u] + 1;\n            q2.push(v);\n        }\n    }\n\n    // distMat for non-builders: BFS from every start (900*900*edges is fine)\n    vector<int16_t> distMat((size_t)V * V, (int16_t)-1);\n    for (int s = 0; s < V; s++) {\n        if (wallSet[s]) continue;\n        vector<int16_t> dist(V, (int16_t)-1);\n        queue<int> qq;\n        dist[s] = 0;\n        qq.push(s);\n        while (!qq.empty()) {\n            int u = qq.front(); qq.pop();\n            int ux = u / W, uy = u % W;\n            for (int k = 0; k < 4; k++) {\n                int vx = ux + dx4[k], vy = uy + dy4[k];\n                if (!inb(vx, vy)) continue;\n                int v = id(vx, vy);\n                if (wallSet[v]) continue;\n                if (dist[v] != -1) continue;\n                dist[v] = dist[u] + 1;\n                qq.push(v);\n            }\n        }\n        for (int t = 0; t < V; t++) distMat[(size_t)s * V + t] = dist[t];\n    }\n\n    // top candidate cells for each component\n    int TOPCELLS = 8;\n    vector<vector<int>> topCells(compCnt);\n    for (int c = 0; c < compCnt; c++) {\n        auto cells = compCells[c];\n        sort(cells.begin(), cells.end(), [&](int a, int b){\n            return distInterior[a] > distInterior[b];\n        });\n        int take = min(TOPCELLS, (int)cells.size());\n        topCells[c].assign(cells.begin(), cells.begin() + take);\n        if (topCells[c].empty() && !cells.empty()) topCells[c].push_back(cells[0]);\n    }\n\n    int K = min(4, M);\n    if (K < 1) K = 1;\n\n    vector<int> segL(K), segR(K);\n    for (int k = 0; k < K; k++) {\n        segL[k] = (long long)k * L / K;\n        segR[k] = (long long)(k + 1) * L / K;\n        if (segR[k] < segL[k]) segR[k] = segL[k];\n    }\n\n    // choose builders greedily\n    vector<int> builderHuman(K, -1);\n    vector<char> usedHuman(M, 0);\n\n    vector<int> segKey(K, -1);\n    for (int k = 0; k < K; k++) {\n        int mid = (segL[k] + segR[k]) / 2;\n        mid = max(0, min(L - 1, mid));\n        segKey[k] = wall[mid];\n    }\n\n    vector<int> order(K);\n    iota(order.begin(), order.end(), 0);\n    sort(order.begin(), order.end(), [&](int a, int b){\n        return (segR[a] - segL[a]) > (segR[b] - segL[b]);\n    });\n\n    for (int idx = 0; idx < K; idx++) {\n        int k = order[idx];\n        int keyCell = segKey[k];\n        int best = -1, bestD = INT_MAX;\n        for (int h = 0; h < M; h++) if (!usedHuman[h]) {\n            int dh = abs(humanPos[h] / W - keyCell / W) + abs(humanPos[h] % W - keyCell % W);\n            if (dh < bestD) { bestD = dh; best = h; }\n        }\n        if (best == -1) best = 0;\n        builderHuman[k] = best;\n        usedHuman[best] = 1;\n    }\n\n    vector<char> isBuilder(M, 0);\n    for (int k = 0; k < K; k++) isBuilder[builderHuman[k]] = 1;\n\n    vector<int> ptr(K);\n    for (int k = 0; k < K; k++) ptr[k] = segL[k];\n\n    vector<char> blockedActual(V, 0);\n    vector<int> willBlockWallCell(K, -1);\n\n    auto canBlockNow = [&](int targetCell, const vector<char>& petAtNow, const vector<char>& humanAtNow) -> bool {\n        if (targetCell < 0 || targetCell >= V) return false;\n        if (blockedActual[targetCell]) return false;\n        if (petAtNow[targetCell]) return false;\n        if (humanAtNow[targetCell]) return false;\n\n        int x = targetCell / W, y = targetCell % W;\n        for (int d = 0; d < 4; d++) {\n            int nx = x + dx4[d], ny = y + dy4[d];\n            if (!inb(nx, ny)) continue;\n            if (petAtNow[id(nx, ny)]) return false;\n        }\n        return true;\n    };\n\n    auto builderMoveOneStepToAdj = [&](int k, int bpos, int wcell, const vector<char>& plannedBlocked) -> char {\n        auto forbiddenWall = [&](int cell)->bool{\n            if (!wallSet[cell]) return false;\n            int wi = wallIndex[cell];\n            if (wi < 0) return false;\n            return !(segL[k] <= wi && wi < segR[k]);\n        };\n\n        vector<char> obs(V, 0);\n        for (int c = 0; c < V; c++) {\n            if (blockedActual[c] || plannedBlocked[c] || forbiddenWall(c)) obs[c] = 1;\n        }\n        if (obs[bpos]) return '.';\n\n        vector<int> candidates;\n        int wx = wcell / W, wy = wcell % W;\n        for (int d = 0; d < 4; d++) {\n            int nx = wx + dx4[d], ny = wy + dy4[d];\n            if (!inb(nx, ny)) continue;\n            int c = id(nx, ny);\n            if (obs[c]) continue;\n            if (c == wcell) continue; // don't step onto wcell while searching\n            candidates.push_back(c);\n        }\n        if (candidates.empty()) return '.';\n\n        vector<int> dist(V, -1), parent(V, -1);\n        queue<int> qq;\n        dist[bpos] = 0;\n        qq.push(bpos);\n\n        int bestCand = -1;\n        int bestDist = INT_MAX;\n\n        vector<char> isCand(V, 0);\n        for (int c : candidates) isCand[c] = 1;\n\n        while (!qq.empty()) {\n            int u = qq.front(); qq.pop();\n            if (dist[u] >= bestDist) continue;\n\n            if (isCand[u]) {\n                bestCand = u;\n                bestDist = dist[u];\n            }\n\n            int ux = u / W, uy = u % W;\n            for (int d = 0; d < 4; d++) {\n                int vx = ux + dx4[d], vy = uy + dy4[d];\n                if (!inb(vx, vy)) continue;\n                int v = id(vx, vy);\n                if (obs[v]) continue;\n                if (dist[v] != -1) continue;\n                dist[v] = dist[u] + 1;\n                parent[v] = u;\n                qq.push(v);\n            }\n        }\n\n        if (bestCand == -1) return '.';\n        if (bestCand == bpos) return '.';\n\n        int cur = bestCand;\n        while (parent[cur] != -1 && parent[cur] != bpos) cur = parent[cur];\n        if (parent[cur] == -1) return '.';\n        return moveChar(bpos, cur);\n    };\n\n    vector<int> targetPos(M, -1);\n\n    vector<char> petAt(V, 0), humanAt(V, 0);\n\n    auto updateTargets = [&](int /*turn*/) {\n        vector<int> petCnt(compCnt, 0);\n        for (int i = 0; i < N; i++) {\n            int p = petPos[i];\n            if (wallSet[p]) continue;\n            int c = compId[p];\n            if (c >= 0) petCnt[c]++;\n        }\n\n        const int PETCAP = 6;\n        vector<double> compScore(compCnt, 0.0);\n        for (int c = 0; c < compCnt; c++) {\n            int n = min(petCnt[c], PETCAP);\n            compScore[c] = (double)compSize[c] / 900.0 * pow(0.5, n);\n        }\n\n        vector<int> comps(compCnt);\n        iota(comps.begin(), comps.end(), 0);\n        sort(comps.begin(), comps.end(), [&](int a, int b){\n            if (compScore[a] != compScore[b]) return compScore[a] > compScore[b];\n            return compSize[a] > compSize[b];\n        });\n\n        int TOPCOMP = min(4, compCnt);\n        vector<int> chosenComps(comps.begin(), comps.begin() + TOPCOMP);\n\n        vector<int> nbHumans;\n        for (int i = 0; i < M; i++) if (!isBuilder[i]) nbHumans.push_back(i);\n\n        vector<char> used(V, 0);\n        const double alpha = 0.0015;\n        const double beta  = 0.00035;\n\n        for (int h : nbHumans) {\n            int cur = humanPos[h];\n            double bestVal = -1e100;\n            int bestCell = cur;\n\n            for (int c : chosenComps) {\n                for (int cell : topCells[c]) {\n                    if (wallSet[cell]) continue;\n                    int d = distMat[(size_t)cur * V + cell];\n                    if (d < 0) continue;\n                    if (used[cell]) continue;\n\n                    int depth = distInterior[cell];\n                    double noise = (double)(rng() % 1000) * 1e-10;\n                    double val = compScore[c]\n                               + alpha * (double)depth\n                               - beta  * (double)d\n                               + noise;\n\n                    if (val > bestVal) {\n                        bestVal = val;\n                        bestCell = cell;\n                    }\n                }\n            }\n\n            // fallback if we couldn't find a new distinct cell\n            if (used[bestCell]) {\n                for (int c : chosenComps) {\n                    for (int cell : topCells[c]) {\n                        if (wallSet[cell]) continue;\n                        int d = distMat[(size_t)cur * V + cell];\n                        if (d < 0) continue;\n\n                        int depth = distInterior[cell];\n                        double noise = (double)(rng() % 1000) * 1e-10;\n                        double val = compScore[c]\n                                   + alpha * (double)depth\n                                   - beta  * (double)d\n                                   + noise;\n\n                        if (val > bestVal) {\n                            bestVal = val;\n                            bestCell = cell;\n                        }\n                    }\n                }\n            }\n\n            targetPos[h] = bestCell;\n            used[bestCell] = 1;\n        }\n    };\n\n    // init positions arrays\n    for (int i = 0; i < N; i++) petAt[petPos[i]] = 1;\n    for (int i = 0; i < M; i++) humanAt[humanPos[i]] = 1;\n\n    updateTargets(0);\n\n    const int UPDATE_INTERVAL = 4;\n\n    for (int turn = 0; turn < 300; turn++) {\n        // rebuild at start of turn\n        fill(petAt.begin(), petAt.end(), 0);\n        for (int i = 0; i < N; i++) petAt[petPos[i]] = 1;\n\n        fill(humanAt.begin(), humanAt.end(), 0);\n        for (int i = 0; i < M; i++) humanAt[humanPos[i]] = 1;\n\n        if (turn % UPDATE_INTERVAL == 0) updateTargets(turn);\n\n        vector<char> plannedBlocked(V, 0);\n        fill(willBlockWallCell.begin(), willBlockWallCell.end(), -1);\n\n        vector<char> action(M, '.');\n\n        // builders\n        for (int k = 0; k < K; k++) {\n            int h = builderHuman[k];\n            int bpos = humanPos[h];\n\n            if (ptr[k] >= segR[k]) continue;\n\n            int widx = ptr[k];\n            int wcell = wall[widx];\n\n            if (isAdj(bpos, wcell)) {\n                if (canBlockNow(wcell, petAt, humanAt)) {\n                    action[h] = blockChar(bpos, wcell);\n                    willBlockWallCell[k] = wcell;\n                    plannedBlocked[wcell] = 1;\n                } else {\n                    action[h] = '.';\n                }\n            } else {\n                action[h] = builderMoveOneStepToAdj(k, bpos, wcell, plannedBlocked);\n            }\n        }\n\n        // non-builders: move greedily along shortest path in final-wall world\n        for (int i = 0; i < M; i++) {\n            if (isBuilder[i]) continue;\n            int cur = humanPos[i];\n            int tgt = targetPos[i];\n            if (tgt < 0 || cur == tgt) continue;\n            int d0 = distMat[(size_t)cur * V + tgt];\n            if (d0 < 0) continue;\n\n            vector<int> options;\n            int ux = cur / W, uy = cur % W;\n            for (int k = 0; k < 4; k++) {\n                int vx = ux + dx4[k], vy = uy + dy4[k];\n                if (!inb(vx, vy)) continue;\n                int v = id(vx, vy);\n                if (wallSet[v]) continue;\n                if (plannedBlocked[v]) continue;\n                int dv = distMat[(size_t)v * V + tgt];\n                if (dv == d0 - 1) options.push_back(v);\n            }\n            if (options.empty()) continue;\n\n            int bestv = options[0];\n            for (int v : options) {\n                if (distInterior[v] > distInterior[bestv]) bestv = v;\n            }\n            action[i] = moveChar(cur, bestv);\n        }\n\n        // output\n        string out(M, '.');\n        for (int i = 0; i < M; i++) out[i] = action[i];\n        cout << out << \"\\n\" << flush;\n\n        // apply actions\n        for (int i = 0; i < M; i++) {\n            char c = action[i];\n            if (c == '.') continue;\n\n            int x = humanPos[i] / W, y = humanPos[i] % W;\n            if (c == 'U') { x--; humanPos[i] = id(x,y); }\n            else if (c == 'D') { x++; humanPos[i] = id(x,y); }\n            else if (c == 'L') { y--; humanPos[i] = id(x,y); }\n            else if (c == 'R') { y++; humanPos[i] = id(x,y); }\n            else {\n                int bx = x, by = y;\n                if (c == 'u') bx--;\n                else if (c == 'd') bx++;\n                else if (c == 'l') by--;\n                else if (c == 'r') by++;\n                int bcell = id(bx, by);\n                if (0 <= bcell && bcell < V) blockedActual[bcell] = 1;\n            }\n        }\n\n        // update builders pointers\n        for (int k = 0; k < K; k++) {\n            int h = builderHuman[k];\n            if (willBlockWallCell[k] == -1) continue;\n            if (ptr[k] >= segR[k]) continue;\n\n            if (action[h] >= 'a' && action[h] <= 'z') {\n                if (willBlockWallCell[k] == wall[ptr[k]]) ptr[k]++;\n            }\n        }\n\n        // read pets movement\n        for (int i = 0; i < N; i++) {\n            string mv;\n            cin >> mv;\n            int p = petPos[i];\n            int x = p / W, y = p % W;\n            if (mv != \".\") {\n                for (char ch : mv) {\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                petPos[i] = id(x, y);\n            }\n        }\n    }\n\n    return 0;\n}","ahc009":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int H = 20;\nstatic constexpr int W = 20;\nstatic constexpr int N = H * W;\nstatic constexpr int L = 200;\nusing ld = long double;\n\nstruct Node {\n    array<ld, N> dp;   // distribution over positions at start of current step\n    ld score;          // exact expected value accumulated for executed prefix\n    int parent;        // index in pool, -1 for root\n    char act;          // action taken to reach this node from parent\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int si, sj, ti, tj;\n    double p_in;\n    cin >> si >> sj >> ti >> tj >> p_in;\n\n    vector<string> hwall(H);\n    for (int i = 0; i < H; i++) cin >> hwall[i]; // length 19\n\n    vector<string> vwall(H - 1);\n    for (int i = 0; i < H - 1; i++) cin >> vwall[i]; // length 20\n\n    auto id = [&](int r, int c) { return r * W + c; };\n    int start = id(si, sj);\n    int target = id(ti, tj);\n\n    const ld Pforget = (ld)p_in;       // probability forgotten -> stay\n    const ld Qmove = (ld)1.0 - Pforget; // probability remembered -> attempt move\n\n    // Precompute moveTo[v][a]\n    // a: 0=U,1=D,2=L,3=R\n    static int moveTo[N][4];\n    for (int r = 0; r < H; r++) {\n        for (int c = 0; c < W; c++) {\n            int v = id(r, c);\n            // U\n            if (r == 0) moveTo[v][0] = v;\n            else moveTo[v][0] = (vwall[r - 1][c] == '1') ? v : id(r - 1, c);\n            // D\n            if (r == H - 1) moveTo[v][1] = v;\n            else moveTo[v][1] = (vwall[r][c] == '1') ? v : id(r + 1, c);\n            // L\n            if (c == 0) moveTo[v][2] = v;\n            else moveTo[v][2] = (hwall[r][c - 1] == '1') ? v : id(r, c - 1);\n            // R\n            if (c == W - 1) moveTo[v][3] = v;\n            else moveTo[v][3] = (hwall[r][c] == '1') ? v : id(r, c + 1);\n        }\n    }\n\n    // BFS distances from target (static shortest path length)\n    const int INF = 1e9;\n    vector<int> dist(N, INF);\n    queue<int> q;\n    dist[target] = 0;\n    q.push(target);\n    while (!q.empty()) {\n        int v = q.front(); q.pop();\n        int dv = dist[v];\n        for (int a = 0; a < 4; a++) {\n            int u = moveTo[v][a];\n            if (u == v) continue; // blocked\n            if (dist[u] > dv + 1) {\n                dist[u] = dv + 1;\n                q.push(u);\n            }\n        }\n    }\n\n    auto rewardAt = [&](int t) -> ld {\n        // t is 0-indexed action => office reached after t+1 turns\n        return (ld)(401 - (t + 1));\n    };\n\n    const char dirChar[4] = {'U','D','L','R'};\n\n    // Build heuristic H[t][v] = approx expected remaining score starting at step t\n    // if at start of step t we are at state v (v!=target).\n    // Uses negative binomial with heuristic success prob qSucc:\n    // Need k=dist[v] remembered moves that each (heuristically) advance by 1.\n    auto buildHeuristic = [&](ld qSucc) -> vector<ld> {\n        ld qFail = 1.0L - qSucc;\n        vector<ld> Hh((L + 1) * N, 0.0L);\n        // Hh[L][*]=0 already\n\n        // Precompute possible rewards: reward=401-(t+j) with j in [k..rem]\n        for (int t = 0; t < L; t++) {\n            int rem = L - t;\n            // Expected value E[k] for k=1..rem\n            vector<ld> E(rem + 1, 0.0L);\n\n            vector<ld> powQ(rem + 1, 1.0L);\n            for (int i = 1; i <= rem; i++) powQ[i] = powQ[i - 1] * qSucc;\n\n            for (int k = 1; k <= rem; k++) {\n                ld pj = powQ[k]; // P(J=k)=qSucc^k\n                ld expected = 0.0L;\n\n                for (int j = k; j <= rem; j++) {\n                    // completion at step (t+j-1), reward uses (t+j)\n                    ld r = (ld)(401 - (t + j));\n                    if (r > 0) expected += r * pj;\n\n                    if (j == rem) break;\n                    // ratio pj_{j+1} = pj_j * j/(j-k+1) * qFail\n                    ld ratio = (ld)j / (ld)(j - k + 1);\n                    pj = pj * ratio * qFail;\n                    if (pj < 1e-30L) break;\n                }\n                E[k] = expected;\n            }\n\n            for (int v = 0; v < N; v++) {\n                if (v == target) {\n                    Hh[(size_t)t * N + v] = 0.0L;\n                    continue;\n                }\n                int k = dist[v];\n                if (k <= 0 || k >= INF || k > rem) {\n                    Hh[(size_t)t * N + v] = 0.0L;\n                } else {\n                    Hh[(size_t)t * N + v] = E[k];\n                }\n            }\n        }\n        return Hh;\n    };\n\n    auto runBeam = [&](ld qHeur, int beamW, uint64_t seed) -> pair<string, ld> {\n        // Build heuristic\n        vector<ld> Hh = buildHeuristic(qHeur);\n\n        auto dotFuture = [&](const array<ld, N>& dpNext, int tNext) -> ld {\n            // tNext in [0..L]\n            const ld* ptr = &Hh[(size_t)tNext * N];\n            ld s = 0.0L;\n            for (int u = 0; u < N; u++) s += dpNext[u] * ptr[u];\n            return s;\n        };\n\n        vector<Node> pool;\n        pool.reserve((L + 1) * beamW + 5);\n\n        vector<int> beamIdx;\n        beamIdx.reserve(beamW);\n\n        // Root node at time t=0 before any action, dp=start=1\n        Node root;\n        root.dp.fill(0.0L);\n        root.dp[start] = 1.0L;\n        root.score = 0.0L;\n        root.parent = -1;\n        root.act = '?';\n        pool.push_back(root);\n        beamIdx.push_back(0);\n\n        mt19937_64 rng(seed);\n        normal_distribution<ld> noise(0.0L, 1.0L);\n\n        for (int t = 0; t < L; t++) {\n            struct Cand {\n                array<ld, N> dp;\n                ld score;\n                ld estKey;\n                int parent;\n                char act;\n            };\n\n            vector<Cand> cands;\n            cands.reserve((size_t)beamIdx.size() * 4);\n\n            for (int idx : beamIdx) {\n                const Node& nd = pool[idx];\n\n                for (int a = 0; a < 4; a++) {\n                    array<ld, N> dpNext;\n                    dpNext.fill(0.0L);\n\n                    ld probReach = 0.0L;\n\n                    for (int v = 0; v < N; v++) {\n                        if (v == target) continue;\n                        ld dv = nd.dp[v];\n                        if (dv == 0.0L) continue;\n\n                        int w = moveTo[v][a];\n                        if (w == target) {\n                            // moved into target only if remembered\n                            probReach += dv * Qmove;\n                            // forgotten => stay in v\n                            dpNext[v] += dv * Pforget;\n                        } else {\n                            // remembered => move to w\n                            dpNext[w] += dv * Qmove;\n                            // forgotten => stay\n                            dpNext[v] += dv * Pforget;\n                        }\n                    }\n\n                    ld gain = probReach * rewardAt(t);\n                    ld newScore = nd.score + gain;\n                    ld future = dotFuture(dpNext, t + 1);\n                    ld est = newScore + future;\n\n                    // small random noise to diversify ties\n                    // (scale chosen small compared to expected score magnitudes)\n                    ld estKey = est + (ld)1e-9 * noise(rng);\n\n                    Cand cd;\n                    cd.dp = dpNext;\n                    cd.score = newScore;\n                    cd.estKey = estKey;\n                    cd.parent = idx;\n                    cd.act = dirChar[a];\n                    cands.push_back(std::move(cd));\n                }\n            }\n\n            // Keep best beamW by estKey\n            int K = min(beamW, (int)cands.size());\n            nth_element(cands.begin(), cands.begin() + K, cands.end(),\n                        [](const Cand& x, const Cand& y){ return x.estKey > y.estKey; });\n            cands.resize(K);\n\n            sort(cands.begin(), cands.end(),\n                 [](const Cand& x, const Cand& y){ return x.estKey > y.estKey; });\n\n            vector<int> newBeam;\n            newBeam.reserve(beamW);\n\n            // push kept candidates to pool\n            for (auto &cd : cands) {\n                Node nn;\n                nn.dp = cd.dp;\n                nn.score = cd.score;\n                nn.parent = cd.parent;\n                nn.act = cd.act;\n                pool.push_back(std::move(nn));\n                newBeam.push_back((int)pool.size() - 1);\n            }\n            beamIdx.swap(newBeam);\n        }\n\n        // pick best exact score among final beam\n        int bestIdx = beamIdx[0];\n        for (int idx : beamIdx) if (pool[idx].score > pool[bestIdx].score) bestIdx = idx;\n\n        // reconstruct string\n        string ans;\n        ans.reserve(L);\n        int cur = bestIdx;\n        while (pool[cur].parent != -1) {\n            ans.push_back(pool[cur].act);\n            cur = pool[cur].parent;\n        }\n        reverse(ans.begin(), ans.end());\n        // ans length should be L\n        if ((int)ans.size() != L) {\n            // Safety: if something went wrong, pad/truncate (shouldn't happen)\n            if ((int)ans.size() > L) ans.resize(L);\n            else while ((int)ans.size() < L) ans.push_back('U');\n        }\n\n        return {ans, pool[bestIdx].score};\n    };\n\n    string bestS;\n    ld bestScore = -1e100L;\n\n    // Multiple heuristic variants for diversification\n    // qHeur is only used in pruning heuristic, exact transition uses real Qmove/Pforget.\n    vector<ld> qMult = {0.82L, 1.00L, 1.16L, 1.32L};\n    uint64_t baseSeed = 88172645463325252ULL ^ (uint64_t)(si*1315423911u + sj*2654435761u + ti*97531u + tj*19260817u);\n\n    int beamW = 30;\n    for (int r = 0; r < (int)qMult.size(); r++) {\n        ld qHeur = Qmove * qMult[r];\n        qHeur = max((ld)1e-4, min((ld)0.9999, qHeur));\n        uint64_t seed = baseSeed ^ (uint64_t)(r * 1000003ULL) ^ (uint64_t)(llround(p_in * 100000));\n        auto [s, sc] = runBeam(qHeur, beamW, seed);\n        if (sc > bestScore) {\n            bestScore = sc;\n            bestS = std::move(s);\n        }\n    }\n\n    cout << bestS << \"\\n\";\n    return 0;\n}","ahc010":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 30;\nstatic constexpr int CELLS = N * N;          // 900\nstatic constexpr int DIRS = 4;\nstatic constexpr int STATES = CELLS * DIRS; // 3600\n\n// Directions: 0=left, 1=up, 2=right, 3=down\nstatic constexpr int di[4] = {0, -1, 0, 1};\nstatic constexpr int dj[4] = {-1, 0, 1, 0};\n\nstruct EvalResult {\n    long long score;\n    int best1;\n    int best2;\n    int numCycles;\n};\n\nstatic int8_t toBase[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\n// toRot[t][r][d] = exit direction (0..3) or -1\nstatic int8_t toRot[8][4][4];\n\nstatic int16_t neighCell[CELLS][4]; // neighCell[c][exitDir] = neighbor cell index or -1\n\nstatic uint8_t tileType[CELLS];     // input tile t\nstatic uint8_t rotCurr[CELLS];\nstatic uint8_t rotBest[CELLS];\n\nstatic int nextState[STATES];\nstatic int vis[STATES];\nstatic int posInPath[STATES];\nstatic int pathArr[STATES];\n\nstatic inline long long llmax0(long long x){ return x; }\n\nEvalResult evaluate(const uint8_t rot[CELLS]) {\n    // Build functional graph transitions for all states\n    for (int c = 0; c < CELLS; c++) {\n        int t = tileType[c];\n        int r = rot[c];\n        for (int d = 0; d < 4; d++) {\n            int v = c * 4 + d; // state: enter from direction d\n            int exitDir = toRot[t][r][d];\n            if (exitDir < 0) {\n                nextState[v] = -1;\n                continue;\n            }\n            int nb = neighCell[c][exitDir];\n            if (nb < 0) {\n                nextState[v] = -1;\n                continue;\n            }\n            int entryNext = (exitDir + 2) & 3;\n            nextState[v] = nb * 4 + entryNext;\n        }\n    }\n\n    // Find all directed cycles in this functional graph\n    int best1 = 0, best2 = 0, cnt1 = 0, numCycles = 0;\n    memset(vis, 0, sizeof(vis));\n\n    for (int v0 = 0; v0 < STATES; v0++) {\n        if (vis[v0] != 0) continue;\n\n        int cur = v0;\n        int pathLen = 0;\n        while (cur != -1 && vis[cur] == 0) {\n            vis[cur] = 1;              // in current traversal\n            posInPath[cur] = pathLen; // position in pathArr\n            pathArr[pathLen++] = cur;\n            cur = nextState[cur];\n        }\n\n        if (cur != -1 && vis[cur] == 1) {\n            // Found a cycle: nodes pathArr[posInPath[cur] .. pathLen-1]\n            int len = pathLen - posInPath[cur];\n            numCycles++;\n\n            if (len > best1) {\n                best2 = best1;\n                best1 = len;\n                cnt1 = 1;\n            } else if (len == best1) {\n                cnt1++;\n                if (cnt1 >= 2) best2 = best1;\n            } else if (len > best2) {\n                best2 = len;\n            }\n        }\n\n        // Mark path nodes as done\n        for (int i = 0; i < pathLen; i++) vis[pathArr[i]] = 2;\n    }\n\n    long long score = (numCycles >= 2) ? 1LL * best1 * best2 : 0LL;\n    return {score, best1, best2, numCycles};\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // Precompute rotation mapping\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                // d is global entry direction after rotation by r (CCW)\n                // original entry direction is d_orig = (d + r) mod 4\n                int d_orig = (d + r) & 3;\n                int exit_orig = toBase[t][d_orig];\n                if (exit_orig < 0) {\n                    toRot[t][r][d] = -1;\n                } else {\n                    // exit direction rotates with tile: exit_global = exit_orig - r\n                    toRot[t][r][d] = (exit_orig - r + 4) & 3;\n                }\n            }\n        }\n    }\n\n    // Read input\n    for (int i = 0; i < N; i++) {\n        string s;\n        cin >> s;\n        for (int j = 0; j < N; j++) {\n            int t = s[j] - '0';\n            tileType[i * N + j] = (uint8_t)t;\n        }\n    }\n\n    // Precompute neighbor cells\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            int c = i * N + j;\n            for (int dir = 0; dir < 4; dir++) {\n                int ni = i + di[dir], nj = j + dj[dir];\n                if (0 <= ni && ni < N && 0 <= nj && nj < N) neighCell[c][dir] = ni * N + nj;\n                else neighCell[c][dir] = -1;\n            }\n        }\n    }\n\n    // Random engine\n    mt19937_64 rng((uint64_t)chrono::steady_clock::now().time_since_epoch().count());\n    auto randInt = [&](int L, int R) -> int {\n        uniform_int_distribution<int> dist(L, R);\n        return dist(rng);\n    };\n    auto rand01 = [&]() -> double {\n        return uniform_real_distribution<double>(0.0, 1.0)(rng);\n    };\n\n    const double TIME_LIMIT = 1.85; // seconds\n    auto startTime = chrono::steady_clock::now();\n    auto elapsedSec = [&]() -> double {\n        return chrono::duration<double>(chrono::steady_clock::now() - startTime).count();\n    };\n\n    long long bestScore = -1;\n    int bestRestart = 0;\n\n    // Multi-restart SA\n    for (int restart = 0; restart < 4; restart++) {\n        if (elapsedSec() > TIME_LIMIT) break;\n\n        if (restart == 0) {\n            // deterministic init\n            for (int c = 0; c < CELLS; c++) rotCurr[c] = 0;\n        } else {\n            for (int c = 0; c < CELLS; c++) rotCurr[c] = (uint8_t)randInt(0, 3);\n        }\n\n        EvalResult curRes = evaluate(rotCurr);\n        long long curScore = curRes.score;\n\n        if (curScore > bestScore) {\n            bestScore = curScore;\n            bestRestart = restart;\n            memcpy(rotBest, rotCurr, CELLS);\n        }\n\n        const double tempStart = 1e7;\n        const double tempEnd = 1e3;\n\n        while (elapsedSec() < TIME_LIMIT) {\n            int c = rng() % CELLS;\n            uint8_t oldR = rotCurr[c];\n\n            // Local continuity estimate to bias rotation proposals\n            int t = tileType[c];\n            int local[4];\n            for (int r = 0; r < 4; r++) {\n                int cnt = 0;\n                for (int entry = 0; entry < 4; entry++) {\n                    int exitDir = toRot[t][r][entry];\n                    if (exitDir < 0) continue;\n                    int nb = neighCell[c][exitDir];\n                    if (nb < 0) continue;\n                    int entryNext = (exitDir + 2) & 3;\n                    int nbT = tileType[nb];\n                    int nbR = rotCurr[nb];\n                    if (toRot[nbT][nbR][entryNext] >= 0) cnt++;\n                }\n                local[r] = cnt;\n            }\n\n            uint8_t newR = oldR;\n\n            if (rand01() < 0.15) {\n                // exploration\n                do { newR = (uint8_t)((oldR + 1 + (rng() % 3)) & 3); } while (newR == oldR);\n            } else {\n                // pick among best local rotations excluding old\n                int best = -1;\n                for (int r = 0; r < 4; r++) if ((uint8_t)r != oldR) best = max(best, local[r]);\n                if (best < 0) continue;\n\n                int threshold = best - 1;\n                vector<int> cand;\n                for (int r = 0; r < 4; r++) {\n                    if ((uint8_t)r == oldR) continue;\n                    if (local[r] >= threshold) cand.push_back(r);\n                }\n                if (cand.empty()) {\n                    for (int r = 0; r < 4; r++) if ((uint8_t)r != oldR) cand.push_back(r);\n                }\n                newR = (uint8_t)cand[rng() % cand.size()];\n            }\n\n            if (newR == oldR) continue;\n\n            rotCurr[c] = newR;\n            EvalResult nres = evaluate(rotCurr);\n            long long newScore = nres.score;\n\n            long long delta = newScore - curScore;\n\n            double prog = elapsedSec() / TIME_LIMIT;\n            double temp = tempEnd + (tempStart - tempEnd) * (1.0 - prog);\n            temp = max(temp, 1e-9);\n\n            bool accept = false;\n            if (delta >= 0) {\n                accept = true;\n            } else {\n                double prob = exp((double)delta / temp);\n                if (rand01() < prob) accept = true;\n            }\n\n            if (accept) {\n                curScore = newScore;\n                if (curScore > bestScore) {\n                    bestScore = curScore;\n                    memcpy(rotBest, rotCurr, CELLS);\n                }\n            } else {\n                rotCurr[c] = oldR;\n            }\n        }\n    }\n\n    // Output rotations as a 900-char string\n    string out;\n    out.reserve(CELLS);\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            int c = i * N + j;\n            out.push_back(char('0' + (int)rotBest[c]));\n        }\n    }\n    cout << out << \"\\n\";\n    return 0;\n}","ahc011":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct DSUFixed {\n    int M;\n    int parent[100], sz[100];\n    void init(int m) { M = m; reset(); }\n    void reset() {\n        for (int i = 0; i < M; i++) parent[i] = i, sz[i] = 1;\n    }\n    int find(int a) {\n        while (parent[a] != a) {\n            parent[a] = parent[parent[a]];\n            a = parent[a];\n        }\n        return a;\n    }\n    void unite(int a, int b) {\n        a = find(a); b = find(b);\n        if (a == b) return;\n        if (sz[a] < sz[b]) swap(a, b);\n        parent[b] = a;\n        sz[a] += sz[b];\n    }\n};\n\nstruct Evaluator {\n    int N, M;\n    DSUFixed dsu;\n    // indices for fixed adjacency pairs\n    vector<int> vertTop, vertBot;\n    vector<int> horL, horR;\n\n    // compatibility for masks 0..15\n    bool vertOk[16][16];\n    bool horOk[16][16];\n\n    int compVerts[100], compEdges[100];\n\n    Evaluator(int N_) : N(N_), M(N_ * N_) {\n        dsu.init(M);\n\n        for (int a = 0; a < 16; a++) for (int b = 0; b < 16; b++) {\n            // vertical: top needs DOWN(8), bottom needs UP(2)\n            vertOk[a][b] = ((a & 8) && (b & 2));\n            // horizontal: left needs RIGHT(4), right needs LEFT(1)\n            horOk[a][b] = ((a & 4) && (b & 1));\n        }\n\n        for (int i = 0; i < N - 1; i++) for (int j = 0; j < N; j++) {\n            int top = i * N + j;\n            int bot = (i + 1) * N + j;\n            vertTop.push_back(top);\n            vertBot.push_back(bot);\n        }\n        for (int i = 0; i < N; i++) for (int j = 0; j < N - 1; j++) {\n            int L = i * N + j;\n            int R = i * N + (j + 1);\n            horL.push_back(L);\n            horR.push_back(R);\n        }\n    }\n\n    struct Res {\n        int bestTree;     // exact largest tree component size\n        int bestFitness;  // smoother metric\n    };\n\n    Res eval(const vector<uint8_t>& b) {\n        dsu.reset();\n\n        // Build components via existing edges\n        for (size_t k = 0; k < vertTop.size(); k++) {\n            int top = vertTop[k], bot = vertBot[k];\n            uint8_t mt = b[top], mb = b[bot];\n            if (vertOk[mt][mb]) dsu.unite(top, bot);\n        }\n        for (size_t k = 0; k < horL.size(); k++) {\n            int L = horL[k], R = horR[k];\n            uint8_t mL = b[L], mR = b[R];\n            if (horOk[mL][mR]) dsu.unite(L, R);\n        }\n\n        for (int i = 0; i < M; i++) compVerts[i] = 0;\n        for (int v = 0; v < M; v++) {\n            if (b[v] == 0) continue;\n            compVerts[dsu.find(v)]++;\n        }\n        for (int i = 0; i < M; i++) compEdges[i] = 0;\n\n        // Count edges per component root\n        for (size_t k = 0; k < vertTop.size(); k++) {\n            int top = vertTop[k], bot = vertBot[k];\n            uint8_t mt = b[top], mb = b[bot];\n            if (vertOk[mt][mb]) compEdges[dsu.find(top)]++;\n        }\n        for (size_t k = 0; k < horL.size(); k++) {\n            int L = horL[k], R = horR[k];\n            uint8_t mL = b[L], mR = b[R];\n            if (horOk[mL][mR]) compEdges[dsu.find(L)]++;\n        }\n\n        int bestTree = 0;\n        int bestFitness = 0;\n        // fitness = v - extraCycles, where extra = edges - (v-1)\n        for (int r = 0; r < M; r++) {\n            int vcnt = compVerts[r];\n            if (vcnt == 0) continue;\n            int ecnt = compEdges[r];\n            int extra = ecnt - (vcnt - 1); // >= 0\n            if (extra == 0) bestTree = max(bestTree, vcnt);\n            int fitness = vcnt - extra;\n            if (fitness < 0) fitness = 0;\n            bestFitness = max(bestFitness, fitness);\n        }\n        return {bestTree, bestFitness};\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    long long T;\n    cin >> N >> T;\n\n    vector<string> s(N);\n    for (int i = 0; i < N; i++) cin >> s[i];\n\n    int M = N * N;\n    vector<uint8_t> b(M);\n    int emptyIdx = -1;\n\n    auto hexToVal = [&](char c) -> int {\n        if ('0' <= c && c <= '9') return c - '0';\n        return 10 + (c - 'a');\n    };\n\n    for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) {\n        int v = hexToVal(s[i][j]);\n        b[i * N + j] = (uint8_t)v;\n        if (v == 0) emptyIdx = i * N + j;\n    }\n\n    Evaluator evaluator(N);\n    const int FULLTREE = N * N - 1;\n\n    auto valForSelect = [&](const Evaluator::Res& r) -> int {\n        // normalized numeric value (avoid huge scaling so selection remains explorative)\n        // bestTree dominates, bestFitness refines.\n        return r.bestTree * 200 + r.bestFitness; // range ~ 0..~2e4\n    };\n\n    int dr[4] = {-1, 1, 0, 0};\n    int dc[4] = {0, 0, -1, 1};\n    char dirChar[4] = {'U', 'D', 'L', 'R'};\n    int opp[4] = {1, 0, 3, 2};\n\n    auto inBounds = [&](int r, int c) {\n        return 0 <= r && r < N && 0 <= c && c < N;\n    };\n\n    uint64_t seed = (uint64_t)chrono::steady_clock::now().time_since_epoch().count();\n    seed ^= 0x9e3779b97f4a7c15ULL * (uint64_t)N;\n    for (int i = 0; i < M; i++) seed = seed * 1315423911u + b[i] + 7;\n    seed ^= (uint64_t)emptyIdx * 1234567ULL;\n    mt19937_64 rng(seed);\n\n    auto start = chrono::steady_clock::now();\n    auto elapsedSec = [&]() -> double {\n        return chrono::duration<double>(chrono::steady_clock::now() - start).count();\n    };\n\n    int bestTreeGlobal = evaluator.eval(b).bestTree;\n    vector<char> bestMovesGlobal;\n    int bestKGlobal = (int)bestMovesGlobal.size();\n\n    const double LIMIT = 2.92;\n    const int maxRestarts = 26;\n    const int STAG = 600;\n\n    for (int restart = 0; restart < maxRestarts; restart++) {\n        if (elapsedSec() > LIMIT) break;\n\n        vector<uint8_t> curB = b;\n        int e = emptyIdx;\n        vector<char> moves;\n        moves.reserve((size_t)T);\n\n        auto curEval = evaluator.eval(curB);\n        int bestTreeRun = curEval.bestTree;\n        vector<char> bestMovesRun = moves;\n        int bestKRun = 0;\n        int stagnation = 0;\n        int prevDir = -1;\n\n        for (long long step = 0; step < T; step++) {\n            if (curEval.bestTree == FULLTREE) break;\n            if (elapsedSec() > LIMIT) break;\n            if (stagnation >= STAG) break;\n\n            int er = e / N, ec = e % N;\n\n            struct Cand {\n                int dir;\n                int nei;          // new empty index after move1\n                Evaluator::Res r1;\n                int lookVal;      // best val over move2\n            };\n\n            vector<Cand> cands;\n            cands.reserve(4);\n\n            for (int dir = 0; dir < 4; dir++) {\n                // mild anti-backtracking\n                if (prevDir != -1 && dir == opp[prevDir]) {\n                    // don't forbid; just reduce probability by skipping some\n                    if ((rng() % 10) < 7) continue;\n                }\n                int nr = er + dr[dir], nc = ec + dc[dir];\n                if (!inBounds(nr, nc)) continue;\n                int nei = nr * N + nc;\n\n                swap(curB[e], curB[nei]);\n                auto r1 = evaluator.eval(curB);\n                swap(curB[e], curB[nei]);\n\n                Cand c;\n                c.dir = dir;\n                c.nei = nei;\n                c.r1 = r1;\n                c.lookVal = valForSelect(r1); // at least move2=none\n                cands.push_back(c);\n            }\n            if (cands.empty()) break;\n\n            // 2-step lookahead: compute best val over all move2 for each move1 cand\n            for (auto& c : cands) {\n                // apply move1\n                swap(curB[e], curB[c.nei]);\n                int e1 = c.nei;\n                int r1p = e1 / N, c1p = e1 % N;\n\n                int bestLookVal = valForSelect(c.r1);\n\n                for (int dir2 = 0; dir2 < 4; dir2++) {\n                    int nr = r1p + dr[dir2], nc = c1p + dc[dir2];\n                    if (!inBounds(nr, nc)) continue;\n                    int e2 = nr * N + nc;\n\n                    swap(curB[e1], curB[e2]);\n                    auto r2 = evaluator.eval(curB);\n                    swap(curB[e1], curB[e2]);\n\n                    bestLookVal = max(bestLookVal, valForSelect(r2));\n                }\n                // undo move1\n                swap(curB[e], curB[c.nei]);\n\n                c.lookVal = bestLookVal;\n            }\n\n            int curBestTree = curEval.bestTree;\n\n            // If there is any improving 1-step bestTree, pick among them using 2-step lookVal.\n            int bestTree1 = curBestTree;\n            for (auto &c : cands) bestTree1 = max(bestTree1, c.r1.bestTree);\n\n            int chosenIdx = 0;\n            if (bestTree1 > curBestTree) {\n                // among candidates with max r1.bestTree pick max lookVal\n                int bestLook = -1;\n                for (int i = 0; i < (int)cands.size(); i++) {\n                    if (cands[i].r1.bestTree == bestTree1) {\n                        if (cands[i].lookVal > bestLook) {\n                            bestLook = cands[i].lookVal;\n                            chosenIdx = i;\n                        }\n                    }\n                }\n            } else {\n                // epsilon-greedy on lookVal to avoid too-greedy softmax\n                // eps decreases as step advances\n                double eps = 0.30 * (1.0 - (double)step / (double)T) + 0.08;\n                if (eps < 0.05) eps = 0.05;\n\n                // rank by lookVal\n                vector<int> ord(cands.size());\n                iota(ord.begin(), ord.end(), 0);\n                sort(ord.begin(), ord.end(), [&](int i, int j){\n                    if (cands[i].lookVal != cands[j].lookVal) return cands[i].lookVal > cands[j].lookVal;\n                    return cands[i].r1.bestTree > cands[j].r1.bestTree;\n                });\n\n                uniform_real_distribution<double> uni(0.0, 1.0);\n                double r01 = uni(rng);\n\n                if (r01 > eps) {\n                    chosenIdx = ord[0];\n                } else {\n                    int pickBand = min<int>(3, (int)cands.size());\n                    chosenIdx = ord[rng() % pickBand];\n                }\n            }\n\n            // execute chosen move1\n            auto ch = cands[chosenIdx];\n            swap(curB[e], curB[ch.nei]);\n            e = ch.nei;\n            moves.push_back(dirChar[ch.dir]);\n            prevDir = ch.dir;\n            curEval = ch.r1;\n\n            // update run best\n            if (curEval.bestTree > bestTreeRun) {\n                bestTreeRun = curEval.bestTree;\n                bestMovesRun = moves;\n                bestKRun = (int)moves.size();\n                stagnation = 0;\n            } else {\n                stagnation++;\n            }\n\n            // update global best (tie-break smaller K)\n            if (bestTreeRun > bestTreeGlobal) {\n                bestTreeGlobal = bestTreeRun;\n                bestMovesGlobal = bestMovesRun;\n                bestKGlobal = bestKRun;\n            } else if (bestTreeRun == bestTreeGlobal && bestKRun < bestKGlobal) {\n                bestMovesGlobal = bestMovesRun;\n                bestKGlobal = bestKRun;\n            }\n        }\n\n        if (bestTreeGlobal == FULLTREE) {\n            // can't do better on S; sometimes still improve K via more restarts, but stop for time.\n            break;\n        }\n    }\n\n    string out;\n    out.reserve(bestMovesGlobal.size());\n    for (char c : bestMovesGlobal) out.push_back(c);\n    cout << out << \"\\n\";\n    return 0;\n}","ahc012":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\nstatic const ll LIM = 1'000'000'000LL;\n\nstruct Point { ll x, y; };\n\nstruct RNG {\n    uint64_t s;\n    explicit RNG(uint64_t seed) : s(seed) {}\n    static uint64_t splitmix64(uint64_t &x) {\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    ll nextLL(ll l, ll r) {\n        return (ll)(splitmix64(s) % (uint64_t)(r - l + 1)) + l;\n    }\n    int nextInt(int l, int r) { return (int)nextLL(l, r); }\n    bool chance(int p_per_1000) { return nextInt(1, 1000) <= p_per_1000; }\n};\n\nstatic inline bool in_bound(ll v) { return -LIM <= v && v <= LIM; }\n\n// orient:\n// 0: proj1=x,   proj2=y\n// 1: proj1=x,   proj2=x+y\n// 2: proj1=x,   proj2=x-y\n// 3: proj1=x+y, proj2=x-y\nstatic inline ll proj_value(int orient, const Point& p, int which) {\n    if (orient == 0) {\n        return (which == 0 ? p.x : p.y);\n    } else if (orient == 1) {\n        return (which == 0 ? p.x : (p.x + p.y));\n    } else if (orient == 2) {\n        return (which == 0 ? p.x : (p.x - p.y));\n    } else { // orient==3\n        return (which == 0 ? (p.x + p.y) : (p.x - p.y));\n    }\n}\n\nstatic ll choose_cut_for_boundary(\n    ll low, ll high, ll prev,\n    const unordered_set<ll>& occ,\n    RNG& rng,\n    bool allowOnPointMode,\n    int window = 400\n) {\n    if (low > high) swap(low, high);\n\n    auto is_free = [&](ll c)->bool{\n        if (!in_bound(c)) return false;\n        if (allowOnPointMode) return true;\n        return occ.find(c) == occ.end();\n    };\n\n    auto pick_near = [&](ll center)->ll {\n        for (int d = 0; d <= window; d++) {\n            ll c1 = center + d;\n            if (c1 > prev && is_free(c1)) return c1;\n            if (d != 0) {\n                ll c2 = center - d;\n                if (c2 > prev && is_free(c2)) return c2;\n            }\n        }\n        // fallback: first free above prev\n        ll c = max(prev + 1, (ll)-LIM);\n        while (c <= LIM && !allowOnPointMode && occ.find(c) != occ.end()) c++;\n        if (c <= LIM) return c;\n        return prev + 1;\n    };\n\n    // If there exists an integer strictly between low and high, prefer inside.\n    if (high - low >= 2) {\n        ll mid = (low + high) / 2;\n        // ensure strict inside\n        for (int d = 0; d <= window; d++) {\n            for (ll c : {mid + (ll)d, mid - (ll)d}) {\n                if (c <= prev) continue;\n                if (!(low < c && c < high)) continue;\n                if (is_free(c)) return c;\n            }\n        }\n        // if all inside are occupied (rare), relax to nearest above prev\n        return pick_near(mid);\n    }\n\n    // duplicates: low==high\n    if (high == low) {\n        // If allowing cut-through, take exactly low if possible.\n        if (allowOnPointMode && low > prev && in_bound(low)) return low;\n        // else shift by +/-1\n        ll c1 = low - 1;\n        if (c1 > prev && is_free(c1)) return c1;\n        ll c2 = low + 1;\n        if (c2 > prev && is_free(c2)) return c2;\n        return prev + 1;\n    }\n\n    // high == low + 1 : no integer strictly between\n    if (high == low + 1) {\n        if (allowOnPointMode) {\n            // randomly choose between low or high\n            if (rng.chance(500)) {\n                if (low > prev && in_bound(low)) return low;\n                if (high > prev && in_bound(high)) return high;\n            } else {\n                if (high > prev && in_bound(high)) return high;\n                if (low > prev && in_bound(low)) return low;\n            }\n            return prev + 1;\n        } else {\n            // shift boundary: choose high+1 (puts \"high\" points on left) if possible, else low-1\n            ll c = high + 1;\n            if (c > prev && is_free(c)) return c;\n            c = low - 1;\n            if (c > prev && is_free(c)) return c;\n            return prev + 1;\n        }\n    }\n\n    return prev + 1;\n}\n\nstatic vector<ll> make_cuts_by_quantiles(\n    const vector<ll>& sortedProj,\n    const unordered_set<ll>& occ,\n    int numCuts,\n    RNG& rng,\n    bool allowOnPointMode,\n    int maxShift = 2\n) {\n    int N = (int)sortedProj.size();\n    vector<ll> cuts;\n    cuts.reserve(numCuts);\n    if (numCuts == 0) return cuts;\n\n    int cols = numCuts + 1;\n    ll prev = -LIM - 5;\n\n    for (int t = 1; t <= numCuts; t++) {\n        ll desiredLeft = (ll)t * N / cols;\n        int idx = (int)desiredLeft;     // boundary at idx, right starts at idx\n        if (idx < 1) idx = 1;\n        if (idx > N - 1) idx = N - 1;\n\n        int off = rng.nextInt(-maxShift, maxShift);\n        int idx2 = idx + off;\n        idx2 = max(1, min(N - 1, idx2));\n\n        ll low = sortedProj[idx2 - 1];\n        ll high = sortedProj[idx2];\n\n        bool allow = allowOnPointMode && rng.chance(150); // small chance\n        ll c = choose_cut_for_boundary(low, high, prev, occ, rng, allow, 450);\n\n        if (c <= prev) c = prev + 1;\n        if (!in_bound(c)) {\n            c = prev + 1;\n            if (!in_bound(c)) c = -LIM;\n        }\n        if (!allowOnPointMode) {\n            while (c <= LIM && occ.find(c) != occ.end()) c++;\n            if (c > LIM) c = prev + 1;\n        }\n        // enforce strict increasing\n        if (c <= prev) c = prev + 1;\n\n        cuts.push_back(c);\n        prev = c;\n    }\n\n    // final strictness\n    for (int i = 1; i < (int)cuts.size(); i++) {\n        if (cuts[i] <= cuts[i-1]) cuts[i] = cuts[i-1] + 1;\n    }\n    return cuts;\n}\n\nstatic int evaluate_candidate(\n    const vector<ll>& proj1,\n    const vector<ll>& proj2,\n    const vector<ll>& cuts1,\n    const vector<ll>& cuts2,\n    const array<int,11>& a\n) {\n    int V = (int)cuts1.size();\n    int H = (int)cuts2.size();\n    int cols = V + 1;\n    int rows = H + 1;\n    int cells = cols * rows;\n\n    vector<int> cnt(cells, 0);\n\n    for (int i = 0; i < (int)proj1.size(); i++) {\n        ll u = proj1[i];\n        ll v = proj2[i];\n\n        // exclude strawberries on any cut line\n        auto it1 = lower_bound(cuts1.begin(), cuts1.end(), u);\n        if (it1 != cuts1.end() && *it1 == u) continue;\n        int col = (int)(it1 - cuts1.begin());\n\n        auto it2 = lower_bound(cuts2.begin(), cuts2.end(), v);\n        if (it2 != cuts2.end() && *it2 == v) continue;\n        int row = (int)(it2 - cuts2.begin());\n\n        if (0 <= col && col < cols && 0 <= row && row < rows) {\n            cnt[col * rows + row]++;\n        }\n    }\n\n    array<int,11> b{};\n    b.fill(0);\n    for (int x : cnt) {\n        if (1 <= x && x <= 10) b[x]++;\n    }\n\n    int matched = 0;\n    for (int d = 1; d <= 10; d++) matched += min(a[d], b[d]);\n    return matched;\n}\n\n// output line for a cut constant c in different family\nstatic void output_line_vertical(ll x, ostream& out) {\n    out << x << \" \" << -LIM << \" \" << x << \" \" << LIM << \"\\n\";\n}\nstatic void output_line_horizontal(ll y, ostream& out) {\n    out << -LIM << \" \" << y << \" \" << LIM << \" \" << y << \"\\n\";\n}\nstatic void output_line_x_plus_y(ll c, ostream& out) {\n    // x + y = c\n    out << 0 << \" \" << c << \" \" << 1 << \" \" << (c - 1) << \"\\n\";\n}\nstatic void output_line_x_minus_y(ll c, ostream& out) {\n    // x - y = c\n    out << c << \" \" << 0 << \" \" << (c + 1) << \" \" << 1 << \"\\n\";\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, K;\n    cin >> N >> K;\n    array<int,11> a{};\n    int sumA = 0;\n    for (int d = 1; d <= 10; d++) {\n        cin >> a[d];\n        sumA += a[d];\n    }\n\n    vector<Point> pts(N);\n    for (int i = 0; i < N; i++) cin >> pts[i].x >> pts[i].y;\n\n    // Precompute for 4 orientations\n    const int ORI = 4;\n    vector<vector<ll>> proj1(ORI, vector<ll>(N));\n    vector<vector<ll>> proj2(ORI, vector<ll>(N));\n    vector<vector<ll>> sorted1(ORI), sorted2(ORI);\n    vector<unordered_set<ll>> occ1(ORI), occ2(ORI);\n\n    for (int o = 0; o < ORI; o++) {\n        occ1[o].reserve((size_t)N * 2);\n        occ2[o].reserve((size_t)N * 2);\n        sorted1[o].reserve(N);\n        sorted2[o].reserve(N);\n        for (int i = 0; i < N; i++) {\n            ll p1 = proj_value(o, pts[i], 0);\n            ll p2 = proj_value(o, pts[i], 1);\n            proj1[o][i] = p1;\n            proj2[o][i] = p2;\n            sorted1[o].push_back(p1);\n            sorted2[o].push_back(p2);\n            occ1[o].insert(p1);\n            occ2[o].insert(p2);\n        }\n        sort(sorted1[o].begin(), sorted1[o].end());\n        sort(sorted2[o].begin(), sorted2[o].end());\n    }\n\n    // Poisson proxy candidate ranking:\n    // expected b_d ~ cells * P(Poisson(lambda)=d), lambda=N/cells.\n    // Then proxy = sum min(a_d, expected).\n    vector<pair<int,int>> cand;\n    cand.reserve((K+1)*(K+2)/2);\n\n    for (int V = 0; V <= K; V++) {\n        for (int H = 0; H <= K - V; H++) {\n            int cells = (V + 1) * (H + 1);\n            if (cells <= 0) continue;\n\n            long double lambda = (long double)N / (long double)cells;\n            // Filter ranges where d=1..10 has non-negligible probability.\n            if (lambda < 0.25L) continue;\n            if (lambda > 12.0L) continue;\n\n            long double logP0 = -lambda; // ln(exp(-lambda))\n            // Compute probabilities iteratively to avoid underflow:\n            // P(d) = P(0) * lambda^d / d!\n            long double P = expl(logP0); // P(0)\n            long double proxy = 0;\n            for (int d = 1; d <= 10; d++) {\n                // P(d) = P(d-1) * lambda / d\n                P = P * lambda / (long double)d;\n                long double expected = (long double)cells * P;\n                proxy += min((long double)a[d], expected);\n            }\n\n            // also reward more cells mildly (helps avoid huge pieces)\n            proxy += 0.002L * (long double)cells;\n            cand.push_back({V, H});\n        }\n    }\n\n    auto pairProxy = [&](pair<int,int> pr)->long double{\n        int V = pr.first, H = pr.second;\n        int cells = (V + 1) * (H + 1);\n        long double lambda = (long double)N / (long double)cells;\n        long double logP0 = -lambda;\n        long double P = expl(logP0);\n        long double proxy = 0;\n        for (int d = 1; d <= 10; d++) {\n            P = P * lambda / (long double)d;\n            long double expected = (long double)cells * P;\n            proxy += min((long double)a[d], expected);\n        }\n        proxy += 0.002L * (long double)cells;\n        // small balance term\n        proxy -= 0.0005L * fabsl((long double)V - (long double)H);\n        return proxy;\n    };\n\n    sort(cand.begin(), cand.end(), [&](auto &p, auto &q){\n        long double vp = pairProxy(p);\n        long double vq = pairProxy(q);\n        if (vp != vq) return vp > vq;\n        if (p.first + p.second != q.first + q.second) return p.first + p.second > q.first + q.second;\n        return (p.first+1)*(p.second+1) > (q.first+1)*(q.second+1);\n    });\n\n    int TOP = min<int>(120, cand.size());\n    cand.resize(TOP);\n\n    uint64_t seed = (uint64_t)chrono::high_resolution_clock::now().time_since_epoch().count();\n    int bestScore = -1;\n    int bestOri = 0;\n    vector<ll> bestCuts1, bestCuts2;\n\n    // Global randomized search (no local search inside to keep runtime stable)\n    int RESTARTS = 4;\n    int variantsPerPair = 6;\n\n    for (int r = 0; r < RESTARTS; r++) {\n        RNG rng(seed + 1000003ULL * (uint64_t)r);\n\n        for (int o = 0; o < ORI; o++) {\n            for (auto [V, H] : cand) {\n                if (V + H > K) continue;\n                for (int it = 0; it < variantsPerPair; it++) {\n                    bool allowOnPointMode = (it >= 4) && rng.chance(800); // rare\n                    int maxShift = 1 + (it / 3);\n\n                    auto c1 = make_cuts_by_quantiles(sorted1[o], occ1[o], V, rng, allowOnPointMode, maxShift);\n                    auto c2 = make_cuts_by_quantiles(sorted2[o], occ2[o], H, rng, allowOnPointMode, maxShift);\n\n                    int sc = evaluate_candidate(proj1[o], proj2[o], c1, c2, a);\n                    if (sc > bestScore) {\n                        bestScore = sc;\n                        bestOri = o;\n                        bestCuts1 = std::move(c1);\n                        bestCuts2 = std::move(c2);\n                    }\n                }\n            }\n        }\n    }\n\n    // Local search on best solution\n    // Try small moves avoiding cut-through constants when possible.\n    {\n        RNG rng(seed + 9999991ULL);\n        int o = bestOri;\n\n        vector<ll> c1 = bestCuts1;\n        vector<ll> c2 = bestCuts2;\n        int cur = bestScore;\n\n        int iters = 1200;\n        for (int it = 0; it < iters; it++) {\n            bool pickFirst = rng.chance(500);\n            if (pickFirst && !c1.empty()) {\n                int idx = rng.nextInt(0, (int)c1.size() - 1);\n                ll lo = (idx == 0 ? -LIM : c1[idx-1] + 1);\n                ll hi = (idx + 1 == (int)c1.size() ? LIM : c1[idx+1] - 1);\n                if (lo > hi) continue;\n\n                ll delta = (ll)rng.nextInt(0,1) ? 1 : -1;\n                delta *= (ll)rng.nextInt(1,2);\n                ll nc = c1[idx] + delta;\n                if (nc < lo || nc > hi) continue;\n\n                // avoid cut constants hitting points (usually helps)\n                if (occ1[o].find(nc) != occ1[o].end() && rng.chance(700)) continue;\n\n                vector<ll> n1 = c1;\n                n1[idx] = nc;\n\n                int ns = evaluate_candidate(proj1[o], proj2[o], n1, c2, a);\n                if (ns > cur) {\n                    cur = ns;\n                    c1.swap(n1);\n                }\n            } else if (!pickFirst && !c2.empty()) {\n                int idx = rng.nextInt(0, (int)c2.size() - 1);\n                ll lo = (idx == 0 ? -LIM : c2[idx-1] + 1);\n                ll hi = (idx + 1 == (int)c2.size() ? LIM : c2[idx+1] - 1);\n                if (lo > hi) continue;\n\n                ll delta = (ll)rng.nextInt(0,1) ? 1 : -1;\n                delta *= (ll)rng.nextInt(1,2);\n                ll nc = c2[idx] + delta;\n                if (nc < lo || nc > hi) continue;\n\n                if (occ2[o].find(nc) != occ2[o].end() && rng.chance(700)) continue;\n\n                vector<ll> n2 = c2;\n                n2[idx] = nc;\n\n                int ns = evaluate_candidate(proj1[o], proj2[o], c1, n2, a);\n                if (ns > cur) {\n                    cur = ns;\n                    c2.swap(n2);\n                }\n            }\n        }\n\n        bestCuts1.swap(c1);\n        bestCuts2.swap(c2);\n        bestScore = cur;\n    }\n\n    int k = (int)bestCuts1.size() + (int)bestCuts2.size();\n    if (k > K) { // should not happen\n        k = 0;\n        bestCuts1.clear();\n        bestCuts2.clear();\n    }\n\n    cout << k << \"\\n\";\n\n    // Output lines from bestOri and cut constants\n    for (ll c : bestCuts1) {\n        if (bestOri == 3) {\n            // proj1 = x+y\n            output_line_x_plus_y(c, cout);\n        } else {\n            // proj1 = x\n            output_line_vertical(c, cout);\n        }\n    }\n    for (ll c : bestCuts2) {\n        if (bestOri == 0) {\n            // proj2 = y\n            output_line_horizontal(c, cout);\n        } else if (bestOri == 1) {\n            // proj2 = x+y\n            output_line_x_plus_y(c, cout);\n        } else { // bestOri 2 or 3\n            // proj2 = x-y\n            output_line_x_minus_y(c, cout);\n        }\n    }\n\n    return 0;\n}","ahc014":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Edge {\n    // kind: 0=H, 1=V, 2=D1 (slope +1), 3=DM (slope -1)\n    int kind;\n    int a, b;\n};\n\nstatic inline int VID(int N, int x, int y) { return x * N + y; }\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M;\n    cin >> N >> M;\n    vector<char> initDot(N * N, 0);\n    for (int i = 0; i < M; i++) {\n        int x, y;\n        cin >> x >> y;\n        initDot[VID(N, x, y)] = 1;\n    }\n\n    const int c = (N - 1) / 2;\n    vector<long long> weight(N * N, 0);\n    for (int x = 0; x < N; x++) for (int y = 0; y < N; y++) {\n        long long dx = x - c, dy = y - c;\n        weight[VID(N, x, y)] = dx * dx + dy * dy + 1;\n    }\n\n    // Increase max sizes\n    const int LAX = 6;\n    const int LDI = 6;\n\n    // Rectangles store:\n    // - v[4] corners in cyclic order\n    // - edges: all unit segments on perimeter\n    // - mids: all intermediate lattice points on perimeter excluding corners\n    // Max perimeter unit edges for these shapes with sizes<=6 is <= 24\n    // Max intermediate points is <= 20\n    struct Rect {\n        array<int, 4> v{};\n        Edge edges[32];\n        int eLen = 0;\n        int mids[24];\n        int mLen = 0;\n    };\n\n    vector<Rect> rects;\n    rects.reserve(300000);\n\n    auto addAxisRect = [&](int x, int y, int dx, int dy) {\n        Rect r;\n        r.v = {VID(N, x, y), VID(N, x + dx, y), VID(N, x + dx, y + dy), VID(N, x, y + dy)};\n        r.eLen = 0;\n        r.mLen = 0;\n\n        // bottom horizontal edges: (x+t,y)->(x+t+1,y)\n        for (int t = 0; t < dx; t++) r.edges[r.eLen++] = Edge{0, x + t, y};\n        // top horizontal edges: y+dy\n        for (int t = 0; t < dx; t++) r.edges[r.eLen++] = Edge{0, x + t, y + dy};\n\n        // left vertical edges: x\n        for (int t = 0; t < dy; t++) r.edges[r.eLen++] = Edge{1, x, y + t};\n        // right vertical edges: x+dx\n        for (int t = 0; t < dy; t++) r.edges[r.eLen++] = Edge{1, x + dx, y + t};\n\n        // midpoints on perimeter excluding corners\n        // bottom/top excluding endpoints: t=1..dx-1\n        for (int t = 1; t < dx; t++) {\n            r.mids[r.mLen++] = VID(N, x + t, y);\n            r.mids[r.mLen++] = VID(N, x + t, y + dy);\n        }\n        // left/right excluding endpoints: t=1..dy-1\n        for (int t = 1; t < dy; t++) {\n            r.mids[r.mLen++] = VID(N, x, y + t);\n            r.mids[r.mLen++] = VID(N, x + dx, y + t);\n        }\n\n        rects.push_back(r);\n    };\n\n    for (int dx = 1; dx <= LAX; dx++) {\n        for (int dy = 1; dy <= LAX; dy++) {\n            for (int x = 0; x + dx < N; x++) {\n                for (int y = 0; y + dy < N; y++) {\n                    addAxisRect(x, y, dx, dy);\n                }\n            }\n        }\n    }\n\n    auto addDiagRect = [&](int x, int y, int a, int b) {\n        // Corners:\n        // A=(x,y)\n        // B=(x+a,y+a)\n        // C=(x+a+b, y+a-b)\n        // D=(x+b, y-b)\n        Rect r;\n        r.v = {VID(N, x, y),\n               VID(N, x + a, y + a),\n               VID(N, x + a + b, y + a - b),\n               VID(N, x + b, y - b)};\n        r.eLen = 0;\n        r.mLen = 0;\n\n        // A->B slope +1: unit edges (x+t,y+t)->(x+t+1,y+t+1)\n        for (int t = 0; t < a; t++) r.edges[r.eLen++] = Edge{2, x + t, y + t};\n\n        // B->C slope -1: unit edges between (k, l+1) and (k+1, l)\n        // For step t: (x+a+t, y+a-t) -> (x+a+t+1, y+a-t-1)\n        // lower y is (y+a-t-1)\n        for (int t = 0; t < b; t++) r.edges[r.eLen++] = Edge{3, x + a + t, y + a - t - 1};\n\n        // C->D: equivalent to D->C along slope +1 with length a\n        for (int t = 0; t < a; t++) {\n            // D->C unit: (x+b+t, y-b+t)->(x+b+t+1,y-b+t+1)\n            r.edges[r.eLen++] = Edge{2, x + b + t, y - b + t};\n        }\n\n        // D->A: slope -1. unit edges (x+t, y-t)->(x+t+1, y-t-1)\n        // lower y is (y-t-1)\n        for (int t = 0; t < b; t++) r.edges[r.eLen++] = Edge{3, x + t, y - t - 1};\n\n        // Midpoints excluding corners:\n        // A->B: (x+t,y+t), t=1..a-1\n        for (int t = 1; t < a; t++) r.mids[r.mLen++] = VID(N, x + t, y + t);\n        // B->C: (x+a+t, y+a-t), t=1..b-1\n        for (int t = 1; t < b; t++) r.mids[r.mLen++] = VID(N, x + a + t, y + a - t);\n        // C->D: (x+b+t, y-b+t), t=1..a-1\n        for (int t = 1; t < a; t++) r.mids[r.mLen++] = VID(N, x + b + t, y - b + t);\n        // D->A: (x+t, y-t), t=1..b-1\n        for (int t = 1; t < b; t++) r.mids[r.mLen++] = VID(N, x + t, y - t);\n\n        rects.push_back(r);\n    };\n\n    // Enumerate 45-degree rectangles with sizes <= LDI:\n    // Need x+a+b < N, and y-b >= 0 and y+a < N.\n    for (int a = 1; a <= LDI; a++) {\n        for (int b = 1; b <= LDI; b++) {\n            for (int x = 0; x + a + b < N; x++) {\n                for (int y = b; y + a < N; y++) {\n                    addDiagRect(x, y, a, b);\n                }\n            }\n        }\n    }\n\n    int R = (int)rects.size();\n\n    // Build adjacency:\n    // adjCorner[v] = rectangles where v is a corner\n    // adjMid[v] = rectangles where v is a midpoint (excluding corners)\n    vector<vector<int>> adjCorner(N * N), adjMid(N * N);\n    adjCorner.assign(N * N, {});\n    adjMid.assign(N * N, {});\n    for (int rid = 0; rid < R; rid++) {\n        for (int k = 0; k < 4; k++) adjCorner[rects[rid].v[k]].push_back(rid);\n        for (int i = 0; i < rects[rid].mLen; i++) adjMid[rects[rid].mids[i]].push_back(rid);\n    }\n\n    struct Candidate {\n        long long key;\n        int rid;\n        // max heap\n        bool operator<(Candidate const& o) const { return key < o.key; }\n    };\n\n    auto run = [&](long long lambdaPotential, uint64_t seedJitter) -> long long {\n        vector<char> dot = initDot;\n        vector<int> cnt(R, 0);\n        vector<char> usedRect(R, 0);\n\n        // Used unit segments for condition3\n        // H: Edge{0, a=x, b=y} where a in [0..N-2], b in [0..N-1]\n        vector<uint8_t> usedH((N - 1) * N, 0);\n        // V: Edge{1, a=x, b=y} where a in [0..N-1], b in [0..N-2]\n        vector<uint8_t> usedV(N * (N - 1), 0);\n        // D1: Edge{2, a=x, b=y} where a in [0..N-2], b in [0..N-2]\n        vector<uint8_t> usedD1((N - 1) * (N - 1), 0);\n        // DM: Edge{3, a=x, b=y} where a in [0..N-2], b in [0..N-2]\n        vector<uint8_t> usedDM((N - 1) * (N - 1), 0);\n\n        auto edgeUsed = [&](const Edge& e) -> bool {\n            if (e.kind == 0) return usedH[e.a * N + e.b];\n            if (e.kind == 1) return usedV[e.a * (N - 1) + e.b];\n            if (e.kind == 2) return usedD1[e.a * (N - 1) + e.b];\n            return usedDM[e.a * (N - 1) + e.b];\n        };\n        auto setEdgeUsed = [&](const Edge& e) {\n            if (e.kind == 0) usedH[e.a * N + e.b] = 1;\n            else if (e.kind == 1) usedV[e.a * (N - 1) + e.b] = 1;\n            else if (e.kind == 2) usedD1[e.a * (N - 1) + e.b] = 1;\n            else usedDM[e.a * (N - 1) + e.b] = 1;\n        };\n\n        auto edgesAvailable = [&](int rid) -> bool {\n            const Rect& r = rects[rid];\n            for (int i = 0; i < r.eLen; i++) {\n                if (edgeUsed(r.edges[i])) return false;\n            }\n            return true;\n        };\n\n        // midCnt[rid] = number of dots currently on its midpoints\n        vector<int> midCnt(R, 0);\n        for (int v = 0; v < N * N; v++) if (dot[v]) {\n            for (int rid : adjMid[v]) midCnt[rid]++;\n        }\n\n        long long sumW = 0;\n        for (int v = 0; v < N * N; v++) if (dot[v]) sumW += weight[v];\n\n        for (int rid = 0; rid < R; rid++) {\n            int s = 0;\n            for (int k = 0; k < 4; k++) s += dot[rects[rid].v[k]] ? 1 : 0;\n            cnt[rid] = s;\n        }\n\n        priority_queue<Candidate> pq;\n        mt19937_64 rng(seedJitter);\n\n        auto pushIf = [&](int rid) {\n            if (usedRect[rid]) return;\n            if (cnt[rid] != 3) return;\n            if (midCnt[rid] != 0) return; // some dot on perimeter midpoints => condition2 fails\n\n            // missing corner u\n            int u = -1;\n            int missIdx = -1;\n            for (int k = 0; k < 4; k++) {\n                int vid = rects[rid].v[k];\n                if (!dot[vid]) { u = vid; missIdx = k; break; }\n            }\n            if (u < 0) return;\n\n            if (!edgesAvailable(rid)) return;\n\n            // Improved potential: count adjacent rectangles rr that would become feasible now\n            long long potential = 0;\n            for (int rr : adjCorner[u]) {\n                if (usedRect[rr]) continue;\n                if (cnt[rr] != 2) continue;\n                if (midCnt[rr] != 0) continue;\n                if (!edgesAvailable(rr)) continue; // ensure we don't overestimate unrealizable potential\n                potential++;\n            }\n\n            // small jitter to diversify ties\n            long long jitter = (long long)(rng() % 7); // 0..6\n            long long key = weight[u] + lambdaPotential * potential + jitter;\n\n            pq.push(Candidate{key, rid});\n        };\n\n        for (int rid = 0; rid < R; rid++) if (cnt[rid] == 3) pushIf(rid);\n\n        while (!pq.empty()) {\n            auto cur = pq.top(); pq.pop();\n            int rid = cur.rid;\n\n            if (usedRect[rid] || cnt[rid] != 3 || midCnt[rid] != 0) continue;\n            if (!edgesAvailable(rid)) continue;\n\n            // missing corner u\n            int u = -1;\n            int missIdx = -1;\n            for (int k = 0; k < 4; k++) {\n                int vid = rects[rid].v[k];\n                if (!dot[vid]) { u = vid; missIdx = k; break; }\n            }\n            if (u < 0) continue;\n\n            // execute move\n            usedRect[rid] = 1;\n            const Rect& r = rects[rid];\n            for (int i = 0; i < r.eLen; i++) setEdgeUsed(r.edges[i]);\n\n            dot[u] = 1;\n            sumW += weight[u];\n\n            // update cnt for rectangles where u is a corner\n            for (int rr : adjCorner[u]) {\n                if (usedRect[rr]) continue;\n                cnt[rr]++;\n                if (cnt[rr] == 3) pushIf(rr);\n            }\n            // update midCnt for rectangles where u is a midpoint\n            for (int rr : adjMid[u]) {\n                if (usedRect[rr]) continue;\n                midCnt[rr]++; // now violates condition2 (midpoint must be empty)\n            }\n        }\n\n        return sumW;\n    };\n\n    // Multiple runs with different lambdas and jitter seeds; keep best score.\n    // (Score is affine in sumW, so maximizing sumW is sufficient.)\n    vector<long long> lambdas = {0, 2, 4, 6, 8};\n    long long bestSum = -1;\n\n    // deterministic jitter seeds\n    vector<uint64_t> seeds = {1, 17, 123, 999, 2021, 7777};\n\n    for (int i = 0; i < (int)lambdas.size(); i++) {\n        long long lam = lambdas[i];\n        uint64_t seedJ = seeds[i % (int)seeds.size()] ^ (uint64_t)M * 1234567ULL ^ (uint64_t)N;\n        bestSum = max(bestSum, run(lam, seedJ));\n    }\n\n    // Now we still need to output operations, so we re-run once more with the best lambda\n    // but in a version that records ops.\n    auto runRecord = [&](long long lambdaPotential, uint64_t seedJitter) -> pair<long long, vector<array<int,4>>> {\n        vector<char> dot = initDot;\n        vector<int> cnt(R, 0);\n        vector<char> usedRect(R, 0);\n\n        vector<uint8_t> usedH((N - 1) * N, 0);\n        vector<uint8_t> usedV(N * (N - 1), 0);\n        vector<uint8_t> usedD1((N - 1) * (N - 1), 0);\n        vector<uint8_t> usedDM((N - 1) * (N - 1), 0);\n\n        auto edgeUsed = [&](const Edge& e) -> bool {\n            if (e.kind == 0) return usedH[e.a * N + e.b];\n            if (e.kind == 1) return usedV[e.a * (N - 1) + e.b];\n            if (e.kind == 2) return usedD1[e.a * (N - 1) + e.b];\n            return usedDM[e.a * (N - 1) + e.b];\n        };\n        auto setEdgeUsed = [&](const Edge& e) {\n            if (e.kind == 0) usedH[e.a * N + e.b] = 1;\n            else if (e.kind == 1) usedV[e.a * (N - 1) + e.b] = 1;\n            else if (e.kind == 2) usedD1[e.a * (N - 1) + e.b] = 1;\n            else usedDM[e.a * (N - 1) + e.b] = 1;\n        };\n\n        auto edgesAvailable = [&](int rid) -> bool {\n            const Rect& r = rects[rid];\n            for (int i = 0; i < r.eLen; i++) if (edgeUsed(r.edges[i])) return false;\n            return true;\n        };\n\n        vector<int> midCnt(R, 0);\n        for (int v = 0; v < N * N; v++) if (dot[v]) for (int rid : adjMid[v]) midCnt[rid]++;\n\n        long long sumW = 0;\n        for (int v = 0; v < N * N; v++) if (dot[v]) sumW += weight[v];\n\n        for (int rid = 0; rid < R; rid++) {\n            int s = 0;\n            for (int k = 0; k < 4; k++) s += dot[rects[rid].v[k]] ? 1 : 0;\n            cnt[rid] = s;\n        }\n\n        priority_queue<Candidate> pq;\n        mt19937_64 rng(seedJitter);\n\n        vector<array<int,4>> ops;\n\n        auto pushIf = [&](int rid) {\n            if (usedRect[rid]) return;\n            if (cnt[rid] != 3) return;\n            if (midCnt[rid] != 0) return;\n\n            int u = -1;\n            for (int k = 0; k < 4; k++) {\n                int vid = rects[rid].v[k];\n                if (!dot[vid]) { u = vid; break; }\n            }\n            if (u < 0) return;\n\n            if (!edgesAvailable(rid)) return;\n\n            long long potential = 0;\n            for (int rr : adjCorner[u]) {\n                if (usedRect[rr]) continue;\n                if (cnt[rr] != 2) continue;\n                if (midCnt[rr] != 0) continue;\n                if (!edgesAvailable(rr)) continue;\n                potential++;\n            }\n\n            long long jitter = (long long)(rng() % 7);\n            long long key = weight[u] + lambdaPotential * potential + jitter;\n            pq.push(Candidate{key, rid});\n        };\n\n        for (int rid = 0; rid < R; rid++) if (cnt[rid] == 3) pushIf(rid);\n\n        while (!pq.empty()) {\n            auto cur = pq.top(); pq.pop();\n            int rid = cur.rid;\n\n            if (usedRect[rid] || cnt[rid] != 3 || midCnt[rid] != 0) continue;\n            if (!edgesAvailable(rid)) continue;\n\n            int u = -1;\n            int missIdx = -1;\n            for (int k = 0; k < 4; k++) {\n                int vid = rects[rid].v[k];\n                if (!dot[vid]) { u = vid; missIdx = k; break; }\n            }\n            if (u < 0) continue;\n\n            usedRect[rid] = 1;\n            const Rect& r = rects[rid];\n            for (int i = 0; i < r.eLen; i++) setEdgeUsed(r.edges[i]);\n\n            dot[u] = 1;\n            sumW += weight[u];\n\n            array<int,4> op{};\n            for (int t = 0; t < 4; t++) op[t] = r.v[(missIdx + t) % 4];\n            ops.push_back(op);\n\n            for (int rr : adjCorner[u]) {\n                if (usedRect[rr]) continue;\n                cnt[rr]++;\n                if (cnt[rr] == 3) pushIf(rr);\n            }\n            for (int rr : adjMid[u]) {\n                if (usedRect[rr]) continue;\n                midCnt[rr]++;\n            }\n        }\n        return {sumW, ops};\n    };\n\n    // Choose lambda that gave bestSum by re-evaluating in same way\n    long long chosenLambda = lambdas[0];\n    for (long long lam : lambdas) {\n        uint64_t seedJ = 1 ^ (uint64_t)M * 1234567ULL ^ (uint64_t)N ^ (uint64_t)lam;\n        long long s = run(lam, seedJ);\n        if (s == bestSum) { chosenLambda = lam; break; }\n    }\n\n    // Record operations with chosen lambda\n    uint64_t seedJ = 123456789ULL ^ (uint64_t)N * 10007ULL ^ (uint64_t)M * 10009ULL ^ (uint64_t)chosenLambda;\n    auto [bestRecordedSum, ops] = runRecord(chosenLambda, seedJ);\n\n    // Output\n    cout << ops.size() << \"\\n\";\n    for (auto &op : ops) {\n        for (int t = 0; t < 4; t++) {\n            int vid = op[t];\n            int x = vid / N;\n            int y = vid % N;\n            cout << x << \" \" << y << (t == 3 ? '\\n' : ' ');\n        }\n    }\n    return 0;\n}","ahc015":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct State {\n    // value 0..3, 0 = empty\n    array<uint8_t, 100> a{};\n};\n\nstatic inline int id(int r, int c) { return r * 10 + c; }\n\nstatic int neigh[100][4]; // -1 if out of grid\n\nstatic State tilt(const State& s, int dir) {\n    // dir: 0=F(up), 1=B(down), 2=L(left), 3=R(right)\n    State t;\n    t.a.fill(0);\n\n    if (dir == 0) { // F: r -> 0\n        for (int c = 0; c < 10; c++) {\n            int k = 0;\n            for (int r = 0; r < 10; r++) {\n                uint8_t v = s.a[id(r, c)];\n                if (v) t.a[id(k++, c)] = v;\n            }\n        }\n    } else if (dir == 1) { // B: r -> 9\n        for (int c = 0; c < 10; c++) {\n            int k = 9;\n            for (int r = 9; r >= 0; r--) {\n                uint8_t v = s.a[id(r, c)];\n                if (v) t.a[id(k--, c)] = v;\n            }\n        }\n    } else if (dir == 2) { // L: c -> 0\n        for (int r = 0; r < 10; r++) {\n            int k = 0;\n            for (int c = 0; c < 10; c++) {\n                uint8_t v = s.a[id(r, c)];\n                if (v) t.a[id(r, k++)] = v;\n            }\n        }\n    } else { // R: c -> 9\n        for (int r = 0; r < 10; r++) {\n            int k = 9;\n            for (int c = 9; c >= 0; c--) {\n                uint8_t v = s.a[id(r, c)];\n                if (v) t.a[id(r, k--)] = v;\n            }\n        }\n    }\n    return t;\n}\n\nstatic int visStamp = 1;\nstatic int vis[100];\nstatic int qbuf[100];\n\nstatic long long calcNumerator(const State& s) {\n    if (++visStamp == INT_MAX) {\n        memset(vis, 0, sizeof(vis));\n        visStamp = 1;\n    }\n\n    long long sum = 0;\n    for (int st = 0; st < 100; st++) {\n        if (s.a[st] == 0 || vis[st] == visStamp) continue;\n        uint8_t flavor = s.a[st];\n\n        int head = 0, tail = 0;\n        qbuf[tail++] = st;\n        vis[st] = visStamp;\n\n        long long cnt = 0;\n        while (head < tail) {\n            int v = qbuf[head++];\n            cnt++;\n            for (int k = 0; k < 4; k++) {\n                int u = neigh[v][k];\n                if (u < 0) continue;\n                if (vis[u] == visStamp) continue;\n                if (s.a[u] != flavor) continue;\n                vis[u] = visStamp;\n                qbuf[tail++] = u;\n            }\n        }\n        sum += cnt * cnt;\n    }\n    return sum;\n}\n\nstatic vector<int> emptiesOf(const State& s) {\n    vector<int> e;\n    e.reserve(100);\n    for (int i = 0; i < 100; i++) if (s.a[i] == 0) e.push_back(i);\n    return e;\n}\n\nstatic int findCellByPT(const State& g, int p) {\n    int cnt = 0;\n    for (int i = 0; i < 100; i++) {\n        if (g.a[i] == 0) {\n            cnt++;\n            if (cnt == p) return i;\n        }\n    }\n    return -1;\n}\n\nstatic vector<int> F; // 1..100\n\n// Exact expectimax for t in late game: compute optimal expected final numerator\nstatic long double solveExactValue(const State& s, int k) {\n    // k: next step index where we must choose direction after placing F[k]\n    if (k == 100) return (long double)calcNumerator(s);\n    uint8_t nextFlavor = (uint8_t)F[k + 1];\n\n    long double best = -1e100L;\n    for (int dir = 0; dir < 4; dir++) {\n        State s1 = tilt(s, dir);\n        vector<int> e = emptiesOf(s1);\n        long double sum = 0;\n\n        int E = (int)e.size();\n        for (int cell : e) {\n            State s2 = s1;\n            s2.a[cell] = nextFlavor;\n            sum += solveExactValue(s2, k + 1);\n        }\n        long double val = sum / (long double)E;\n        if (val > best) best = val;\n    }\n    return best;\n}\n\nstatic int chooseDirExact(const State& s, int k) {\n    // choose direction at step k\n    uint8_t nextFlavor = (uint8_t)F[k + 1];\n\n    int bestDir = 0;\n    long double bestVal = -1e100L;\n\n    for (int dir = 0; dir < 4; dir++) {\n        State s1 = tilt(s, dir);\n        vector<int> e = emptiesOf(s1);\n\n        long double sum = 0;\n        int E = (int)e.size();\n        for (int cell : e) {\n            State s2 = s1;\n            s2.a[cell] = nextFlavor;\n            sum += solveExactValue(s2, k + 1);\n        }\n        long double val = sum / (long double)E;\n\n        if (val > bestVal) {\n            bestVal = val;\n            bestDir = dir;\n        } else if (fabsl(val - bestVal) <= 1e-12L) {\n            // tie-break by immediate numerator after first tilt\n            long long immNew = calcNumerator(s1);\n            long long immBest = calcNumerator(tilt(s, bestDir));\n            if (immNew > immBest) bestDir = dir;\n        }\n    }\n    return bestDir;\n}\n\nstatic vector<int> sampleK(const vector<int>& v, int K, mt19937_64& rng) {\n    if ((int)v.size() <= K) return v;\n    vector<int> w = v;\n    shuffle(w.begin(), w.end(), rng);\n    w.resize(K);\n    return w;\n}\n\n// Fast 2-step lookahead (greedy choices for dir1/dir2), with unbiased sampling.\nstatic long double estimateDepth2(const State& s0, int t, mt19937_64& rng) {\n    // s0 is state after applying direction at step t (i.e., before placing F[t+1])\n    uint8_t f1 = (uint8_t)F[t + 1];\n    uint8_t f2 = (uint8_t)F[t + 2];\n\n    vector<int> e1 = emptiesOf(s0);\n    int E1 = (int)e1.size();\n\n    int K1;\n    if (E1 <= 16) K1 = E1;\n    else if (E1 <= 40) K1 = 8;\n    else K1 = 6;\n\n    K1 = min(K1, E1);\n    vector<int> cells1 = sampleK(e1, K1, rng);\n\n    long double total = 0;\n    for (int c1 : cells1) {\n        State s1 = s0;\n        s1.a[c1] = f1;\n\n        // choose dir1 by immediate numerator (greedy)\n        long long bestNum1 = -1;\n        State bestT1;\n        for (int dir1 = 0; dir1 < 4; dir1++) {\n            State t1 = tilt(s1, dir1);\n            long long num1 = calcNumerator(t1);\n            if (num1 > bestNum1) {\n                bestNum1 = num1;\n                bestT1 = t1;\n            }\n        }\n\n        // sample placements for f2 in bestT1, then choose dir2 greedily by max numerator\n        vector<int> e2 = emptiesOf(bestT1);\n        int E2 = (int)e2.size();\n        int K2;\n        if (E2 <= 16) K2 = E2;\n        else if (E2 <= 40) K2 = 4; // slightly increased from 3 to improve quality\n        else K2 = 2;\n        K2 = min(K2, E2);\n\n        vector<int> cells2 = sampleK(e2, K2, rng);\n\n        long double sum2 = 0;\n        for (int c2 : cells2) {\n            State s2 = bestT1;\n            s2.a[c2] = f2;\n\n            long long bestNum2 = -1;\n            for (int dir2 = 0; dir2 < 4; dir2++) {\n                State t2 = tilt(s2, dir2);\n                bestNum2 = max(bestNum2, calcNumerator(t2));\n            }\n            sum2 += (long double)bestNum2;\n        }\n\n        total += sum2 / (long double)cells2.size();\n    }\n\n    return total / (long double)cells1.size();\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    for (int r = 0; r < 10; r++) for (int c = 0; c < 10; c++) {\n        int v = id(r, c);\n        // 0: down, 1: up, 2: right, 3: left (order arbitrary)\n        neigh[v][0] = (r + 1 < 10) ? id(r + 1, c) : -1;\n        neigh[v][1] = (r - 1 >= 0) ? id(r - 1, c) : -1;\n        neigh[v][2] = (c + 1 < 10) ? id(r, c + 1) : -1;\n        neigh[v][3] = (c - 1 >= 0) ? id(r, c - 1) : -1;\n    }\n\n    F.assign(101, 0);\n    for (int i = 1; i <= 100; i++) cin >> F[i];\n\n    State g;\n    g.a.fill(0);\n\n    const char dirChar[4] = {'F', 'B', 'L', 'R'};\n\n    // RNG seed (deterministic-ish per run)\n    uint64_t seed = 0x9e3779b97f4a7c15ULL;\n    for (int i = 1; i <= 100; i++) seed = seed * 1315423911u + (uint64_t)F[i] + i;\n    std::mt19937_64 rng(seed);\n\n    for (int t = 1; t <= 100; t++) {\n        int p;\n        cin >> p;\n\n        int cell = findCellByPT(g, p);\n        g.a[cell] = (uint8_t)F[t];\n\n        if (t == 100) break;\n\n        int bestDir = 0;\n        long double bestVal = -1e100L;\n\n        // Exact expectimax earlier to fix late-game weaknesses.\n        if (t >= 95) {\n            bestDir = chooseDirExact(g, t);\n        } else {\n            for (int dir0 = 0; dir0 < 4; dir0++) {\n                State s0 = tilt(g, dir0);\n                long double val = estimateDepth2(s0, t, rng);\n                if (val > bestVal) {\n                    bestVal = val;\n                    bestDir = dir0;\n                }\n            }\n        }\n\n        g = tilt(g, bestDir);\n        cout << dirChar[bestDir] << \"\\n\" << flush;\n    }\n    return 0;\n}","ahc016":"#include <bits/stdc++.h>\nusing namespace std;\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 int popcnt_u64(uint64_t x) { return (int)__builtin_popcountll(x); }\n\nstruct Invariants {\n    int edges = 0;\n    long long twoStars = 0;\n    long long triangles = 0;\n    vector<int> degSorted;\n};\n\nstruct WLMethod {\n    int N;\n    int L;\n    int T;\n    vector<long long> offset; // for upper triangle indexing by rank positions\n    vector<uint64_t> maskGT;  // maskGT[j] = bits k where k>j\n    int Wwords;\n\n    uint64_t saltDeg;\n    uint64_t saltStep1;\n    uint64_t saltStep2;\n    uint64_t saltNeigh;\n\n    WLMethod(int N_, int L_,\n             uint64_t sdeg, uint64_t s1, uint64_t s2, uint64_t sne)\n        : N(N_), L(L_),\n          T(N_ * (N_ - 1) / 2),\n          offset(N_, 0),\n          saltDeg(sdeg), saltStep1(s1), saltStep2(s2), saltNeigh(sne) {\n\n        for (int i = 0; i < N; i++) offset[i] = 1LL * i * (2LL * N - i - 1) / 2;\n\n        uint64_t fullMask = (N == 64 ? ~0ULL : ((1ULL << N) - 1ULL));\n        maskGT.assign(N, 0);\n        for (int j = 0; j < N; j++) {\n            // bits > j => [j+1..N-1]\n            uint64_t le;\n            if (j + 1 >= 64) le = ~0ULL;\n            else if (j + 1 == 0) le = 0;\n            else le = (1ULL << (j + 1)) - 1ULL;\n            maskGT[j] = fullMask & ~le;\n        }\n\n        Wwords = (T + 63) / 64;\n    }\n\n    Invariants computeInvariants(const vector<uint64_t>& adj) const {\n        vector<int> deg(N);\n        long long edges2 = 0;\n        for (int v = 0; v < N; v++) {\n            deg[v] = popcnt_u64(adj[v]);\n            edges2 += deg[v];\n        }\n        int edges = (int)(edges2 / 2);\n\n        long long twoStars = 0;\n        for (int v = 0; v < N; v++) {\n            long long d = deg[v];\n            twoStars += d * (d - 1) / 2;\n        }\n\n        long long triangles = 0;\n        // count i<j<k using i<j edges and k>j restriction\n        for (int i = 0; i < N; i++) {\n            for (int j = i + 1; j < N; j++) {\n                if ((adj[i] >> j) & 1ULL) {\n                    uint64_t common = adj[i] & adj[j] & maskGT[j]; // k>j\n                    triangles += popcnt_u64(common);\n                }\n            }\n        }\n\n        vector<int> degSorted = deg;\n        sort(degSorted.begin(), degSorted.end());\n\n        return Invariants{edges, twoStars, triangles, std::move(degSorted)};\n    }\n\n    // Hash of multiset { colFinal[u] : u neighbor of v }, but computed from row bitmask directly.\n    uint64_t neighborSignature(uint64_t rowMask, const vector<uint64_t>& colFinal) const {\n        vector<uint64_t> lst;\n        while (rowMask) {\n            int u = __builtin_ctzll(rowMask);\n            rowMask &= rowMask - 1;\n            lst.push_back(colFinal[u]);\n        }\n        sort(lst.begin(), lst.end());\n\n        uint64_t h = 1469598103934665603ULL ^ saltNeigh;\n        for (auto x : lst) {\n            h ^= splitmix64(x + 0x9ddfea08eb382d69ULL);\n            h *= 1099511628211ULL;\n        }\n        return h;\n    }\n\n    vector<uint64_t> canonicalBits(const vector<uint64_t>& adj) const {\n        vector<int> deg(N);\n        for (int v = 0; v < N; v++) deg[v] = popcnt_u64(adj[v]);\n\n        // WL colors over rounds\n        vector<vector<uint64_t>> col(L + 1, vector<uint64_t>(N, 0));\n        for (int v = 0; v < N; v++) {\n            col[0][v] = splitmix64((uint64_t)deg[v] + saltDeg);\n        }\n\n        const uint64_t A1 = 0x1234567890abcdefULL;\n        const uint64_t A2 = 0xfedcba0987654321ULL;\n        const uint64_t A3 = 0x0f0f0f0f0f0f0f0fULL;\n\n        for (int r = 0; r < L; r++) {\n            for (int v = 0; v < N; v++) {\n                uint64_t sum1 = 0, sum2 = 0, xr = 0;\n                int cnt = 0;\n                uint64_t row = adj[v];\n                while (row) {\n                    int u = __builtin_ctzll(row);\n                    row &= row - 1;\n                    uint64_t cu = col[r][u];\n\n                    // fixed precedence with parentheses\n                    sum1 += splitmix64((cu + A1) ^ saltStep1);\n                    sum2 += splitmix64((cu + A2) ^ saltStep2);\n                    xr ^= splitmix64(cu + A3);\n                    cnt++;\n                }\n                uint64_t oldc = col[r][v];\n                uint64_t nc =\n                    splitmix64(oldc ^ (sum1 + 0x9e3779b97f4a7c15ULL)) ^\n                    splitmix64(sum2 ^ 0xbf58476d1ce4e5b9ULL) ^\n                    (xr + splitmix64((uint64_t)cnt + 0x94d049bb133111ebULL));\n                col[r + 1][v] = nc;\n            }\n        }\n\n        vector<uint64_t> colFinal(N);\n        for (int v = 0; v < N; v++) colFinal[v] = col[L][v];\n\n        // Neighbor-signature for tie-breaking (permutation-invariant)\n        vector<uint64_t> neighSig(N);\n        for (int v = 0; v < N; v++) {\n            neighSig[v] = neighborSignature(adj[v], colFinal);\n        }\n\n        // Canonical order: lexicographic by (all-round colors), then neighSig, then degree, then index.\n        vector<int> ord(N);\n        iota(ord.begin(), ord.end(), 0);\n\n        auto cmp = [&](int a, int b) {\n            for (int r = 0; r <= L; r++) {\n                uint64_t ca = col[r][a], cb = col[r][b];\n                if (ca != cb) return ca < cb;\n            }\n            if (neighSig[a] != neighSig[b]) return neighSig[a] < neighSig[b];\n            if (deg[a] != deg[b]) return deg[a] < deg[b];\n            return a < b; // last resort\n        };\n        sort(ord.begin(), ord.end(), cmp);\n\n        // Build upper-triangle adjacency bits in canonical order\n        vector<uint64_t> bits(Wwords, 0);\n        for (int ai = 0; ai < N; ai++) {\n            int oa = ord[ai];\n            uint64_t row = adj[oa];\n            for (int bj = ai + 1; bj < N; bj++) {\n                int ob = ord[bj];\n                if ((row >> ob) & 1ULL) {\n                    int pos = (int)offset[ai] + (bj - ai - 1);\n                    bits[pos >> 6] |= (1ULL << (pos & 63));\n                }\n            }\n        }\n        return bits;\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int M;\n    double epsInput;\n    cin >> M >> epsInput;\n    double eps = epsInput;\n\n    // Tune N and WL rounds\n    int N;\n    if (eps <= 0.15) N = 25;\n    else if (eps <= 0.25) N = 30;\n    else if (eps <= 0.35) N = 32;\n    else N = 35;\n\n    int L = (N >= 32 ? 3 : 4);\n\n    int T = N * (N - 1) / 2;\n    int Wwords = (T + 63) / 64;\n\n    // fixed-label encoding distance for selecting diverse codewords (anchors)\n    vector<long long> offsetFixed(N, 0);\n    for (int i = 0; i < N; i++) offsetFixed[i] = 1LL * i * (2LL * N - i - 1) / 2;\n\n    auto encodeFixed = [&](const vector<uint64_t>& adj) -> vector<uint64_t> {\n        vector<uint64_t> bits(Wwords, 0);\n        for (int ai = 0; ai < N; ai++) {\n            uint64_t row = adj[ai];\n            for (int bj = ai + 1; bj < N; bj++) {\n                if ((row >> bj) & 1ULL) {\n                    int pos = (int)offsetFixed[ai] + (bj - ai - 1);\n                    bits[pos >> 6] |= (1ULL << (pos & 63));\n                }\n            }\n        }\n        return bits;\n    };\n\n    auto distHam = [&](const vector<uint64_t>& A, const vector<uint64_t>& B) -> int {\n        int d = 0;\n        for (int w = 0; w < Wwords; w++) d += popcnt_u64(A[w] ^ B[w]);\n        return d;\n    };\n\n    // Ensemble WL methods\n    vector<WLMethod> methods;\n    methods.emplace_back(N, L, 0x1111111111111111ULL, 0x2222222222222222ULL, 0x3333333333333333ULL, 0x4444444444444444ULL);\n    methods.emplace_back(N, L, 0xaaaaaaaaaaaaaaaaULL, 0xbbbbbbbbbbbbbbbbULL, 0xccccccccccccccccULL, 0xddddddddddddddddULL);\n    methods.emplace_back(N, L, 0x0123456789abcdefULL, 0xfedcba9876543210ULL, 0x0f0f0f0f0f0f0f0fULL, 0x2222333344445555ULL);\n\n    // Candidate pool generation + greedy farthest selection\n    uint64_t seedBase = 0x6a09e667f3bcc909ULL\n                        ^ splitmix64((uint64_t)(M * 1000ULL))\n                        ^ splitmix64((uint64_t)llround(eps * 1000.0));\n\n    auto nextRand = [&](uint64_t &st) -> uint64_t {\n        st = splitmix64(st);\n        return st;\n    };\n\n    int poolSize = min(2500, 15 * M + 200);\n    vector<vector<uint64_t>> poolAdj;\n    vector<vector<uint64_t>> poolFixedBits;\n    poolAdj.reserve(poolSize);\n    poolFixedBits.reserve(poolSize);\n\n    for (int p = 0; p < poolSize; p++) {\n        uint64_t st = seedBase ^ splitmix64((uint64_t)p * 0x9e3779b97f4a7c15ULL);\n        vector<uint64_t> adj(N, 0ULL);\n        for (int i = 0; i < N; i++) {\n            for (int j = i + 1; j < N; j++) {\n                uint64_t r = nextRand(st);\n                if (r & 1ULL) {\n                    adj[i] |= (1ULL << j);\n                    adj[j] |= (1ULL << i);\n                }\n            }\n        }\n        poolAdj.push_back(std::move(adj));\n        poolFixedBits.push_back(encodeFixed(poolAdj.back()));\n    }\n\n    vector<int> chosen;\n    chosen.reserve(M);\n    chosen.push_back(0);\n\n    vector<int> minDist(poolSize, INT_MAX);\n    for (int i = 0; i < poolSize; i++) minDist[i] = distHam(poolFixedBits[i], poolFixedBits[chosen[0]]);\n    minDist[chosen[0]] = -1;\n\n    for (int it = 1; it < M; it++) {\n        int bestIdx = -1, bestVal = -1;\n        for (int i = 0; i < poolSize; i++) {\n            if (minDist[i] > bestVal) {\n                bestVal = minDist[i];\n                bestIdx = i;\n            }\n        }\n        chosen.push_back(bestIdx);\n        for (int i = 0; i < poolSize; i++) {\n            int d = distHam(poolFixedBits[i], poolFixedBits[bestIdx]);\n            if (d < minDist[i]) minDist[i] = d;\n        }\n        minDist[bestIdx] = -1;\n    }\n\n    vector<vector<uint64_t>> GAdj(M);\n    for (int k = 0; k < M; k++) GAdj[k] = poolAdj[chosen[k]];\n\n    // Precompute invariants + canonical bitstrings for each candidate\n    vector<Invariants> invs(M);\n    vector<vector<vector<uint64_t>>> canonBits(M, vector<vector<uint64_t>>(methods.size()));\n\n    for (int k = 0; k < M; k++) {\n        invs[k] = methods[0].computeInvariants(GAdj[k]);\n        for (int mi = 0; mi < (int)methods.size(); mi++) {\n            canonBits[k][mi] = methods[mi].canonicalBits(GAdj[k]);\n        }\n    }\n\n    // Output graphs\n    cout << N << \"\\n\";\n    for (int k = 0; k < M; k++) {\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                s.push_back(((GAdj[k][i] >> j) & 1ULL) ? '1' : '0');\n            }\n        }\n        cout << s << \"\\n\";\n    }\n    cout.flush();\n\n    // Weights (lightly tune with eps)\n    double f = min(1.0, eps / 0.4);\n    double wEdge = 0.02 * (1.0 + f);\n    double wTwo  = 0.0005 * (1.0 + f);\n    double wTri  = 0.005 * (1.0 + f);\n    double wDeg  = 0.003 * (1.0 + f);\n\n    for (int q = 0; q < 100; q++) {\n        string H;\n        cin >> H;\n\n        vector<uint64_t> adj(N, 0ULL);\n        int idx = 0;\n        for (int i = 0; i < N; i++) {\n            for (int j = i + 1; j < N; j++) {\n                if (H[idx++] == '1') {\n                    adj[i] |= (1ULL << j);\n                    adj[j] |= (1ULL << i);\n                }\n            }\n        }\n\n        Invariants invH = methods[0].computeInvariants(adj);\n\n        vector<vector<uint64_t>> canonH(methods.size());\n        for (int mi = 0; mi < (int)methods.size(); mi++) {\n            canonH[mi] = methods[mi].canonicalBits(adj);\n        }\n\n        int best = 0;\n        long long bestScore = (1LL << 62);\n\n        for (int k = 0; k < M; k++) {\n            // Ensemble: min Hamming distance across methods (robust to WL failures)\n            long long dHamMin = (1LL << 60);\n            for (int mi = 0; mi < (int)methods.size(); mi++) {\n                long long dHam = 0;\n                for (int w = 0; w < Wwords; w++) {\n                    dHam += popcnt_u64(canonBits[k][mi][w] ^ canonH[mi][w]);\n                }\n                dHamMin = min(dHamMin, dHam);\n            }\n\n            long long score = dHamMin;\n            score += (long long)llround(wEdge * (double)llabs((long long)invH.edges - invs[k].edges));\n            score += (long long)llround(wTwo  * (double)llabs(invH.twoStars - invs[k].twoStars));\n            score += (long long)llround(wTri  * (double)llabs(invH.triangles - invs[k].triangles));\n\n            long long dDeg = 0;\n            for (int i = 0; i < N; i++) dDeg += llabs((long long)invH.degSorted[i] - invs[k].degSorted[i]);\n            score += (long long)llround(wDeg * (double)dDeg);\n\n            if (score < bestScore) {\n                bestScore = score;\n                best = k;\n            }\n        }\n\n        cout << best << \"\\n\";\n        cout.flush();\n    }\n\n    return 0;\n}","ahc017":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct AdjEdge {\n    int to;\n    int eid;\n    int nxt;\n};\n\nstatic const long long INFLL = (1LL << 60);\nstatic const long long UNREACH = 1000000000LL;\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<long long> W(M);\n    vector<vector<AdjEdge>> g(N); // will reserve below\n\n    for (int i = 0; i < M; i++) {\n        int u, v;\n        long long w;\n        cin >> u >> v >> w;\n        --u; --v;\n        W[i] = w;\n        g[u].push_back({v, i, -1});\n        g[v].push_back({u, i, -1});\n    }\n\n    // coords unused\n    for (int i = 0; i < N; i++) {\n        int x, y;\n        cin >> x >> y;\n    }\n\n    mt19937_64 rng(1234567);\n\n    // -----------------------------\n    // Lightweight importance for initialization:\n    // few-source shortest-path tree subtree sizes (as in previous refinement)\n    // -----------------------------\n    int Qimp = min(8, N);\n    vector<int> sourcesImp;\n    sourcesImp.reserve(Qimp);\n    vector<int> anchors = {0, N/2, N-1};\n    for (int a : anchors) if ((int)sourcesImp.size() < Qimp) sourcesImp.push_back(a);\n    while ((int)sourcesImp.size() < Qimp) {\n        int s = (int)(rng() % N);\n        bool ok = true;\n        for (int t : sourcesImp) if (t == s) ok = false;\n        if (ok) sourcesImp.push_back(s);\n    }\n\n    vector<long long> dist(N);\n    vector<int> parent(N), parentEdge(N);\n    vector<vector<int>> children(N);\n    vector<int> order(N), subtree(N);\n\n    // parent chosen from all shortest predecessors (single parent for tree)\n    auto dijkstra_original = [&](int src, vector<long long>& d) {\n        fill(d.begin(), d.end(), INFLL);\n        priority_queue<pair<long long,int>, vector<pair<long long,int>>, greater<pair<long long,int>>> pq;\n        d[src] = 0;\n        pq.push({0, src});\n        while (!pq.empty()) {\n            auto [cd, v] = pq.top(); pq.pop();\n            if (cd != d[v]) continue;\n            for (auto &e : g[v]) {\n                int to = e.to, id = e.eid;\n                long long nd = cd + W[id];\n                if (nd < d[to]) {\n                    d[to] = nd;\n                    pq.push({nd, to});\n                }\n            }\n        }\n    };\n\n    vector<long long> edgeCount(M, 0);\n\n    for (int s : sourcesImp) {\n        dijkstra_original(s, dist);\n\n        for (int i = 0; i < N; i++) {\n            parent[i] = -1;\n            parentEdge[i] = -1;\n            children[i].clear();\n        }\n\n        parent[s] = s;\n        parentEdge[s] = -1;\n\n        for (int v = 0; v < N; v++) {\n            if (v == s) continue;\n            long long dv = dist[v];\n            long long bestDu = INFLL;\n            int bestE = -1, bestP = -1;\n\n            // scan predecessors by checking all neighbors u with dist[u]+w(u,v)=dist[v]\n            for (auto &e : g[v]) {\n                int u = e.to;\n                int eid = e.eid;\n                if (dist[u] == INFLL) continue;\n                if (dist[u] + W[eid] == dv) {\n                    if (dist[u] < bestDu || (dist[u] == bestDu && eid < bestE)) {\n                        bestDu = dist[u];\n                        bestE = eid;\n                        bestP = u;\n                    }\n                }\n            }\n            parent[v] = bestP;\n            parentEdge[v] = bestE;\n        }\n\n        iota(order.begin(), order.end(), 0);\n        sort(order.begin(), order.end(), [&](int a, int b){ return dist[a] > dist[b]; });\n\n        for (int v = 0; v < N; v++) if (v != s) children[parent[v]].push_back(v);\n\n        for (int v = 0; v < N; v++) subtree[v] = 1;\n        for (int v : order) {\n            int sum = 1;\n            for (int c : children[v]) sum += subtree[c];\n            subtree[v] = sum;\n        }\n\n        for (int v = 0; v < N; v++) {\n            if (v == s) continue;\n            int e = parentEdge[v];\n            if (e >= 0) edgeCount[e] += subtree[v];\n        }\n    }\n\n    vector<long double> impRaw(M);\n    long double mxRaw = 0;\n    for (int e = 0; e < M; e++) {\n        impRaw[e] = (long double)edgeCount[e] * (long double)W[e];\n        mxRaw = max(mxRaw, impRaw[e]);\n    }\n    if (mxRaw <= 0) mxRaw = 1;\n\n    vector<double> imp(M);\n    long double scale = mxRaw;\n    for (int e = 0; e < M; e++) {\n        // concave log transform\n        long double x = impRaw[e] / scale * 100.0L + 1.0L;\n        imp[e] = (double)log1pl(x);\n    }\n    double mxImp = 0;\n    for (double x : imp) mxImp = max(mxImp, x);\n    if (mxImp <= 0) mxImp = 1;\n    for (int e = 0; e < M; e++) imp[e] /= mxImp;\n\n    // -----------------------------\n    // Initial schedule: greedy balance by imp\n    // -----------------------------\n    vector<int> edgeOrder(M);\n    iota(edgeOrder.begin(), edgeOrder.end(), 0);\n    sort(edgeOrder.begin(), edgeOrder.end(), [&](int a, int b){\n        if (imp[a] != imp[b]) return imp[a] > imp[b];\n        return W[a] > W[b];\n    });\n\n    vector<int> dayOfEdge(M, -1), posInDay(M, -1);\n    vector<vector<int>> edgesByDay(D);\n    vector<vector<unsigned char>> removed(D, vector<unsigned char>(M, 0));\n    vector<int> cntDay(D, 0);\n    vector<long double> sumImpDay(D, 0.0L);\n\n    struct PQNode { long double s; int c; int d; int ver; };\n    struct PQCmp {\n        bool operator()(const PQNode& a, const PQNode& b) const {\n            if (a.s != b.s) return a.s > b.s;\n            if (a.c != b.c) return a.c > b.c;\n            return a.d > b.d;\n        }\n    };\n\n    priority_queue<PQNode, vector<PQNode>, PQCmp> pq;\n    vector<int> ver(D, 0);\n    for (int d = 0; d < D; d++) pq.push({0.0L, 0, d, ver[d]});\n\n    for (int e : edgeOrder) {\n        while (true) {\n            auto cur = pq.top(); pq.pop();\n            int d = cur.d;\n            if (cur.ver != ver[d]) continue;\n            if ((int)edgesByDay[d].size() >= K) continue;\n\n            dayOfEdge[e] = d;\n            posInDay[e] = (int)edgesByDay[d].size();\n            edgesByDay[d].push_back(e);\n            removed[d][e] = 1;\n            cntDay[d]++;\n            sumImpDay[d] += (long double)imp[e];\n\n            ver[d]++;\n            pq.push({sumImpDay[d], cntDay[d], d, ver[d]});\n            break;\n        }\n    }\n\n    // -----------------------------\n    // Dijkstra proxy local search\n    // -----------------------------\n    int Qfast = min(14, N);\n    vector<int> sourcesFast;\n    sourcesFast.reserve(Qfast);\n    {\n        unordered_set<int> used;\n        while ((int)sourcesFast.size() < Qfast) {\n            int s = (int)(rng() % N);\n            if (used.insert(s).second) sourcesFast.push_back(s);\n        }\n    }\n\n    auto dijkstra_original_src = [&](int src, vector<long long>& d) {\n        fill(d.begin(), d.end(), INFLL);\n        priority_queue<pair<long long,int>, vector<pair<long long,int>>, greater<pair<long long,int>>> pq;\n        d[src] = 0;\n        pq.push({0, src});\n        while (!pq.empty()) {\n            auto [cd, v] = pq.top(); pq.pop();\n            if (cd != d[v]) continue;\n            for (auto &e : g[v]) {\n                int to = e.to, id = e.eid;\n                long long nd = cd + W[id];\n                if (nd < d[to]) {\n                    d[to] = nd;\n                    pq.push({nd, to});\n                }\n            }\n        }\n    };\n\n    vector<vector<long long>> baseDist(Qfast, vector<long long>(N, INFLL));\n    for (int i = 0; i < Qfast; i++) dijkstra_original_src(sourcesFast[i], baseDist[i]);\n\n    auto dijkstra_day = [&](int day, int src, vector<long long>& d) {\n        fill(d.begin(), d.end(), INFLL);\n        priority_queue<pair<long long,int>, vector<pair<long long,int>>, greater<pair<long long,int>>> pq;\n        d[src] = 0;\n        pq.push({0, src});\n        while (!pq.empty()) {\n            auto [cd, v] = pq.top(); pq.pop();\n            if (cd != d[v]) continue;\n            for (auto &e : g[v]) {\n                int to = e.to, id = e.eid;\n                if (removed[day][id]) continue; // repaired on this day => removed\n                long long nd = cd + W[id];\n                if (nd < d[to]) {\n                    d[to] = nd;\n                    pq.push({nd, to});\n                }\n            }\n        }\n    };\n\n    vector<long long> distWork(N);\n    auto computeProxyDay = [&](int day) -> long double {\n        long double sum = 0.0L;\n        for (int si = 0; si < Qfast; si++) {\n            int s = sourcesFast[si];\n            dijkstra_day(day, s, distWork);\n            for (int v = 0; v < N; v++) {\n                if (v == s) continue;\n                long long dk = (distWork[v] == INFLL ? UNREACH : distWork[v]);\n                long long d0 = baseDist[si][v];\n                // dk >= d0 in this monotone edge removal scenario, so nonnegative\n                sum += (long double)(dk - d0);\n            }\n        }\n        return sum;\n    };\n\n    vector<long double> proxyDay(D, 0.0L);\n    long double totalProxy = 0.0L;\n    for (int day = 0; day < D; day++) {\n        proxyDay[day] = computeProxyDay(day);\n        totalProxy += proxyDay[day];\n    }\n\n    auto swapEdges = [&](int eA, int eB) {\n        if (eA == eB) return;\n        int d1 = dayOfEdge[eA], d2 = dayOfEdge[eB];\n        if (d1 == d2) return;\n\n        int p1 = posInDay[eA];\n        int p2 = posInDay[eB];\n\n        // swap edge IDs inside day vectors\n        edgesByDay[d1][p1] = eB;\n        edgesByDay[d2][p2] = eA;\n\n        posInDay[eB] = p1;\n        posInDay[eA] = p2;\n\n        dayOfEdge[eA] = d2;\n        dayOfEdge[eB] = d1;\n\n        // update removed flags for each day\n        removed[d1][eA] = 0;\n        removed[d2][eB] = 0;\n        removed[d1][eB] = 1;\n        removed[d2][eA] = 1;\n    };\n\n    auto elapsedSec = [&](){\n        static auto start = chrono::steady_clock::now();\n        return chrono::duration<double>(chrono::steady_clock::now() - start).count();\n    };\n\n    double TIME_LIMIT = 5.85; // conservative\n    int iter = 0;\n\n    auto pickCandidatesHigh = [&](int d, int take) {\n        // sample some edges from day d, return the top-by-imp 'take' edges\n        auto &vec = edgesByDay[d];\n        int sz = (int)vec.size();\n        int samples = min(sz, 18);\n        vector<int> cand;\n        cand.reserve(samples);\n        for (int t = 0; t < samples; t++) {\n            int id = (int)(rng() % sz);\n            cand.push_back(vec[id]);\n        }\n        sort(cand.begin(), cand.end(), [&](int a, int b){ return imp[a] > imp[b]; });\n        cand.erase(unique(cand.begin(), cand.end()), cand.end());\n        if ((int)cand.size() > take) cand.resize(take);\n        while ((int)cand.size() < take && sz > 0) {\n            int id = (int)(rng() % sz);\n            cand.push_back(vec[id]);\n            sort(cand.begin(), cand.end(), [&](int a, int b){ return imp[a] > imp[b]; });\n            cand.erase(unique(cand.begin(), cand.end()), cand.end());\n            if ((int)cand.size() > take) cand.resize(take);\n        }\n        return cand;\n    };\n\n    auto pickCandidatesLow = [&](int d, int take) {\n        auto &vec = edgesByDay[d];\n        int sz = (int)vec.size();\n        int samples = min(sz, 18);\n        vector<int> cand;\n        cand.reserve(samples);\n        for (int t = 0; t < samples; t++) {\n            int id = (int)(rng() % sz);\n            cand.push_back(vec[id]);\n        }\n        sort(cand.begin(), cand.end(), [&](int a, int b){ return imp[a] < imp[b]; });\n        cand.erase(unique(cand.begin(), cand.end()), cand.end());\n        if ((int)cand.size() > take) cand.resize(take);\n        while ((int)cand.size() < take && sz > 0) {\n            int id = (int)(rng() % sz);\n            cand.push_back(vec[id]);\n            sort(cand.begin(), cand.end(), [&](int a, int b){ return imp[a] < imp[b]; });\n            cand.erase(unique(cand.begin(), cand.end()), cand.end());\n            if ((int)cand.size() > take) cand.resize(take);\n        }\n        return cand;\n    };\n\n    while (true) {\n        if (elapsedSec() > TIME_LIMIT) break;\n        iter++;\n\n        // sort days by proxy\n        vector<int> days(D);\n        iota(days.begin(), days.end(), 0);\n        sort(days.begin(), days.end(), [&](int a, int b){ return proxyDay[a] > proxyDay[b]; });\n\n        int topCount = min(3, D);\n        int botCount = min(3, D);\n        int dHigh = days[(int)(rng() % topCount)];                // among worst\n        int dLow = days[D-1 - (int)(rng() % botCount)];          // among best\n        if (dHigh == dLow) continue;\n\n        // candidate edges on those days\n        auto candHigh = pickCandidatesHigh(dHigh, 3); // largest imp\n        auto candLow  = pickCandidatesLow(dLow, 3);  // smallest imp\n\n        // generate candidate pairs, prioritize by predicted improvement in proxy (imp difference heuristic)\n        struct PairCand { int eA, eB; double score; };\n        vector<PairCand> pairs;\n        for (int eA : candHigh) for (int eB : candLow) {\n            if (eA == eB) continue;\n            if (dayOfEdge[eA] != dHigh || dayOfEdge[eB] != dLow) continue;\n            double sc = imp[eA] - imp[eB];\n            pairs.push_back({eA, eB, sc});\n        }\n        if (pairs.empty()) continue;\n        sort(pairs.begin(), pairs.end(), [&](const PairCand& a, const PairCand& b){\n            return a.score > b.score;\n        });\n\n        // evaluate a few best pairs exactly by proxy\n        long double bestNewTotal = totalProxy;\n        int bestEA = -1, bestEB = -1;\n        long double bestNewHigh = 0, bestNewLow = 0;\n\n        int evalLimit = min(6, (int)pairs.size());\n        for (int pi = 0; pi < evalLimit; pi++) {\n            int eA = pairs[pi].eA;\n            int eB = pairs[pi].eB;\n\n            swapEdges(eA, eB);\n\n            long double newHigh = computeProxyDay(dHigh); // day indices unchanged\n            long double newLow  = computeProxyDay(dLow);\n            long double newTotal = totalProxy - proxyDay[dHigh] - proxyDay[dLow] + newHigh + newLow;\n\n            swapEdges(eA, eB); // revert to original\n\n            if (newTotal < bestNewTotal) {\n                bestNewTotal = newTotal;\n                bestEA = eA; bestEB = eB;\n                bestNewHigh = newHigh;\n                bestNewLow = newLow;\n            }\n        }\n\n        // apply best improving swap\n        if (bestEA != -1) {\n            swapEdges(bestEA, bestEB);\n            proxyDay[dHigh] = bestNewHigh;\n            proxyDay[dLow] = bestNewLow;\n            totalProxy = bestNewTotal;\n        }\n    }\n\n    // Output schedule\n    for (int e = 0; e < M; e++) {\n        cout << (dayOfEdge[e] + 1) << (e + 1 == M ? '\\n' : ' ');\n    }\n    return 0;\n}","ahc019":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic inline int idx3(int D, int x, int y, int z){\n    return x*D*D + y*D + z; // z fastest\n}\n\nstruct Coord { int x,y,z; };\n\nstruct HopcroftKarp {\n    int nL, nR;\n    vector<vector<int>> adj; // adj[u] -> v\n    vector<int> dist, matchL, matchR;\n\n    HopcroftKarp(int nL_=0, int nR_=0): nL(nL_), nR(nR_) {\n        adj.assign(nL, {});\n        dist.assign(nL, 0);\n        matchL.assign(nL, -1);\n        matchR.assign(nR, -1);\n    }\n    void add_edge(int u, int v){\n        adj[u].push_back(v);\n    }\n    bool bfs(){\n        deque<int> q;\n        for(int i=0;i<nL;i++){\n            if(matchL[i] == -1){\n                dist[i] = 0;\n                q.push_back(i);\n            }else dist[i] = -1;\n        }\n        bool reachFree = false;\n        while(!q.empty()){\n            int v = q.front(); q.pop_front();\n            for(int to: adj[v]){\n                int u = matchR[to];\n                if(u == -1){\n                    reachFree = true;\n                }else if(dist[u] == -1){\n                    dist[u] = dist[v] + 1;\n                    q.push_back(u);\n                }\n            }\n        }\n        return reachFree;\n    }\n    bool dfs(int v){\n        for(int to: adj[v]){\n            int u = matchR[to];\n            if(u == -1 || (dist[u] == dist[v] + 1 && dfs(u))){\n                matchL[v] = to;\n                matchR[to] = v;\n                return true;\n            }\n        }\n        dist[v] = -1;\n        return false;\n    }\n    int max_matching(){\n        int flow = 0;\n        while(bfs()){\n            for(int i=0;i<nL;i++){\n                if(matchL[i] == -1){\n                    if(dfs(i)) flow++;\n                }\n            }\n        }\n        return flow;\n    }\n};\n\nusing Block = vector<int>;\nusing Blocks = vector<Block>;\n\nstatic Blocks packClassBoxes(\n    const vector<unsigned char>& exist,\n    int D,\n    vector<unsigned char>& used,\n    const vector<array<int,3>>& oris, // (dx,dy,dz) permutations\n    int need\n){\n    // Greedy deterministic scan: for each orientation, scan all origins in increasing order.\n    Blocks res;\n    if(need <= 0) return res;\n\n    int N = D*D*D;\n    (void)N;\n\n    for(auto od : oris){\n        int dx = od[0], dy = od[1], dz = od[2];\n        for(int x=0; x+dx<=D && (int)res.size()<need; x++){\n            for(int y=0; y+dy<=D && (int)res.size()<need; y++){\n                for(int z=0; z+dz<=D && (int)res.size()<need; z++){\n                    if((int)res.size() >= need) break;\n\n                    // Check fit\n                    bool ok = true;\n                    Block cubes;\n                    cubes.reserve(dx*dy*dz);\n                    for(int xx=0; xx<dx && ok; xx++){\n                        for(int yy=0; yy<dy && ok; yy++){\n                            for(int zz=0; zz<dz && ok; zz++){\n                                int gx = x+xx, gy=y+yy, gz=z+zz;\n                                int id = idx3(D, gx,gy,gz);\n                                if(!exist[id] || used[id]){\n                                    ok = false;\n                                }else{\n                                    cubes.push_back(id);\n                                }\n                            }\n                        }\n                    }\n                    if(!ok) continue;\n\n                    // Place\n                    for(int id: cubes) used[id] = 1;\n                    res.push_back(std::move(cubes));\n                }\n            }\n        }\n    }\n    return res;\n}\n\nstatic Blocks pack2x2x2(\n    const vector<unsigned char>& exist, int D,\n    vector<unsigned char>& used, int need\n){\n    Blocks res;\n    if(need <= 0) return res;\n    for(int x=0; x+2<=D && (int)res.size()<need; x++){\n        for(int y=0; y+2<=D && (int)res.size()<need; y++){\n            for(int z=0; z+2<=D && (int)res.size()<need; z++){\n                int ids[8];\n                bool ok = true;\n                int t=0;\n                for(int xx=0; xx<2; xx++){\n                    for(int yy=0; yy<2; yy++){\n                        for(int zz=0; zz<2; zz++){\n                            int gx=x+xx, gy=y+yy, gz=z+zz;\n                            int id = idx3(D,gx,gy,gz);\n                            ids[t++] = id;\n                            if(!exist[id] || used[id]) ok = false;\n                        }\n                    }\n                }\n                if(!ok) continue;\n                Block b;\n                b.reserve(8);\n                for(int i=0;i<8;i++){\n                    used[ids[i]] = 1;\n                    b.push_back(ids[i]);\n                }\n                res.push_back(std::move(b));\n            }\n        }\n    }\n    return res;\n}\n\nstatic vector<pair<int,int>> maxDominoPairs(\n    const vector<unsigned char>& exist,\n    int D,\n    const vector<int>& remCubes,\n    const vector<int>& parity,\n    const vector<array<int,6>>& neigh\n){\n    int m = (int)remCubes.size();\n    vector<int> posToLocal(D*D*D, -1);\n    for(int i=0;i<m;i++) posToLocal[remCubes[i]] = i;\n\n    vector<int> leftLocal, rightLocal;\n    leftLocal.reserve(m);\n    rightLocal.reserve(m);\n    vector<int> localToRight(m, -1);\n\n    for(int i=0;i<m;i++){\n        int g = remCubes[i];\n        if(parity[g]==0){\n            leftLocal.push_back(i);\n        }else{\n            localToRight[i] = (int)rightLocal.size();\n            rightLocal.push_back(i);\n        }\n    }\n\n    int nL = (int)leftLocal.size();\n    int nR = (int)rightLocal.size();\n    HopcroftKarp hk(nL, nR);\n\n    for(int li=0; li<nL; li++){\n        int lLocal = leftLocal[li];\n        int g = remCubes[lLocal];\n        for(int dir=0; dir<6; dir++){\n            int ng = neigh[g][dir];\n            if(ng < 0) continue;\n            int vLocal = posToLocal[ng];\n            if(vLocal < 0) continue;\n            int rv = localToRight[vLocal];\n            if(rv >= 0){\n                hk.add_edge(li, rv);\n            }\n        }\n    }\n\n    hk.max_matching();\n\n    vector<pair<int,int>> pairs;\n    for(int li=0; li<nL; li++){\n        int rmatch = hk.matchL[li];\n        if(rmatch != -1){\n            int lLocal = leftLocal[li];\n            int rLocal = rightLocal[rmatch];\n            pairs.push_back({ remCubes[lLocal], remCubes[rLocal] });\n        }\n    }\n    return pairs;\n}\n\nint main(){\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int D;\n    cin >> D;\n\n    vector<vector<string>> f(2, vector<string>(D));\n    vector<vector<string>> r(2, vector<string>(D));\n\n    for(int i=0;i<2;i++){\n        for(int z=0; z<D; z++){\n            cin >> f[i][z];\n        }\n        for(int z=0; z<D; z++){\n            cin >> r[i][z];\n        }\n    }\n\n    int N = D*D*D;\n\n    // Precompute parity and neighbor ids\n    vector<int> parity(N, 0);\n    vector<array<int,6>> neigh(N);\n    for(int x=0;x<D;x++){\n        for(int y=0;y<D;y++){\n            for(int z=0;z<D;z++){\n                int id = idx3(D,x,y,z);\n                parity[id] = (x+y+z)&1;\n                array<int,6> nb;\n                nb.fill(-1);\n                // +x,-x,+y,-y,+z,-z\n                if(x+1<D) nb[0] = idx3(D,x+1,y,z);\n                if(x-1>=0) nb[1] = idx3(D,x-1,y,z);\n                if(y+1<D) nb[2] = idx3(D,x,y+1,z);\n                if(y-1>=0) nb[3] = idx3(D,x,y-1,z);\n                if(z+1<D) nb[4] = idx3(D,x,y,z+1);\n                if(z-1>=0) nb[5] = idx3(D,x,y,z-1);\n                neigh[id] = nb;\n            }\n        }\n    }\n\n    auto buildExist = [&](int i)->vector<unsigned char>{\n        vector<unsigned char> exist(N, 0);\n        for(int x=0;x<D;x++){\n            for(int y=0;y<D;y++){\n                for(int z=0;z<D;z++){\n                    if(f[i][z][x] == '1' && r[i][z][y] == '1'){\n                        exist[idx3(D,x,y,z)] = 1;\n                    }\n                }\n            }\n        }\n        return exist;\n    };\n\n    vector<unsigned char> exist[2];\n    exist[0] = buildExist(0);\n    exist[1] = buildExist(1);\n\n    // 1) Compute max number of 2x2x2 boxes (deterministic greedy)\n    int max8[2] = {0,0};\n    for(int i=0;i<2;i++){\n        vector<unsigned char> used(N, 0);\n        auto b8 = pack2x2x2(exist[i], D, used, INT_MAX/4);\n        max8[i] = (int)b8.size();\n    }\n    int keep8 = min(max8[0], max8[1]);\n\n    // 2) For each object: place exact keep8, then compute max 2x2x1 count\n    vector<Blocks> b8_exact(2), b4_max(2);\n    vector<int> max4(2,0);\n    for(int i=0;i<2;i++){\n        vector<unsigned char> used(N,0);\n        b8_exact[i] = pack2x2x2(exist[i], D, used, keep8);\n\n        vector<array<int,3>> oris4 = {\n            array<int,3>{2,2,1},\n            array<int,3>{2,1,2},\n            array<int,3>{1,2,2}\n        };\n        // max packing of 2x2x1 on remaining\n        b4_max[i] = packClassBoxes(exist[i], D, used, oris4, INT_MAX/4);\n        max4[i] = (int)b4_max[i].size();\n    }\n    int keep4 = min(max4[0], max4[1]);\n\n    // 3) Place exact keep8 and keep4, then compute max 1x1x3 count\n    vector<Blocks> b4_exact(2), b3_max(2);\n    vector<int> max3(2,0);\n    for(int i=0;i<2;i++){\n        vector<unsigned char> used(N,0);\n        b8_exact[i] = pack2x2x2(exist[i], D, used, keep8);\n        vector<array<int,3>> oris4 = {\n            array<int,3>{2,2,1},\n            array<int,3>{2,1,2},\n            array<int,3>{1,2,2}\n        };\n        b4_exact[i] = packClassBoxes(exist[i], D, used, oris4, keep4);\n\n        vector<array<int,3>> oris3 = {\n            array<int,3>{1,1,3},\n            array<int,3>{1,3,1},\n            array<int,3>{3,1,1}\n        };\n        b3_max[i] = packClassBoxes(exist[i], D, used, oris3, INT_MAX/4);\n        max3[i] = (int)b3_max[i].size();\n    }\n    int keep3 = min(max3[0], max3[1]);\n\n    // 4) Final placement: exact keep8/keep4/keep3, compute remaining cubes for domino matching\n    vector<Blocks> b3_exact(2);\n    vector<vector<int>> remCubes(2);\n    for(int i=0;i<2;i++){\n        vector<unsigned char> used(N,0);\n        b8_exact[i] = pack2x2x2(exist[i], D, used, keep8);\n\n        vector<array<int,3>> oris4 = {\n            array<int,3>{2,2,1},\n            array<int,3>{2,1,2},\n            array<int,3>{1,2,2}\n        };\n        b4_exact[i] = packClassBoxes(exist[i], D, used, oris4, keep4);\n\n        vector<array<int,3>> oris3 = {\n            array<int,3>{1,1,3},\n            array<int,3>{1,3,1},\n            array<int,3>{3,1,1}\n        };\n        b3_exact[i] = packClassBoxes(exist[i], D, used, oris3, keep3);\n\n        remCubes[i].clear();\n        remCubes[i].reserve(N);\n        for(int id=0; id<N; id++){\n            if(exist[i][id] && !used[id]) remCubes[i].push_back(id);\n        }\n    }\n\n    // 5) Domino matching on remaining\n    vector<pair<int,int>> matchPairs[2];\n    for(int i=0;i<2;i++){\n        matchPairs[i] = maxDominoPairs(exist[i], D, remCubes[i], parity, neigh);\n    }\n    int keepDom = min((int)matchPairs[0].size(), (int)matchPairs[1].size());\n\n    // 6) Build unit cubes after selecting first keepDom dominoes\n    vector<vector<int>> units(2);\n    for(int i=0;i<2;i++){\n        vector<unsigned char> usedRem(N,0);\n        for(int t=0;t<keepDom;t++){\n            usedRem[ matchPairs[i][t].first ] = 1;\n            usedRem[ matchPairs[i][t].second ] = 1;\n        }\n        units[i].clear();\n        units[i].reserve(remCubes[i].size());\n        for(int g : remCubes[i]){\n            if(!usedRem[g]) units[i].push_back(g);\n        }\n    }\n\n    int u0 = (int)units[0].size();\n    int u1 = (int)units[1].size();\n\n    int X = keep8 + keep4 + keep3 + keepDom; // number of blocks before units\n    int unitBase = X + 1; // first unit id\n    int nBlocks = X + max(u0, u1);\n\n    vector<int> b0(N, 0), b1(N, 0);\n\n    auto assignBlocks = [&](int objIdx, vector<int>& b, \n                             const Blocks& B8, const Blocks& B4, const Blocks& B3,\n                             const vector<pair<int,int>>& domPairs,\n                             const vector<vector<int>>& unitsAll,\n                             const int keepDomLocal,\n                             int keep8, int keep4, int keep3,\n                             int unitBase,\n                             int maxUnits\n    ){\n        (void)objIdx; (void)maxUnits;\n\n        for(int k=0;k<(int)B8.size();k++){\n            int id = 1 + k;\n            for(int cube : B8[k]) b[cube] = id;\n        }\n        for(int k=0;k<(int)B4.size();k++){\n            int id = keep8 + 1 + k;\n            for(int cube : B4[k]) b[cube] = id;\n        }\n        for(int k=0;k<(int)B3.size();k++){\n            int id = keep8 + keep4 + 1 + k;\n            for(int cube : B3[k]) b[cube] = id;\n        }\n\n        int domStart = keep8 + keep4 + keep3 + 1;\n        for(int t=0;t<keepDomLocal;t++){\n            int id = domStart + t;\n            auto [a,bx] = domPairs[t];\n            b[a] = id;\n            b[bx] = id;\n        }\n\n        for(int t=0;t<(int)unitsAll[objIdx].size();t++){\n            int id = unitBase + t;\n            b[ unitsAll[objIdx][t] ] = id;\n        }\n    };\n\n    assignBlocks(0, b0, b8_exact[0], b4_exact[0], b3_exact[0], matchPairs[0],\n                  units, keepDom, keep8, keep4, keep3, unitBase, max(u0,u1));\n    assignBlocks(1, b1, b8_exact[1], b4_exact[1], b3_exact[1], matchPairs[1],\n                  units, keepDom, keep8, keep4, keep3, unitBase, max(u0,u1));\n\n    cout << nBlocks << \"\\n\";\n\n    auto printB = [&](const vector<int>& b){\n        bool first = true;\n        for(int x=0;x<D;x++){\n            for(int y=0;y<D;y++){\n                for(int z=0;z<D;z++){\n                    int v = b[idx3(D,x,y,z)];\n                    if(!first) cout << ' ';\n                    first = false;\n                    cout << v;\n                }\n            }\n        }\n        cout << \"\\n\";\n    };\n\n    printB(b0);\n    printB(b1);\n    return 0;\n}","ahc020":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\n\nstatic int ceil_sqrt_ll(long long x) {\n    // returns smallest r s.t. r*r >= x, for x>=0\n    if (x <= 0) return 0;\n    long long r = (long long) sqrt((long double)x);\n    while (r * r < x) ++r;\n    while ((r - 1) * (r - 1) >= x) --r;\n    return (int)r;\n}\n\nstruct Fenwick {\n    int n = 0;\n    vector<int> bit;\n    int bitMask = 1;\n\n    void init(int n_) {\n        if ((int)bit.size() != n_ + 1) bit.assign(n_ + 1, 0);\n        else fill(bit.begin(), bit.end(), 0);\n        n = n_;\n        bitMask = 1;\n        while (bitMask < n) bitMask <<= 1;\n    }\n\n    void add(int idx, int delta) { // idx: 1..n\n        for (; idx <= n; idx += idx & -idx) bit[idx] += delta;\n    }\n\n    int kth(int k) const {\n        // smallest idx such that prefix sum >= k, assuming 1<=k<=total\n        int idx = 0;\n        for (int d = bitMask; d > 0; d >>= 1) {\n            int next = idx + d;\n            if (next <= n && bit[next] < k) {\n                idx = next;\n                k -= bit[next];\n            }\n        }\n        return idx + 1;\n    }\n\n    int getMax(int total) const {\n        if (total == 0) return 0;\n        int pos = kth(total); // fenwick index\n        return pos - 1; // radius = (r+1)-1\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, K;\n    cin >> N >> M >> K;\n    vector<ll> x(N), y(N);\n    for (int i = 0; i < N; i++) cin >> x[i] >> y[i];\n\n    vector<int> U(M), V(M);\n    vector<ll> W(M);\n    vector<vector<tuple<int,ll,int>>> adj(N);\n    for (int j = 0; j < M; j++) {\n        cin >> U[j] >> V[j] >> W[j];\n        --U[j]; --V[j];\n        adj[U[j]].push_back({V[j], W[j], j});\n        adj[V[j]].push_back({U[j], W[j], j});\n    }\n\n    vector<ll> ax(K), ay(K);\n    for (int k = 0; k < K; k++) cin >> ax[k] >> ay[k];\n\n    const int LIM = 5000;\n    const int INF_R = LIM + 1;\n\n    // r[station][resident] = ceil(sqrt(dist^2)) or INF_R if >5000\n    vector<vector<uint16_t>> r(N, vector<uint16_t>(K, INF_R));\n    const long long LIM2 = 1LL * LIM * LIM;\n    for (int i = 0; i < N; i++) {\n        for (int k = 0; k < K; k++) {\n            ll dx = x[i] - ax[k];\n            ll dy = y[i] - ay[k];\n            ll dist2 = dx*dx + dy*dy;\n            if (dist2 > LIM2) continue;\n            int rr = ceil_sqrt_ll(dist2);\n            if (rr > LIM) continue;\n            r[i][k] = (uint16_t)rr;\n        }\n    }\n\n    // Build a shortest-path tree from root 0 by cable weights w_j.\n    // (Tie-break deterministic; could be randomized but kept stable for simplicity.)\n    const ll INF = (1LL<<62);\n    vector<ll> dist(N, INF);\n    vector<int> parent(N, -1), parentEdgeId(N, -1);\n    vector<ll> bestEdgeW(N, INF);\n\n    dist[0] = 0;\n    parent[0] = -1;\n    bestEdgeW[0] = 0;\n    using PII = pair<ll,int>;\n    priority_queue<PII, vector<PII>, greater<PII>> pq;\n    pq.push({0, 0});\n\n    while (!pq.empty()) {\n        auto [d, u] = pq.top(); pq.pop();\n        if (d != dist[u]) continue;\n        for (auto [v, ww, id] : adj[u]) {\n            ll nd = d + ww;\n            if (nd < dist[v]) {\n                dist[v] = nd;\n                parent[v] = u;\n                parentEdgeId[v] = id;\n                bestEdgeW[v] = ww;\n                pq.push({nd, v});\n            } else if (nd == dist[v]) {\n                if (ww < bestEdgeW[v] || (ww == bestEdgeW[v] && u < parent[v])) {\n                    parent[v] = u;\n                    parentEdgeId[v] = id;\n                    bestEdgeW[v] = ww;\n                    pq.push({nd, v});\n                }\n            }\n        }\n    }\n\n    vector<ll> weightToParent(N, 0);\n    for (int v = 1; v < N; v++) weightToParent[v] = W[parentEdgeId[v]];\n\n    // Precompute rooted-tree children and ancestor chains (excluding root).\n    vector<vector<int>> children(N);\n    for (int v = 1; v < N; v++) children[parent[v]].push_back(v);\n\n    vector<vector<int>> anc(N); // anc[v] = nodes on path v->root excluding root, including v\n    vector<int> depthCnt(N, 0);\n    for (int v = 1; v < N; v++) {\n        int cur = v;\n        while (cur != 0) {\n            anc[v].push_back(cur);\n            cur = parent[cur];\n        }\n        depthCnt[v] = (int)anc[v].size();\n        // root depthCnt=0\n    }\n\n    // Candidate sets per resident:\n    // take near-by-radius + shallow-by-depth for diversity\n    const int L = 20;\n    const int Lnear = 14;\n    const int Lshallow = 6;\n\n    vector<vector<int>> cand(K);\n    for (int k = 0; k < K; k++) {\n        vector<pair<int,int>> tmp; // (r, station)\n        tmp.reserve(N);\n        for (int i = 0; i < N; i++) {\n            int need = r[i][k];\n            if (need <= LIM) tmp.push_back({need, i});\n        }\n\n        // near\n        sort(tmp.begin(), tmp.end());\n        vector<int> nearSet;\n        for (int t = 0; t < (int)tmp.size() && (int)nearSet.size() < Lnear; t++)\n            nearSet.push_back(tmp[t].second);\n\n        // shallow\n        vector<pair<int,int>> tmp2;\n        tmp2.reserve(tmp.size());\n        for (auto &pr : tmp) {\n            int i = pr.second;\n            tmp2.push_back({depthCnt[i], i});\n        }\n        sort(tmp2.begin(), tmp2.end());\n        vector<int> shallowSet;\n        for (int t = 0; t < (int)tmp2.size() && (int)shallowSet.size() < Lshallow; t++)\n            shallowSet.push_back(tmp2[t].second);\n\n        // union\n        vector<int> res;\n        res.reserve(L);\n        vector<char> used(N, 0);\n        auto addv = [&](int s) {\n            if (!used[s]) {\n                used[s] = 1;\n                res.push_back(s);\n            }\n        };\n        for (int s : nearSet) addv(s);\n        for (int s : shallowSet) addv(s);\n\n        // if too small, fill with next-nearest\n        if ((int)res.size() < L) {\n            for (auto &pr : tmp) {\n                addv(pr.second);\n                if ((int)res.size() >= L) break;\n            }\n        }\n        cand[k] = std::move(res);\n        // Statement guarantees at least one station within 5000, so cand[k] non-empty.\n    }\n\n    // Greedy clustered initialization for one order permutation.\n    auto buildGreedyAssign = [&](mt19937_64 &rng) -> vector<int> {\n        vector<int> assign(K, -1);\n\n        vector<int> sz(N, 0);             // active station count (for initialization)\n        vector<int> curMax(N, 0);        // current max radius assigned to station\n        vector<int> subtreeCnt(N, 0);   // active stations count in subtree for initialization\n\n        vector<int> order(K);\n        iota(order.begin(), order.end(), 0);\n        shuffle(order.begin(), order.end(), rng);\n\n        for (int k : order) {\n            ll bestDelta = (1LL<<62);\n            vector<int> bestStations;\n\n            for (int to : cand[k]) {\n                int need = (int)r[to][k]; // <= 5000\n                int oldMax = curMax[to];\n                int newMax = max(oldMax, need);\n                ll deltaP = 1LL * newMax * newMax - 1LL * oldMax * oldMax;\n\n                ll deltaEdge = 0;\n                if (sz[to] == 0) {\n                    // station becomes active: add edges along anc[to] where subtreeCnt becomes 1\n                    for (int u : anc[to]) {\n                        if (subtreeCnt[u] == 0) deltaEdge += weightToParent[u];\n                    }\n                }\n                ll delta = deltaP + deltaEdge;\n\n                if (delta < bestDelta) {\n                    bestDelta = delta;\n                    bestStations.clear();\n                    bestStations.push_back(to);\n                } else if (delta == bestDelta) {\n                    bestStations.push_back(to);\n                }\n            }\n\n            int chosen = bestStations[rng() % bestStations.size()];\n            assign[k] = chosen;\n\n            int need = (int)r[chosen][k];\n            bool wasInactive = (sz[chosen] == 0);\n            sz[chosen]++;\n            curMax[chosen] = max(curMax[chosen], need);\n\n            if (wasInactive) {\n                // activate station => increment subtreeCnt along anc[chosen]\n                for (int u : anc[chosen]) subtreeCnt[u] += 1;\n            }\n        }\n        return assign;\n    };\n\n    // Local improvement given an initial assignment, using exact objective within this SPT-union model.\n    auto solveTrial = [&](const vector<int> &assignInit, int timeLimitMs) -> pair<ll, vector<int>> {\n        auto tStart = chrono::steady_clock::now();\n        auto timeUp = [&]() {\n            auto now = chrono::steady_clock::now();\n            return chrono::duration_cast<chrono::milliseconds>(now - tStart).count() > timeLimitMs;\n        };\n\n        vector<int> assign = assignInit;\n\n        // Fenwicks per station for max radius\n        vector<Fenwick> fenw(N);\n        for (int i = 0; i < N; i++) fenw[i].init(LIM + 1);\n\n        vector<int> sz(N, 0);\n        vector<int> P(N, 0);\n\n        for (int k = 0; k < K; k++) {\n            int i = assign[k];\n            int need = (int)r[i][k];\n            fenw[i].add(need + 1, +1);\n            sz[i]++;\n        }\n\n        ll Pcost = 0;\n        for (int i = 0; i < N; i++) {\n            if (sz[i] > 0) P[i] = fenw[i].getMax(sz[i]);\n            else P[i] = 0;\n            Pcost += 1LL * P[i] * P[i];\n        }\n\n        // subtreeCnt by active stations\n        vector<int> subtreeCnt(N, 0);\n        function<int(int)> dfs = [&](int v) -> int {\n            int cnt = (sz[v] > 0) ? 1 : 0;\n            for (int to : children[v]) cnt += dfs(to);\n            subtreeCnt[v] = cnt;\n            return cnt;\n        };\n        dfs(0);\n\n        ll edgeCost = 0;\n        for (int v = 1; v < N; v++) {\n            if (subtreeCnt[v] > 0) edgeCost += weightToParent[v];\n        }\n\n        ll totalCost = Pcost + edgeCost;\n\n        // Temp arrays for deltaEdge when both toggles happen\n        vector<int> mark(N, 0);\n        vector<int> change(N, 0);\n        int stamp = 1;\n\n        auto deltaEdge = [&](int from, int to, bool fromInactive, bool toActive) -> ll {\n            if (!fromInactive && !toActive) return 0LL;\n            ll dE = 0;\n\n            if (fromInactive && !toActive) {\n                for (int u : anc[from]) {\n                    // subtreeCnt[u] decreases by 1; edge toggles off iff it was 1\n                    if (subtreeCnt[u] == 1) dE -= weightToParent[u];\n                }\n                return dE;\n            }\n            if (!fromInactive && toActive) {\n                for (int u : anc[to]) {\n                    // subtreeCnt[u] increases by 1; edge toggles on iff it was 0\n                    if (subtreeCnt[u] == 0) dE += weightToParent[u];\n                }\n                return dE;\n            }\n\n            // both inactive->inactive? actually fromInactive means from becomes empty; toActive means to becomes non-empty\n            // handle overlap exactly\n            int curStamp = stamp++;\n            for (int u : anc[from]) {\n                if (mark[u] != curStamp) {\n                    mark[u] = curStamp;\n                    change[u] = -1;\n                } else change[u] -= 1;\n            }\n            for (int u : anc[to]) {\n                if (mark[u] != curStamp) {\n                    mark[u] = curStamp;\n                    change[u] = +1;\n                } else change[u] += 1;\n            }\n\n            // iterate marked nodes by scanning anc[from] and anc[to] chains (N<=100, ok)\n            // We\u2019ll gather unique nodes quickly.\n            int tmpList[200];\n            int tcnt = 0;\n            auto addUniq = [&](int u) {\n                if (mark[u] == curStamp) {\n                    // check uniq by linear scan (small)\n                    for (int i = 0; i < tcnt; i++) if (tmpList[i] == u) return;\n                    tmpList[tcnt++] = u;\n                }\n            };\n            for (int u : anc[from]) addUniq(u);\n            for (int u : anc[to]) addUniq(u);\n\n            for (int i = 0; i < tcnt; i++) {\n                int u = tmpList[i];\n                int before = subtreeCnt[u];\n                int after = before + change[u];\n                bool b1 = before > 0;\n                bool b2 = after > 0;\n                if (b1 != b2) {\n                    dE += (b2 ? +weightToParent[u] : -weightToParent[u]);\n                }\n            }\n            return dE;\n        };\n\n        auto evalDelta = [&](int k, int to) -> ll {\n            int from = assign[k];\n            if (to == from) return 0LL;\n            int rFrom = (int)r[from][k];\n            int rTo = (int)r[to][k];\n\n            int oldPFrom = P[from], oldPTo = P[to];\n\n            bool fromInactive = (sz[from] == 1);\n            bool toActive = (sz[to] == 0);\n\n            ll dE = deltaEdge(from, to, fromInactive, toActive);\n\n            // delta P via fenwick max update\n            fenw[from].add(rFrom + 1, -1);\n            sz[from]--;\n            fenw[to].add(rTo + 1, +1);\n            sz[to]++;\n\n            int newPFrom = (sz[from] == 0 ? 0 : fenw[from].getMax(sz[from]));\n            int newPTo   = (sz[to] == 0 ? 0 : fenw[to].getMax(sz[to]));\n\n            ll dP = 1LL*newPFrom*newPFrom + 1LL*newPTo*newPTo\n                  - (1LL*oldPFrom*oldPFrom + 1LL*oldPTo*oldPTo);\n\n            // rollback\n            fenw[to].add(rTo + 1, -1);\n            sz[to]--;\n            fenw[from].add(rFrom + 1, +1);\n            sz[from]++;\n\n            return dP + dE;\n        };\n\n        auto commitMove = [&](int k, int to) {\n            int from = assign[k];\n            int rFrom = (int)r[from][k];\n            int rTo = (int)r[to][k];\n\n            int oldPFrom = P[from], oldPTo = P[to];\n            bool fromInactive = (sz[from] == 1);\n            bool toActive = (sz[to] == 0);\n\n            // apply fenwick & Pcost\n            fenw[from].add(rFrom + 1, -1);\n            sz[from]--;\n            fenw[to].add(rTo + 1, +1);\n            sz[to]++;\n\n            int newPFrom = (sz[from] == 0 ? 0 : fenw[from].getMax(sz[from]));\n            int newPTo   = (sz[to] == 0 ? 0 : fenw[to].getMax(sz[to]));\n\n            Pcost += 1LL*newPFrom*newPFrom + 1LL*newPTo*newPTo\n                   - (1LL*oldPFrom*oldPFrom + 1LL*oldPTo*oldPTo);\n\n            P[from] = newPFrom;\n            P[to] = newPTo;\n\n            // update edge cost / subtreeCnt only if active toggles\n            if (fromInactive) {\n                for (int u : anc[from]) {\n                    subtreeCnt[u]--;\n                    if (subtreeCnt[u] == 0) edgeCost -= weightToParent[u];\n                }\n            }\n            if (toActive) {\n                for (int u : anc[to]) {\n                    if (subtreeCnt[u] == 0) edgeCost += weightToParent[u];\n                    subtreeCnt[u]++;\n                }\n            }\n\n            assign[k] = to;\n            totalCost = Pcost + edgeCost;\n        };\n\n        vector<int> order(K);\n        iota(order.begin(), order.end(), 0);\n\n        mt19937_64 rng(1234567 ^ (ll)assign[0] * 1000003);\n\n        for (int pass = 0; pass < 3 && !timeUp(); pass++) {\n            shuffle(order.begin(), order.end(), rng);\n            bool any = false;\n            for (int k : order) {\n                if (timeUp()) break;\n                int from = assign[k];\n\n                ll bestDelta = 0;\n                int bestTo = -1;\n\n                // evaluate all candidates for this resident\n                for (int to : cand[k]) {\n                    if (to == from) continue;\n                    ll d = evalDelta(k, to);\n                    if (d < bestDelta) {\n                        bestDelta = d;\n                        bestTo = to;\n                    }\n                }\n                if (bestTo != -1) {\n                    commitMove(k, bestTo);\n                    any = true;\n                }\n            }\n            if (!any) break;\n        }\n\n        // Build edge selection B from subtreeCnt\n        vector<int> activeEdges(M, 0);\n        for (int v = 1; v < N; v++) {\n            if (subtreeCnt[v] > 0) activeEdges[parentEdgeId[v]] = 1;\n        }\n\n        // score objective uses totalCost; but for output we return P and B packed? We'll rebuild B outside.\n        // We'll return totalCost and store P in a special vector by encoding: [P0..PN-1, dummy]\n        // However easiest: return P only, and rebuild B in main using recomputed? Can't.\n        // So we return totalCost and store B by global capture not possible. We'll return both by rebuilding now:\n        // We'll pack into vector<int> out size N+M as [P, B].\n        vector<int> out(N + M);\n        for (int i = 0; i < N; i++) out[i] = P[i];\n        for (int j = 0; j < M; j++) out[N + j] = activeEdges[j];\n        return {totalCost, out};\n    };\n\n    // Initial assignments:\n    // 1) nearest-by-radius\n    // 2) random among top candidates\n    // 3-5) greedy clustered (different random orders)\n    vector<vector<int>> inits;\n\n    {\n        vector<int> assign0(K);\n        for (int k = 0; k < K; k++) {\n            // cand[k] is union; use smallest required radius among them\n            int best = cand[k][0];\n            int bestNeed = (int)r[best][k];\n            for (int s : cand[k]) {\n                int need = (int)r[s][k];\n                if (need < bestNeed) {\n                    bestNeed = need;\n                    best = s;\n                }\n            }\n            assign0[k] = best;\n        }\n        inits.push_back(assign0);\n    }\n\n    {\n        mt19937_64 rng(777777);\n        vector<int> assign1(K);\n        for (int k = 0; k < K; k++) {\n            int t = min(5, (int)cand[k].size());\n            int idx = rng() % t;\n            // bias towards small radii: pick among first by radii (sort a temp)\n            vector<pair<int,int>> tmp;\n            tmp.reserve(cand[k].size());\n            for (int s : cand[k]) tmp.push_back({(int)r[s][k], s});\n            sort(tmp.begin(), tmp.end());\n            assign1[k] = tmp[idx].second;\n        }\n        inits.push_back(assign1);\n    }\n\n    // Greedy clustered inits\n    for (int rep = 0; rep < 4; rep++) {\n        mt19937_64 rng(12345 + rep * 998244353ULL);\n        inits.push_back(buildGreedyAssign(rng));\n    }\n\n    // Run several trials under time control.\n    // We will try up to 4 different initial assignments.\n    int maxTrials = 4;\n    int timePerTrialMs = 320; // refined from 450ms to allow more candidates/starts\n\n    ll bestCost = (1LL<<62);\n    vector<int> bestOut;\n\n    for (int t = 0; t < (int)inits.size() && t < maxTrials; t++) {\n        auto [cost, out] = solveTrial(inits[t], timePerTrialMs);\n        if (cost < bestCost) {\n            bestCost = cost;\n            bestOut = std::move(out);\n        }\n    }\n\n    // Output best\n    for (int i = 0; i < N; i++) {\n        if (i) cout << ' ';\n        cout << bestOut[i];\n    }\n    cout << '\\n';\n    for (int j = 0; j < M; j++) {\n        if (j) cout << ' ';\n        cout << bestOut[N + j];\n    }\n    cout << '\\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 LIM = 10000;\nstatic constexpr int KEY_SAMP = 40;\nstatic constexpr int E_SAMP = 60;\n\nstruct SwapOp {\n    short x1, y1, x2, y2;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    auto id = [](int x, int y) -> int { return x * (x + 1) / 2 + y; };\n\n    vector<int> cx(V), cy(V);\n    for (int x = 0; x < N; x++) for (int y = 0; y <= x; y++) {\n        int idx = id(x, y);\n        cx[idx] = x;\n        cy[idx] = y;\n    }\n\n    // Read\n    vector<int> at(V), pos(V);\n    for (int x = 0; x < N; x++) for (int y = 0; y <= x; y++) {\n        int b; cin >> b;\n        int idx = id(x, y);\n        at[idx] = b;\n        pos[b] = idx;\n    }\n\n    // key partition by value rank: blocks 1,2,...,30\n    // pref[t] = sum_{i=1..t+1} i = (t+1)(t+2)/2, and block t is values in [pref[t-1], pref[t]-1]\n    vector<int> pref(N);\n    for (int t = 0; t < N; t++) pref[t] = (t + 1) * (t + 2) / 2;\n\n    vector<int> key(V);\n    for (int v = 0; v < V; v++) {\n        int t = 0;\n        while (t < N && v >= pref[t]) t++;\n        key[v] = t;\n    }\n\n    // Build cover edges: u at tier x -> child at tier x+1 (two children)\n    // store directed edges list (from[e] -> to[e])\n    // and for each cell, store up to 2 incoming/outgoing cover edges.\n    vector<int> from, to;\n    from.reserve(870);\n    to.reserve(870);\n\n    vector<array<int,2>> outEdge(V, array<int,2>{-1,-1});\n    vector<array<int,2>> inEdge(V, array<int,2>{-1,-1});\n\n    auto add_out = [&](int u, int eidx) {\n        if (outEdge[u][0] == -1) outEdge[u][0] = eidx;\n        else outEdge[u][1] = eidx;\n    };\n    auto add_in = [&](int v, int eidx) {\n        if (inEdge[v][0] == -1) inEdge[v][0] = eidx;\n        else inEdge[v][1] = eidx;\n    };\n\n    int M = 0;\n    for (int x = 0; x <= N - 2; x++) {\n        for (int y = 0; y <= x; y++) {\n            int u = id(x, y);\n            int c1 = id(x + 1, y);\n            int c2 = id(x + 1, y + 1);\n\n            int e1 = M++;\n            from.push_back(u); to.push_back(c1);\n            add_out(u, e1); add_in(c1, e1);\n\n            int e2 = M++;\n            from.push_back(u); to.push_back(c2);\n            add_out(u, e2); add_in(c2, e2);\n        }\n    }\n\n    auto affectedEdges = [&](int a, int b, int buf[16]) -> int {\n        int cnt = 0;\n        auto add = [&](int e) {\n            if (e < 0) return;\n            for (int i = 0; i < cnt; i++) if (buf[i] == e) return;\n            buf[cnt++] = e;\n        };\n        for (int k = 0; k < 2; k++) {\n            add(outEdge[a][k]); add(inEdge[a][k]);\n            add(outEdge[b][k]); add(inEdge[b][k]);\n        }\n        return cnt;\n    };\n\n    // Swap implementation\n    vector<SwapOp> ops;\n    ops.reserve(LIM);\n    int K = 0;\n\n    auto doSwap = [&](int a, int b) -> bool {\n        if (K >= LIM) return false;\n        if (a == b) return true;\n        ops.push_back(SwapOp{(short)cx[a], (short)cy[a], (short)cx[b], (short)cy[b]});\n        K++;\n        int va = at[a], vb = at[b];\n        swap(at[a], at[b]);\n        pos[va] = b;\n        pos[vb] = a;\n        return true;\n    };\n\n    // Stage 1: key violations along cover edges\n    vector<char> keyViol(M, 0);\n    deque<int> qKey;\n    int keyViolCnt = 0;\n\n    for (int e = 0; e < M; e++) {\n        int u = from[e], v = to[e];\n        bool w = key[at[u]] > key[at[v]];\n        keyViol[e] = (char)w;\n        if (w) { keyViolCnt++; qKey.push_back(e); }\n    }\n\n    auto computeKeyDelta = [&](int a, int b) -> int {\n        int buf[16];\n        int cnt = affectedEdges(a, b, buf);\n        int va = at[a], vb = at[b];\n        int oldSum = 0, newSum = 0;\n        for (int i = 0; i < cnt; i++) {\n            int e = buf[i];\n            oldSum += (keyViol[e] ? 1 : 0);\n            int u = from[e], v = to[e];\n            int newUVal = (u == a ? vb : (u == b ? va : at[u]));\n            int newVVal = (v == a ? vb : (v == b ? va : at[v]));\n            bool nw = key[newUVal] > key[newVVal];\n            newSum += (nw ? 1 : 0);\n        }\n        return newSum - oldSum;\n    };\n\n    auto updateKeyAround = [&](int a, int b, deque<int> &queue) {\n        int buf[16];\n        int cnt = affectedEdges(a, b, buf);\n        for (int i = 0; i < cnt; i++) {\n            int e = buf[i];\n            int u = from[e], v = to[e];\n            bool nw = key[at[u]] > key[at[v]];\n            if ((bool)keyViol[e] != nw) {\n                keyViolCnt += (nw ? +1 : -1);\n                keyViol[e] = (char)nw;\n                if (nw) queue.push_back(e);\n            }\n        }\n    };\n\n    int stuckKey = 0;\n    while (keyViolCnt > 0 && K < LIM) {\n        if (qKey.empty()) {\n            for (int e = 0; e < M; e++) if (keyViol[e]) qKey.push_back(e);\n            if (qKey.empty()) break;\n        }\n\n        vector<int> cand;\n        cand.reserve(KEY_SAMP);\n        while (!qKey.empty() && (int)cand.size() < KEY_SAMP) {\n            int e = qKey.front(); qKey.pop_front();\n            if (keyViol[e]) cand.push_back(e);\n        }\n\n        int bestE = -1;\n        int bestDelta = INT_MAX;\n\n        for (int e : cand) {\n            int a = from[e], b = to[e];\n            int delta = computeKeyDelta(a, b);\n            if (delta < bestDelta) {\n                bestDelta = delta;\n                bestE = e;\n            }\n        }\n\n        // Reinsert other candidates (keep queue alive)\n        for (int e : cand) if (e != bestE) qKey.push_back(e);\n\n        if (bestE == -1) break;\n        int a = from[bestE], b = to[bestE];\n\n        // Prefer non-increasing key violations; occasionally allow small increase if stuck.\n        bool accept = false;\n        if (bestDelta <= 0) accept = true;\n        else if (stuckKey > 200 && bestDelta <= 1) accept = true;\n\n        if (!accept) {\n            stuckKey++;\n            // As a fallback, accept best non-stale edge directly if it still violates.\n            // (This should be rare.)\n            if (bestDelta <= 2) accept = true;\n        }\n\n        if (!accept) break; // let Stage 2 handle remaining if any\n\n        if (!doSwap(a, b)) break;\n        updateKeyAround(a, b, qKey);\n        stuckKey = (bestDelta <= 0 ? 0 : stuckKey + 1);\n    }\n\n    // compute E and actViol\n    vector<char> actViol(M, 0);\n    long long Ecnt = 0;\n    for (int e = 0; e < M; e++) {\n        int u = from[e], v = to[e];\n        bool w = at[u] > at[v];\n        actViol[e] = (char)w;\n        if (w) Ecnt++;\n    }\n\n    if (Ecnt == 0) {\n        cout << K << \"\\n\";\n        for (auto &op : ops) cout << op.x1 << \" \" << op.y1 << \" \" << op.x2 << \" \" << op.y2 << \"\\n\";\n        return 0;\n    }\n\n    // Stage 2: fix only equal-key edges (but choose best delta)\n    deque<int> qAct;\n    for (int e = 0; e < M; e++) {\n        int u = from[e], v = to[e];\n        if (actViol[e] && key[at[u]] == key[at[v]]) qAct.push_back(e);\n    }\n\n    auto computeEDelta = [&](int a, int b) -> long long {\n        int buf[16];\n        int cnt = affectedEdges(a, b, buf);\n        int va = at[a], vb = at[b];\n        long long oldSum = 0, newSum = 0;\n        for (int i = 0; i < cnt; i++) {\n            int e = buf[i];\n            oldSum += (actViol[e] ? 1 : 0);\n            int u = from[e], v = to[e];\n            int newUVal = (u == a ? vb : (u == b ? va : at[u]));\n            int newVVal = (v == a ? vb : (v == b ? va : at[v]));\n            bool nw = newUVal > newVVal;\n            newSum += (nw ? 1 : 0);\n        }\n        return newSum - oldSum;\n    };\n\n    auto updateActAround = [&](int a, int b, deque<int> &queue) {\n        int buf[16];\n        int cnt = affectedEdges(a, b, buf);\n        for (int i = 0; i < cnt; i++) {\n            int e = buf[i];\n            int u = from[e], v = to[e];\n            bool nw = at[u] > at[v];\n            if ((bool)actViol[e] != nw) {\n                Ecnt += (nw ? +1 : -1);\n                actViol[e] = (char)nw;\n            }\n            // Always consider pushing if violated and keys equal\n            if (nw) {\n                if (key[at[u]] == key[at[v]]) queue.push_back(e);\n            }\n        }\n    };\n\n    int stuckE = 0;\n    while (Ecnt > 0 && K < LIM) {\n        if (qAct.empty()) {\n            for (int e = 0; e < M; e++) {\n                if (actViol[e]) {\n                    int u = from[e], v = to[e];\n                    if (key[at[u]] == key[at[v]]) qAct.push_back(e);\n                }\n            }\n            if (qAct.empty()) break; // no equal-key moves\n        }\n\n        vector<int> cand;\n        cand.reserve(E_SAMP);\n        while (!qAct.empty() && (int)cand.size() < E_SAMP) {\n            int e = qAct.front(); qAct.pop_front();\n            if (!actViol[e]) continue;\n            int u = from[e], v = to[e];\n            if (key[at[u]] != key[at[v]]) continue;\n            cand.push_back(e);\n        }\n        if (cand.empty()) continue;\n\n        int bestE = -1;\n        long long bestDelta = (1LL<<60);\n\n        for (int e : cand) {\n            int a = from[e], b = to[e];\n            long long delta = computeEDelta(a, b);\n            if (delta < bestDelta) {\n                bestDelta = delta;\n                bestE = e;\n            }\n        }\n\n        for (int e : cand) if (e != bestE) qAct.push_back(e);\n\n        if (bestE == -1) continue;\n        int a = from[bestE], b = to[bestE];\n\n        // Accept rules: prefer delta<0, allow delta==0, avoid delta>0 unless stuck.\n        bool accept = false;\n        if (bestDelta < 0) accept = true;\n        else if (bestDelta == 0) accept = (stuckE > 50); // reduce plateau wandering\n        else {\n            // bestDelta > 0\n            accept = (stuckE > 400 && bestDelta <= 2);\n        }\n\n        if (!accept) {\n            stuckE++;\n            // If very stuck, do a deterministic rescue: take any violated equal-key edge.\n            if (stuckE > 800) {\n                int rescueE = -1;\n                for (int e : cand) { if (actViol[e]) { rescueE = e; break; } }\n                if (rescueE == -1) break;\n                a = from[rescueE]; b = to[rescueE];\n                if (!doSwap(a, b)) break;\n                updateActAround(a, b, qAct);\n                stuckE = 0;\n            }\n            continue;\n        }\n\n        if (!doSwap(a, b)) break;\n        updateActAround(a, b, qAct);\n        stuckE = 0;\n    }\n\n    cout << K << \"\\n\";\n    for (auto &op : ops) cout << op.x1 << \" \" << op.y1 << \" \" << op.x2 << \" \" << op.y2 << \"\\n\";\n    return 0;\n}","toyota2023summer-final":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\n\nstatic const int dx4[4] = {-1, 1, 0, 0}; // up, down, left, right in (i,j)\nstatic const int dy4[4] = {0, 0, -1, 1};\n\nstruct Tree {\n    int V = 0;                 // total reachable nodes including entrance\n    int ent = -1;              // entrance node id\n    vector<int> parent;\n    vector<int> depth;\n    vector<int> bfsOrder;\n    vector<vector<int>> children; // adjacency in BFS tree (parent->children)\n};\n\nstatic Tree build_bfs_tree(\n    int D,\n    const vector<vector<int>> &id,\n    int ent,\n    const vector<pair<int,int>> &coord,\n    const array<int,4> &dirOrder\n){\n    int V = 0;\n    // id values are in [0,V). We can infer V by max+1\n    for (int i=0;i<D;i++) for (int j=0;j<D;j++) if (id[i][j] >= 0) V = max(V, id[i][j] + 1);\n\n    vector<int> parent(V, -1), depth(V, -1), bfsOrder(V, -1);\n    vector<vector<int>> children(V);\n    vector<char> vis(V, 0);\n\n    queue<int> q;\n    vis[ent] = 1;\n    depth[ent] = 0;\n    bfsOrder[ent] = 0;\n    int ord = 1;\n    q.push(ent);\n\n    while(!q.empty()){\n        int v = q.front(); q.pop();\n        auto [x,y] = coord[v];\n        for(int k=0;k<4;k++){\n            int dir = dirOrder[k];\n            int nx = x + dx4[dir];\n            int ny = y + dy4[dir];\n            if(nx < 0 || nx >= D || ny < 0 || ny >= D) continue;\n            int nid = id[nx][ny];\n            if(nid < 0) continue;\n            if(vis[nid]) continue;\n            vis[nid] = 1;\n            parent[nid] = v;\n            depth[nid] = depth[v] + 1;\n            bfsOrder[nid] = ord++;\n            q.push(nid);\n        }\n    }\n\n    // Build children from parent\n    for(int v=0; v<V; v++){\n        if(v == ent) continue;\n        int p = parent[v];\n        if(p >= 0) children[p].push_back(v);\n    }\n\n    Tree t;\n    t.V = V;\n    t.ent = ent;\n    t.parent = move(parent);\n    t.depth = move(depth);\n    t.bfsOrder = move(bfsOrder);\n    t.children = move(children);\n    return t;\n}\n\nstatic vector<int> compute_subtree_sizes(const Tree &t){\n    vector<int> sub(t.V, 1);\n    vector<int> nodes(t.V);\n    iota(nodes.begin(), nodes.end(), 0);\n    sort(nodes.begin(), nodes.end(), [&](int a,int b){\n        return t.depth[a] > t.depth[b];\n    });\n    for(int v : nodes){\n        if(v == t.ent) continue;\n        int p = t.parent[v];\n        // add to parent\n        if(p >= 0) sub[p] += sub[v];\n    }\n    return sub;\n}\n\n// Simulate greedy removal order using structural priorities (no labels).\n// Availability rule: a node is removable if parent already removed => exactly tree poset.\nstatic vector<int> simulate_proxy_pos(\n    const Tree &t,\n    const vector<ll> &key1,\n    const vector<ll> &key2\n){\n    int M = t.V - 1; // number of containers = all nodes except entrance\n    vector<int> pos(t.V, -1);\n    vector<char> removed(t.V, 0);\n\n    struct Node {\n        ll k1, k2;\n        int ord;\n        int v;\n    };\n    struct Cmp {\n        bool operator()(const Node &a, const Node &b) const {\n            if(a.k1 != b.k1) return a.k1 > b.k1; // min-heap\n            if(a.k2 != b.k2) return a.k2 > b.k2;\n            if(a.ord != b.ord) return a.ord > b.ord;\n            return a.v > b.v;\n        }\n    };\n\n    priority_queue<Node, vector<Node>, Cmp> pq;\n    for(int ch : t.children[t.ent]){\n        pq.push({key1[ch], key2[ch], t.bfsOrder[ch], ch});\n    }\n\n    int cnt = 0;\n    while(cnt < M){\n        auto cur = pq.top(); pq.pop();\n        int v = cur.v;\n        if(removed[v]) continue;\n        removed[v] = 1;\n        pos[v] = cnt++;\n        for(int ch : t.children[v]){\n            if(!removed[ch]) pq.push({key1[ch], key2[ch], t.bfsOrder[ch], ch});\n        }\n    }\n    return pos;\n}\n\nstruct Fenwick {\n    int n;\n    vector<int> bit;\n    Fenwick(int n=0): n(n), bit(n+1,0) {}\n    void add(int i, int v){\n        for(i++; i<=n; i+=i&-i) bit[i]+=v;\n    }\n    int sumPrefix(int i){\n        int s=0;\n        for(i++; i>0; i-=i&-i) s+=bit[i-1];\n        return s;\n    }\n};\n\nstatic ll count_inversions(const vector<int> &a, int maxVal){\n    int n = (int)a.size();\n    Fenwick fw(maxVal+1);\n    ll inv = 0;\n    for(int i=0;i<n;i++){\n        int x = a[i];\n        int le = fw.sumPrefix(x); // number of <= x so far\n        inv += i - le;            // number of > x so far\n        fw.add(x, 1);\n    }\n    return inv;\n}\n\nstruct InsertionHeuristic {\n    // proxyPos[p][v] is rank 0..M-1 for container nodes; entrance pos=-1\n    vector<vector<int>> proxyPos;\n    int P = 0;\n    int M = 0; // containers count\n    vector<int> sumPosScaled; // sum over proxies of pos[v], used for tie with t_d*P\n\n    const vector<int> *assignedNodesPtr = nullptr;\n    const vector<int> *labelPtr = nullptr;\n\n    ll choose_candidate_cost(\n        int v,\n        int t,\n        const vector<int> &assignedNodes,\n        const vector<int> &label\n    ){\n        // total cost = sum over proxies of inversion increment between (assigned node u, candidate v)\n        ll total = 0;\n        for(int p=0;p<P;p++){\n            int pv = proxyPos[p][v];\n            for(int u : assignedNodes){\n                int pu = proxyPos[p][u];\n                int lu = label[u];\n                if(pu < pv){\n                    if(lu > t) total++;\n                } else { // pu > pv\n                    if(t > lu) total++;\n                }\n            }\n        }\n        return total;\n    }\n};\n\nstatic int pick_best_node(\n    const Tree &t,\n    const InsertionHeuristic &ih,\n    const vector<int> &readyVec,\n    const vector<char> &readyFlag,\n    const vector<int> &assignedNodes,\n    const vector<int> &label,\n    int tval\n){\n    int bestV = -1;\n    ll bestCost = (1LL<<62);\n    ll bestTie = (1LL<<62);\n\n    for(int v : readyVec){\n        if(!readyFlag[v]) continue;\n        // cost is sum of proxy inversion increments\n        ll cost = 0;\n        for(int p=0;p<ih.P;p++){\n            int pv = ih.proxyPos[p][v];\n            for(int u : assignedNodes){\n                int pu = ih.proxyPos[p][u];\n                int lu = label[u];\n                if(pu < pv){\n                    if(lu > tval) cost++;\n                } else {\n                    if(tval > lu) cost++;\n                }\n            }\n        }\n        ll tie = llabs( (ll)ih.sumPosScaled[v] - (ll)tval * ih.P );\n\n        if(cost < bestCost ||\n           (cost == bestCost && (tie < bestTie ||\n              (tie == bestTie && (\n                  t.depth[v] < t.depth[bestV] ||\n                  (t.depth[v] == t.depth[bestV] && t.bfsOrder[v] < t.bfsOrder[bestV])\n              )))\n           ))\n        {\n            bestCost = cost;\n            bestTie = tie;\n            bestV = v;\n        }\n    }\n    return bestV;\n}\n\nstatic ll simulate_one(\n    const Tree &t,\n    const InsertionHeuristic &ih,\n    mt19937 &rng\n){\n    int M = ih.M;\n    vector<int> labels(t.V, -1);\n\n    // ready nodes: those with all children already \"inserted\" (postorder insertion)\n    vector<int> remChildCnt(t.V, 0);\n    for(int v=0; v<t.V; v++){\n        if(v == t.ent) continue;\n        remChildCnt[v] = (int)t.children[v].size();\n    }\n\n    vector<char> readyFlag(t.V, 0);\n    vector<int> readyVec;\n    for(int v=0; v<t.V; v++){\n        if(v == t.ent) continue;\n        if(remChildCnt[v] == 0){\n            readyFlag[v] = 1;\n            readyVec.push_back(v);\n        }\n    }\n\n    vector<int> assignedNodes;\n    assignedNodes.reserve(M);\n\n    // random permutation as arrival sequence\n    vector<int> perm(M);\n    iota(perm.begin(), perm.end(), 0);\n    shuffle(perm.begin(), perm.end(), rng);\n\n    for(int d=0; d<M; d++){\n        int t_d = perm[d];\n        int v = pick_best_node(t, ih, readyVec, readyFlag, assignedNodes, labels, t_d);\n\n        readyFlag[v] = 0;\n        labels[v] = t_d;\n        assignedNodes.push_back(v);\n\n        int p = t.parent[v];\n        if(p >= 0 && p != t.ent){\n            remChildCnt[p]--;\n            if(remChildCnt[p] == 0){\n                readyFlag[p] = 1;\n                readyVec.push_back(p);\n            }\n        }\n    }\n\n    // transport with min-heap by actual label\n    vector<char> removed(t.V, 0);\n    struct NodeLab{\n        int lab, ord, v;\n    };\n    struct Cmp{\n        bool operator()(const NodeLab& a, const NodeLab& b) const{\n            if(a.lab != b.lab) return a.lab > b.lab;\n            if(a.ord != b.ord) return a.ord > b.ord;\n            return a.v > b.v;\n        }\n    };\n    priority_queue<NodeLab, vector<NodeLab>, Cmp> pq;\n    for(int ch : t.children[t.ent]){\n        pq.push({labels[ch], t.bfsOrder[ch], ch});\n    }\n\n    vector<int> seq;\n    seq.reserve(M);\n    while((int)seq.size() < M){\n        auto cur = pq.top(); pq.pop();\n        int v = cur.v;\n        if(removed[v]) continue;\n        removed[v] = 1;\n        seq.push_back(labels[v]);\n        for(int ch : t.children[v]){\n            if(!removed[ch]) pq.push({labels[ch], t.bfsOrder[ch], ch});\n        }\n    }\n\n    return count_inversions(seq, M-1);\n}\n\nstatic InsertionHeuristic make_insertion_heuristic(\n    const Tree &t,\n    const vector<vector<int>> &proxyPos\n){\n    InsertionHeuristic ih;\n    ih.proxyPos = proxyPos;\n    ih.P = (int)proxyPos.size();\n    ih.M = t.V - 1;\n\n    ih.sumPosScaled.assign(t.V, 0);\n    for(int p=0;p<ih.P;p++){\n        for(int v=0; v<t.V; v++){\n            if(v == t.ent) continue;\n            ih.sumPosScaled[v] += proxyPos[p][v];\n        }\n    }\n    return ih;\n}\n\nint main(){\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int D, N;\n    cin >> D >> N;\n    vector<vector<bool>> obs(D, vector<bool>(D,false));\n    for(int k=0;k<N;k++){\n        int ri, rj;\n        cin >> ri >> rj;\n        obs[ri][rj] = true;\n    }\n\n    int ent_i = 0;\n    int ent_j = (D-1)/2;\n\n    vector<vector<int>> id(D, vector<int>(D, -1));\n    vector<pair<int,int>> coord;\n    coord.reserve(D*D);\n\n    int V = 0;\n    for(int i=0;i<D;i++) for(int j=0;j<D;j++){\n        if(obs[i][j]) continue;\n        id[i][j] = V++;\n        coord.push_back({i,j});\n    }\n\n    int ent = id[ent_i][ent_j];\n    int M = V - 1;\n\n    // Candidate BFS direction orders\n    vector<array<int,4>> dirCandidates = {\n        array<int,4>{0,3,1,2},\n        array<int,4>{0,2,1,3},\n        array<int,4>{1,3,0,2},\n        array<int,4>{1,2,0,3},\n        array<int,4>{3,0,2,1},\n        array<int,4>{2,0,3,1}\n    };\n\n    // Add a couple random permutations to broaden search\n    uint64_t seed = chrono::steady_clock::now().time_since_epoch().count();\n    mt19937 rng(seed);\n    for(int rep=0; rep<2; rep++){\n        array<int,4> a = {0,1,2,3};\n        shuffle(a.begin(), a.end(), rng);\n        // avoid duplicates\n        bool ok = true;\n        for(auto &b: dirCandidates){\n            if(b == a) ok = false;\n        }\n        if(ok) dirCandidates.push_back(a);\n    }\n\n    // For each tree, compute proxies and evaluate by small Monte-Carlo\n    ll bestScore = (1LL<<62);\n    Tree bestTree;\n    InsertionHeuristic bestIH;\n    bool bestInit = false;\n\n    // Proxy setup candidates (depth +/- subtree sizes, and -depth)\n    for(auto dirOrder : dirCandidates){\n        Tree t = build_bfs_tree(D, id, ent, coord, dirOrder);\n\n        // subtree sizes\n        auto sub = compute_subtree_sizes(t);\n\n        // Build 4 proxy key choices\n        vector<ll> key1a(t.V), key2a(t.V);\n        vector<ll> key1b(t.V), key2b(t.V);\n        vector<ll> key1c(t.V), key2c(t.V);\n        vector<ll> key1d(t.V), key2d(t.V);\n\n        for(int v=0; v<t.V; v++){\n            if(v == t.ent) continue;\n            key1a[v] = t.depth[v]; key2a[v] = 0;\n            key1b[v] = t.depth[v]; key2b[v] = - (ll)sub[v];\n            key1c[v] = t.depth[v]; key2c[v] = + (ll)sub[v];\n            key1d[v] = - (ll)t.depth[v]; key2d[v] = + (ll)sub[v];\n        }\n\n        vector<vector<int>> proxyPos;\n        proxyPos.reserve(4);\n        proxyPos.push_back(simulate_proxy_pos(t, key1a, key2a));\n        proxyPos.push_back(simulate_proxy_pos(t, key1b, key2b));\n        proxyPos.push_back(simulate_proxy_pos(t, key1c, key2c));\n        proxyPos.push_back(simulate_proxy_pos(t, key1d, key2d));\n\n        InsertionHeuristic ih = make_insertion_heuristic(t, proxyPos);\n\n        // Monte-Carlo evaluation\n        int S = 3; // keep small for time\n        ll sumInv = 0;\n        for(int s=0;s<S;s++){\n            sumInv += simulate_one(t, ih, rng);\n        }\n        ll avgInv = sumInv / S;\n\n        if(!bestInit || avgInv < bestScore){\n            bestScore = avgInv;\n            bestTree = move(t);\n            bestIH = move(ih);\n            bestInit = true;\n        }\n    }\n\n    const Tree &t = bestTree;\n    const InsertionHeuristic &ih = bestIH;\n\n    // Real online insertion\n    vector<int> remChildCnt(t.V, 0);\n    for(int v=0; v<t.V; v++){\n        if(v == t.ent) continue;\n        remChildCnt[v] = (int)t.children[v].size();\n    }\n\n    vector<char> readyFlag(t.V, 0);\n    vector<int> readyVec;\n    readyVec.reserve(M);\n    for(int v=0; v<t.V; v++){\n        if(v == t.ent) continue;\n        if(remChildCnt[v] == 0){\n            readyFlag[v] = 1;\n            readyVec.push_back(v);\n        }\n    }\n\n    vector<int> labels(t.V, -1);\n    vector<int> assignedNodes;\n    assignedNodes.reserve(M);\n\n    for(int d=0; d<M; d++){\n        int t_d;\n        cin >> t_d;\n\n        int bestV = pick_best_node(t, ih, readyVec, readyFlag, assignedNodes, labels, t_d);\n\n        auto [pi, pj] = coord[bestV];\n        cout << pi << \" \" << pj << \"\\n\" << flush;\n\n        readyFlag[bestV] = 0;\n        labels[bestV] = t_d;\n        assignedNodes.push_back(bestV);\n\n        int p = t.parent[bestV];\n        if(p >= 0 && p != t.ent){\n            remChildCnt[p]--;\n            if(remChildCnt[p] == 0){\n                readyFlag[p] = 1;\n                readyVec.push_back(p);\n            }\n        }\n    }\n\n    // Transport order (feasible): parent-before-child, greedily by min label\n    vector<char> removed(t.V, 0);\n    struct NodeLab{\n        int lab, ord, v;\n    };\n    struct Cmp{\n        bool operator()(const NodeLab& a, const NodeLab& b) const{\n            if(a.lab != b.lab) return a.lab > b.lab;\n            if(a.ord != b.ord) return a.ord > b.ord;\n            return a.v > b.v;\n        }\n    };\n    priority_queue<NodeLab, vector<NodeLab>, Cmp> pq;\n    for(int ch : t.children[t.ent]){\n        pq.push({labels[ch], t.bfsOrder[ch], ch});\n    }\n\n    vector<int> orderNodes;\n    orderNodes.reserve(M);\n\n    while((int)orderNodes.size() < M){\n        auto cur = pq.top(); pq.pop();\n        int v = cur.v;\n        if(removed[v]) continue;\n        removed[v] = 1;\n        orderNodes.push_back(v);\n        for(int ch : t.children[v]){\n            if(!removed[ch]) pq.push({labels[ch], t.bfsOrder[ch], ch});\n        }\n    }\n\n    for(int k=0; k<M; k++){\n        auto [qi, qj] = coord[orderNodes[k]];\n        cout << qi << \" \" << qj << \"\\n\" << flush;\n    }\n\n    return 0;\n}","ahc024":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const int DIRS[4][2] = {{1,0},{-1,0},{0,1},{0,-1}};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int n, m;\n    cin >> n >> m;\n    vector<vector<int>> a(n, vector<int>(n));\n    for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) cin >> a[i][j];\n\n    int N = n * n;\n    auto id = [&](int i, int j){ return i*n + j; };\n    auto ij = [&](int x){ return pair<int,int>(x/n, x%n); };\n\n    // adjOrig[x][y] for 0<=x<y<=m\n    vector<vector<unsigned char>> adjOrig(m+1, vector<unsigned char>(m+1, 0));\n    for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) {\n        int c1 = a[i][j];\n        for (auto &d : DIRS) {\n            int ni = i + d[0], nj = j + d[1];\n            int c2;\n            if (ni < 0 || ni >= n || nj < 0 || nj >= n) c2 = 0;\n            else c2 = a[ni][nj];\n            if (c1 == c2) continue;\n            int x = min(c1, c2), y = max(c1, c2);\n            adjOrig[x][y] = 1;\n        }\n    }\n\n    // touchOutside[c] = does color c appear on boundary in the input?\n    vector<unsigned char> touchOutside(m+1, 0);\n    vector<vector<int>> boundaryCells(m+1);\n    for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) {\n        if (i==0 || i==n-1 || j==0 || j==n-1) {\n            int c = a[i][j];\n            touchOutside[c] = 1;\n            boundaryCells[c].push_back(id(i,j));\n        }\n    }\n\n    vector<unsigned char> forbidden(m+1, 0);\n    for (int c = 1; c <= m; c++) forbidden[c] = !touchOutside[c];\n\n    // isColor[c][cell]\n    vector<vector<unsigned char>> isColor(m+1, vector<unsigned char>(N, 0));\n    vector<vector<int>> posByColor(m+1);\n    for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) {\n        int c = a[i][j];\n        int t = id(i,j);\n        isColor[c][t] = 1;\n        posByColor[c].push_back(t);\n    }\n\n    // mustKeepAllowedCells[c] = allowed-cell which is adjacent to forbidden-color cell in original\n    vector<vector<int>> mustKeepAllowed(m+1);\n    vector<unsigned char> mustKeepCell(N, 0);\n    for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) {\n        int c = a[i][j];\n        if (c == 0) continue; // none inside\n        int cur = id(i,j);\n        if (forbidden[c]) {\n            mustKeepCell[cur] = 1; // forbidden handled separately too\n            continue;\n        }\n        // allowed color: keep if adjacent to any forbidden color\n        bool ok = false;\n        for (auto &d : DIRS) {\n            int ni = i + d[0], nj = j + d[1];\n            if (ni < 0 || ni >= n || nj < 0 || nj >= n) continue;\n            int cc = a[ni][nj];\n            if (cc != 0 && forbidden[cc]) { ok = true; break; }\n        }\n        if (ok) mustKeepAllowed[c].push_back(cur);\n    }\n\n    // repEdges for allowed-allowed adjacent pairs: store endpoints (cell of x, cell of y)\n    vector<vector<vector<pair<int,int>>>> repEdges(m+1, vector<vector<pair<int,int>>>(m+1));\n    for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) {\n        int u = a[i][j];\n        int cid = id(i,j);\n        if (j+1 < n) {\n            int v = a[i][j+1];\n            if (u != v && !forbidden[u] && !forbidden[v]) {\n                int x = min(u,v), y = max(u,v);\n                int id_x = (u==x ? cid : id(i,j+1));\n                int id_y = (u==x ? id(i,j+1) : cid);\n                repEdges[x][y].push_back({id_x, id_y});\n            }\n        }\n        if (i+1 < n) {\n            int v = a[i+1][j];\n            if (u != v && !forbidden[u] && !forbidden[v]) {\n                int x = min(u,v), y = max(u,v);\n                int id_x = (u==x ? cid : id(i+1,j));\n                int id_y = (u==x ? id(i+1,j) : cid);\n                repEdges[x][y].push_back({id_x, id_y});\n            }\n        }\n    }\n\n    // list of allowed-allowed adjacent pairs\n    vector<pair<int,int>> adjPairs;\n    for (int x = 1; x <= m; x++) if (!forbidden[x]) {\n        for (int y = x+1; y <= m; y++) if (!forbidden[y]) {\n            if (adjOrig[x][y]) adjPairs.push_back({x,y});\n        }\n    }\n\n    // BFS distances within cells of color c\n    auto bfsDist = [&](int c, int start, vector<int>& dist) {\n        fill(dist.begin(), dist.end(), -1);\n        queue<int> q;\n        dist[start] = 0;\n        q.push(start);\n        while(!q.empty()) {\n            int cur = q.front(); q.pop();\n            auto [ci, cj] = ij(cur);\n            for (auto &d : DIRS) {\n                int ni = ci + d[0], nj = cj + d[1];\n                if (ni<0||ni>=n||nj<0||nj>=n) continue;\n                int nid = id(ni,nj);\n                if (!isColor[c][nid]) continue;\n                if (dist[nid] != -1) continue;\n                dist[nid] = dist[cur] + 1;\n                q.push(nid);\n            }\n        }\n    };\n\n    // shortest path between two nodes within original color c; mark cells on that path to keepMask\n    auto bfsPath = [&](int c, int s, int t, vector<unsigned char>& keepMask) {\n        vector<int> parent(N, -1);\n        queue<int> q;\n        parent[s] = s;\n        q.push(s);\n        while(!q.empty()) {\n            int cur = q.front(); q.pop();\n            if (cur == t) break;\n            auto [ci, cj] = ij(cur);\n            for (auto &d : DIRS) {\n                int ni = ci + d[0], nj = cj + d[1];\n                if (ni<0||ni>=n||nj<0||nj>=n) continue;\n                int nid = id(ni,nj);\n                if (!isColor[c][nid]) continue;\n                if (parent[nid] != -1) continue;\n                parent[nid] = cur;\n                q.push(nid);\n            }\n        }\n        if (parent[t] == -1) return; // shouldn't happen\n\n        int cur = t;\n        while(true) {\n            keepMask[cur] = 1;\n            if (cur == s) break;\n            cur = parent[cur];\n        }\n    };\n\n    // Build kept subgraph for color c connecting ALL terminal cells (terminals are mandatory),\n    // but Steiner computation only uses representatives of terminal-connected components.\n    auto buildSteinerForColor = [&](int c,\n                                     const vector<int>& terminalCells,\n                                     vector<vector<int>>& b /*b as grid*/ ) {\n        // Mark terminals\n        vector<unsigned char> termMask(N, 0), seenTerm(N, 0);\n        for (int x : terminalCells) termMask[x] = 1;\n\n        // Find connected components among terminal cells (adjacency only between terminal cells)\n        vector<int> reps;\n        vector<int> stack;\n        queue<int> q;\n        for (int x : terminalCells) {\n            if (seenTerm[x]) continue;\n            seenTerm[x] = 1;\n            reps.push_back(x);\n            q.push(x);\n            while(!q.empty()) {\n                int cur = q.front(); q.pop();\n                auto [ci, cj] = ij(cur);\n                for (auto &d : DIRS) {\n                    int ni = ci + d[0], nj = cj + d[1];\n                    if (ni<0||ni>=n||nj<0||nj>=n) continue;\n                    int nid = id(ni,nj);\n                    if (!termMask[nid] || seenTerm[nid]) continue;\n                    seenTerm[nid] = 1;\n                    q.push(nid);\n                }\n            }\n        }\n\n        vector<unsigned char> keepMask(N, 0);\n        for (int t : terminalCells) keepMask[t] = 1; // always keep terminals\n\n        if ((int)reps.size() <= 1) {\n            // just terminals already connected among themselves; done\n        } else {\n            int k = (int)reps.size();\n            vector<int> dist(N);\n            vector<vector<int>> distMat(k, vector<int>(k, 0));\n\n            // distances between reps\n            for (int i = 0; i < k; i++) {\n                bfsDist(c, reps[i], dist);\n                for (int j = 0; j < k; j++) distMat[i][j] = dist[reps[j]];\n            }\n\n            // MST via Prim\n            const int INF = 1e9;\n            vector<int> minCost(k, INF), parent(k, -1);\n            vector<unsigned char> used(k, 0);\n            minCost[0] = 0;\n            for (int it = 0; it < k; it++) {\n                int v = -1;\n                for (int i = 0; i < k; i++) if (!used[i] && (v==-1 || minCost[i] < minCost[v])) v = i;\n                used[v] = 1;\n                for (int u = 0; u < k; u++) if (!used[u]) {\n                    int w = distMat[v][u];\n                    if (w >= 0 && w < minCost[u]) {\n                        minCost[u] = w;\n                        parent[u] = v;\n                    }\n                }\n            }\n\n            // Add paths for MST edges\n            for (int u = 1; u < k; u++) {\n                int p = parent[u];\n                if (p < 0) continue;\n                bfsPath(c, reps[p], reps[u], keepMask);\n            }\n        }\n\n        // Apply to b\n        for (int cell = 0; cell < N; cell++) if (keepMask[cell]) {\n            auto [x,y] = ij(cell);\n            b[x][y] = c;\n        }\n    };\n\n    // Connectivity repair: connect components of b==c using MST-steiner over component reps.\n    auto connectColorMST = [&](vector<vector<int>>& b, int c) {\n        // find components in current b==c\n        vector<unsigned char> vis(N, 0);\n        vector<int> reps;\n        queue<int> q;\n\n        for (int cell : posByColor[c]) {\n            if (b[cell/n][cell%n] != c) continue;\n            if (vis[cell]) continue;\n            vis[cell] = 1;\n            reps.push_back(cell);\n            q.push(cell);\n            while(!q.empty()) {\n                int cur = q.front(); q.pop();\n                auto [ci, cj] = ij(cur);\n                for (auto &d : DIRS) {\n                    int ni = ci + d[0], nj = cj + d[1];\n                    if (ni<0||ni>=n||nj<0||nj>=n) continue;\n                    int nid = id(ni,nj);\n                    if (vis[nid]) continue;\n                    if (b[ni][nj] != c) continue;\n                    vis[nid] = 1;\n                    q.push(nid);\n                }\n            }\n        }\n        if ((int)reps.size() <= 1) return;\n\n        int k = (int)reps.size();\n        vector<int> dist(N);\n        vector<vector<int>> distMat(k, vector<int>(k, 0));\n\n        for (int i = 0; i < k; i++) {\n            bfsDist(c, reps[i], dist);\n            for (int j = 0; j < k; j++) distMat[i][j] = dist[reps[j]];\n        }\n\n        // MST\n        const int INF = 1e9;\n        vector<int> minCost(k, INF), parent(k, -1);\n        vector<unsigned char> used(k, 0);\n        minCost[0] = 0;\n        for (int it = 0; it < k; it++) {\n            int v = -1;\n            for (int i = 0; i < k; i++) if (!used[i] && (v==-1 || minCost[i] < minCost[v])) v = i;\n            used[v] = 1;\n            for (int u = 0; u < k; u++) if (!used[u]) {\n                int w = distMat[v][u];\n                if (w >= 0 && w < minCost[u]) {\n                    minCost[u] = w;\n                    parent[u] = v;\n                }\n            }\n        }\n\n        // Add paths\n        vector<unsigned char> keepMask(N, 0);\n        for (int u = 1; u < k; u++) {\n            int p = parent[u];\n            if (p < 0) continue;\n            fill(keepMask.begin(), keepMask.end(), 0);\n            bfsPath(c, reps[p], reps[u], keepMask);\n            for (int cell = 0; cell < N; cell++) if (keepMask[cell]) {\n                auto [x,y] = ij(cell);\n                b[x][y] = c;\n            }\n        }\n    };\n\n    auto checkAll = [&](const vector<vector<int>>& b)->bool{\n        // ward colors connectivity\n        for (int c = 1; c <= m; c++) {\n            int start = -1, tot = 0;\n            for (int cell : posByColor[c]) {\n                auto [i,j] = ij(cell);\n                if (b[i][j] == c) {\n                    tot++;\n                    if (start == -1) start = cell;\n                }\n            }\n            if (tot == 0) return false;\n            vector<unsigned char> vis(N, 0);\n            queue<int> q;\n            vis[start] = 1;\n            q.push(start);\n            int cnt = 1;\n            while(!q.empty()) {\n                int cur = q.front(); q.pop();\n                auto [ci, cj] = ij(cur);\n                for (auto &d : DIRS) {\n                    int ni = ci + d[0], nj = cj + d[1];\n                    if (ni<0||ni>=n||nj<0||nj>=n) continue;\n                    if (b[ni][nj] != c) continue;\n                    int nid = id(ni,nj);\n                    if (!vis[nid]) { vis[nid] = 1; q.push(nid); cnt++; }\n                }\n            }\n            if (cnt != tot) return false;\n        }\n\n        // 0 connectivity via outside\n        int M2 = n + 2;\n        auto idExt = [&](int x,int y){ return x*M2 + y; };\n        vector<unsigned char> vis0(M2*M2, 0);\n        queue<pair<int,int>> q;\n        vis0[idExt(0,0)] = 1;\n        q.push({0,0});\n        while(!q.empty()) {\n            auto [x,y] = q.front(); q.pop();\n            for (auto &d : DIRS) {\n                int nx = x + d[0], ny = y + d[1];\n                if (nx<0||nx>=M2||ny<0||ny>=M2) continue;\n                bool pass;\n                if (nx==0||nx==M2-1||ny==0||ny==M2-1) pass = true; // outside\n                else pass = (b[nx-1][ny-1] == 0);\n                if (!pass) continue;\n                int nid = idExt(nx,ny);\n                if (!vis0[nid]) { vis0[nid] = 1; q.push({nx,ny}); }\n            }\n        }\n        for (int i=0;i<n;i++) for (int j=0;j<n;j++) {\n            if (b[i][j] == 0) {\n                if (!vis0[idExt(i+1,j+1)]) return false;\n            }\n        }\n\n        // adjacency equivalence\n        vector<vector<unsigned char>> adjOut(m+1, vector<unsigned char>(m+1, 0));\n        for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) {\n            int c1 = b[i][j];\n            for (auto &d : DIRS) {\n                int ni = i + d[0], nj = j + d[1];\n                int c2;\n                if (ni < 0 || ni >= n || nj < 0 || nj >= n) c2 = 0;\n                else c2 = b[ni][nj];\n                if (c1 == c2) continue;\n                int x = min(c1, c2), y = max(c1, c2);\n                adjOut[x][y] = 1;\n            }\n        }\n        for (int x = 0; x <= m; x++) for (int y = x+1; y <= m; y++) {\n            if (adjOut[x][y] != adjOrig[x][y]) return false;\n        }\n        return true;\n    };\n\n    mt19937_64 rng((uint64_t)chrono::high_resolution_clock::now().time_since_epoch().count());\n\n    vector<vector<int>> best = a;\n    int bestZero = -1;\n\n    auto computeZero = [&](const vector<vector<int>>& b)->int{\n        int cnt = 0;\n        for (int i=0;i<n;i++) for (int j=0;j<n;j++) if (b[i][j]==0) cnt++;\n        return cnt;\n    };\n\n    // stamp-based terminal marking per color\n    vector<vector<int>> termStamp(m+1, vector<int>(N, 0));\n    int stamp = 1;\n    vector<vector<int>> terminals(m+1);\n\n    auto startTime = chrono::high_resolution_clock::now();\n\n    // how many trials (bounded by time)\n    int T = 30;\n    for (int trial = 0; trial < T; trial++) {\n        double elapsed = chrono::duration<double>(chrono::high_resolution_clock::now() - startTime).count();\n        if (elapsed > 1.85) break;\n\n        // b init: keep forbidden colors completely, others set to 0 for now\n        vector<vector<int>> b(n, vector<int>(n, 0));\n        for (int i=0;i<n;i++) for (int j=0;j<n;j++) {\n            int c = a[i][j];\n            if (forbidden[c]) b[i][j] = c;\n        }\n\n        // clear terminals\n        for (int c=1;c<=m;c++) terminals[c].clear();\n        stamp++;\n\n        // start terminals with mustKeepAllowed (terminals are mandatory for allowed colors)\n        for (int c=1;c<=m;c++) if (!forbidden[c]) {\n            for (int cell : mustKeepAllowed[c]) {\n                if (termStamp[c][cell] != stamp) {\n                    termStamp[c][cell] = stamp;\n                    terminals[c].push_back(cell);\n                }\n            }\n        }\n\n        // choose representative edge for each allowed-allowed adjacent pair (biased to endpoints already in mustKeep)\n        for (auto [x,y] : adjPairs) {\n            auto &vec = repEdges[x][y];\n            if (vec.empty()) { stamp += 1; break; }\n\n            int bestScore = -1;\n            vector<pair<int,int>> cand;\n            cand.reserve(vec.size());\n            for (auto &e : vec) {\n                int id_x = e.first;\n                int id_y = e.second;\n                int sx = (termStamp[x][id_x] == stamp ? 1 : 0);\n                int sy = (termStamp[y][id_y] == stamp ? 1 : 0);\n                int s = sx + sy;\n                if (s > bestScore) {\n                    bestScore = s;\n                    cand.clear();\n                    cand.push_back(e);\n                } else if (s == bestScore) {\n                    cand.push_back(e);\n                }\n            }\n            auto e = cand[(size_t)(rng() % cand.size())];\n            int id_x = e.first, id_y = e.second;\n\n            if (termStamp[x][id_x] != stamp) { termStamp[x][id_x] = stamp; terminals[x].push_back(id_x); }\n            if (termStamp[y][id_y] != stamp) { termStamp[y][id_y] = stamp; terminals[y].push_back(id_y); }\n        }\n\n        // choose one boundary tile for each allowed color (to ensure adjacency with 0 exists)\n        for (int c=1;c<=m;c++) if (!forbidden[c]) {\n            if (boundaryCells[c].empty()) continue; // should not happen because c allowed implies boundary touch\n\n            // if terminal core exists, choose boundary closest to an existing terminal (within c-region)\n            if (!terminals[c].empty()) {\n                int seed0 = terminals[c][(size_t)(rng()%terminals[c].size())];\n                vector<int> dist(N);\n                bfsDist(c, seed0, dist);\n\n                int bestDist = INT_MAX;\n                vector<int> candidates;\n                for (int bd : boundaryCells[c]) {\n                    if (dist[bd] == -1) continue;\n                    if (dist[bd] < bestDist) {\n                        bestDist = dist[bd];\n                        candidates.clear();\n                        candidates.push_back(bd);\n                    } else if (dist[bd] == bestDist) {\n                        candidates.push_back(bd);\n                    }\n                }\n                int chosen = candidates.empty()\n                              ? boundaryCells[c][(size_t)(rng()%boundaryCells[c].size())]\n                              : candidates[(size_t)(rng()%candidates.size())];\n                if (termStamp[c][chosen] != stamp) {\n                    termStamp[c][chosen] = stamp;\n                    terminals[c].push_back(chosen);\n                }\n            } else {\n                int chosen = boundaryCells[c][(size_t)(rng()%boundaryCells[c].size())];\n                if (termStamp[c][chosen] != stamp) {\n                    termStamp[c][chosen] = stamp;\n                    terminals[c].push_back(chosen);\n                }\n            }\n        }\n\n        // Build allowed colors using MST-steiner over terminal components\n        // (terminals[c] may be empty only if touchOutside but something went wrong; we ensure boundary seed above)\n        bool fail = false;\n        for (int c=1;c<=m;c++) if (!forbidden[c]) {\n            if (terminals[c].empty()) { fail = true; break; }\n            // apply Steiner kept region for this color\n            buildSteinerForColor(c, terminals[c], b);\n        }\n        if (fail) continue;\n\n        // 0-connectivity repair: restore enclosed 0 holes and reconnect affected colors\n        for (int iter = 0; iter < 12; iter++) {\n            int M2 = n + 2;\n            auto idExt = [&](int x,int y){ return x*M2 + y; };\n            vector<unsigned char> vis0(M2*M2, 0);\n            queue<pair<int,int>> q;\n            vis0[idExt(0,0)] = 1;\n            q.push({0,0});\n            while(!q.empty()) {\n                auto [x,y] = q.front(); q.pop();\n                for (auto &d : DIRS) {\n                    int nx = x + d[0], ny = y + d[1];\n                    if (nx<0||nx>=M2||ny<0||ny>=M2) continue;\n                    bool pass;\n                    if (nx==0||nx==M2-1||ny==0||ny==M2-1) pass = true;\n                    else pass = (b[nx-1][ny-1] == 0);\n                    if (!pass) continue;\n                    int nid = idExt(nx,ny);\n                    if (!vis0[nid]) { vis0[nid]=1; q.push({nx,ny}); }\n                }\n            }\n\n            vector<unsigned char> changed(m+1, 0);\n            bool anyHole = false;\n            for (int i=0;i<n;i++) for (int j=0;j<n;j++) {\n                if (b[i][j] == 0 && !vis0[idExt(i+1,j+1)]) {\n                    anyHole = true;\n                    int c = a[i][j];\n                    b[i][j] = c;         // restore original\n                    if (!forbidden[c]) changed[c] = 1; // only allowed colors should be affected\n                }\n            }\n            if (!anyHole) break;\n\n            for (int c=1;c<=m;c++) if (changed[c]) {\n                connectColorMST(b, c);\n            }\n        }\n\n        if (!checkAll(b)) continue;\n\n        int z = computeZero(b);\n        if (bestZero == -1 || z > bestZero) {\n            bestZero = z;\n            best = std::move(b);\n        }\n    }\n\n    // If somehow no improvement, output original (always legal)\n    if (bestZero < 0) best = a;\n\n    for (int i=0;i<n;i++){\n        for (int j=0;j<n;j++){\n            if (j) cout << ' ';\n            cout << best[i][j];\n        }\n        cout << '\\n';\n    }\n    return 0;\n}","ahc025":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Judge {\n    int N, D, Q;\n    int used = 0;\n    vector<vector<int8_t>> memo; // 2=unknown, -1/0/+1 known for singleton i vs j\n\n    Judge(int n, int d, int q) : N(n), D(d), Q(q) {\n        memo.assign(N, vector<int8_t>(N, 2));\n    }\n\n    int doQuery(const vector<int>& L, const vector<int>& R) {\n        // L and R must be non-empty, disjoint\n        used++;\n        cout << (int)L.size() << ' ' << (int)R.size();\n        for (int x : L) cout << ' ' << x;\n        for (int x : R) cout << ' ' << x;\n        cout << '\\n' << flush;\n\n        string s;\n        cin >> s;\n        char c = s[0];\n        if (c == '<') return -1;\n        if (c == '>') return 1;\n        return 0; // '='\n    }\n\n    int cmpSingleton(int i, int j) {\n        if (i == j) return 0;\n        int8_t &m = memo[i][j];\n        if (m != 2) return (int)m;\n        vector<int> L{ i }, R{ j };\n        int s = doQuery(L, R);\n        m = (int8_t)s;\n        memo[j][i] = (int8_t)(-s);\n        return s;\n    }\n\n    // A and B must be non-empty and disjoint\n    int cmpSets(const vector<int>& A, const vector<int>& B) {\n        if (A.empty() || B.empty()) return 0;\n        return doQuery(A, B);\n    }\n};\n\nstatic int ceil_log2_int(int x) {\n    int b = 0, v = 1;\n    while (v < x) { v <<= 1; b++; }\n    return b;\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    Judge judge(N, D, Q);\n\n    // --- Parameters for estimation from generator distribution ---\n    const double lambda = 1e-5;\n    const double cap = 1e5 * (double)N / (double)D;\n\n    auto estimateFromBucket = [&](int bucket, int Kp) -> double {\n        // bucket in [0..Kp]\n        // Use p=(bucket+0.5)/(Kp+1) as in earlier stable heuristic.\n        double p = (bucket + 0.5) / (double)(Kp + 1);\n        p = min(max(p, 1e-12), 1.0 - 1e-12);\n        double x = -log(1.0 - p) / lambda;\n        x = max(1.0, min(cap, x));\n        return x;\n    };\n\n    // --- Choose Kp under a budget for ordering info ---\n    auto chooseKp = [&]() -> int {\n        long long orderingBudget = (long long)(0.55L * (long long)Q);\n        int maxKp = min(24, N);\n\n        int best = 1;\n        for (int Kp = 1; Kp <= maxKp; Kp++) {\n            long long sortCost = 1LL * Kp * (Kp - 1) / 2; // worst-case insertion sort\n            long long itemCost = 1LL * (N - Kp) * ceil_log2_int(Kp + 1);\n            long long cost = sortCost + itemCost;\n            if (cost <= orderingBudget) best = Kp;\n            else break;\n        }\n        return best;\n    };\n\n    int Kp = chooseKp();\n\n    // --- Pick pivots and sort them by singleton comparisons ---\n    uint64_t seed = 712367821ULL ^ (uint64_t)N * 1000003ULL ^ (uint64_t)D * 9176ULL ^ (uint64_t)Q * 1237ULL;\n    mt19937_64 rng(seed);\n\n    vector<int> ids(N);\n    iota(ids.begin(), ids.end(), 0);\n    shuffle(ids.begin(), ids.end(), rng);\n    vector<int> pivots(ids.begin(), ids.begin() + Kp);\n\n    // insertion sort ascending\n    for (int i = 1; i < Kp; i++) {\n        int j = i;\n        while (j > 0) {\n            int s = judge.cmpSingleton(pivots[j], pivots[j - 1]); // piv[j] ? piv[j-1]\n            if (s == -1) {\n                swap(pivots[j], pivots[j - 1]); // piv[j] < piv[j-1]\n                j--;\n            } else break;\n            if (judge.used >= Q) break;\n        }\n        if (judge.used >= Q) break;\n    }\n\n    vector<int> pivotPos(N, -1);\n    for (int i = 0; i < Kp; i++) pivotPos[pivots[i]] = i;\n\n    // --- Estimate weights by pivot bucketization ---\n    vector<int> bucket(N, Kp / 2);\n    vector<double> w_est(N, 1.0);\n\n    // pivots\n    for (int p : pivots) {\n        int pos = pivotPos[p];\n        bucket[p] = pos;\n        w_est[p] = estimateFromBucket(pos, Kp);\n    }\n\n    // non-pivots: k = #pivots strictly less than item\n    for (int item = 0; item < N; item++) {\n        if (pivotPos[item] != -1) continue;\n\n        int lo = 0, hi = Kp;\n        while (lo < hi && judge.used < Q) {\n            int mid = (lo + hi) / 2;\n            int s = judge.cmpSingleton(item, pivots[mid]); // item ? piv[mid]\n            if (s == 1) lo = mid + 1;\n            else hi = mid;\n        }\n        int k = lo;\n        bucket[item] = k;\n        w_est[item] = estimateFromBucket(k, Kp);\n    }\n\n    // --- Initial partition: LPT (place largest estimated into smallest bin) ---\n    vector<int> order(N);\n    iota(order.begin(), order.end(), 0);\n    sort(order.begin(), order.end(), [&](int a, int b) {\n        if (w_est[a] != w_est[b]) return w_est[a] > w_est[b];\n        return a < b;\n    });\n\n    vector<vector<int>> bins(D);\n    vector<double> binSumEst(D, 0.0);\n    vector<int> d_i(N, 0), posInBin(N, -1);\n\n    for (int x : order) {\n        int best = 0;\n        for (int b = 1; b < D; b++) if (binSumEst[b] < binSumEst[best]) best = b;\n        d_i[x] = best;\n        posInBin[x] = (int)bins[best].size();\n        bins[best].push_back(x);\n        binSumEst[best] += w_est[x];\n    }\n\n    // --- Local refinement ---\n    double totalEst = 0;\n    for (double v : w_est) totalEst += v;\n    double meanEst = totalEst / (double)D;\n\n    auto moveItem = [&](int x, int from, int to) {\n        int idx = posInBin[x];\n        auto &vf = bins[from];\n        int y = vf.back();\n        vf[idx] = y;\n        posInBin[y] = idx;\n        vf.pop_back();\n\n        bins[to].push_back(x);\n        posInBin[x] = (int)bins[to].size() - 1;\n\n        d_i[x] = to;\n        binSumEst[from] -= w_est[x];\n        binSumEst[to] += w_est[x];\n    };\n\n    int maxIters = 0;\n    if (Q > judge.used) maxIters = min(800, Q - judge.used); // 1 query/iter\n    for (int it = 0; it < maxIters && judge.used < Q; it++) {\n        // choose light bin (min estimated sum) among non-empty bins\n        int light = -1;\n        for (int b = 0; b < D; b++) {\n            if (bins[b].empty()) continue;\n            if (light == -1 || binSumEst[b] < binSumEst[light]) light = b;\n        }\n        // choose heavy bin (max estimated sum) among bins with size>=2 (avoid emptying)\n        int heavy = -1;\n        for (int b = 0; b < D; b++) {\n            if ((int)bins[b].size() < 2) continue;\n            if (heavy == -1 || binSumEst[b] > binSumEst[heavy]) heavy = b;\n        }\n        if (light == -1 || heavy == -1) break;\n        if (heavy == light) break;\n\n        // verify direction using one balance query\n        // want heavy.actual >= light.actual\n        int s = judge.cmpSets(bins[heavy], bins[light]);\n        if (s == -1) {\n            // swap roles only if it doesn't break the size>=2 condition\n            if ((int)bins[light].size() >= 2) swap(heavy, light);\n            else break;\n        }\n        if ((int)bins[heavy].size() < 2) break;\n\n        // choose x in heavy that minimizes estimated delta-variance\n        double devH = binSumEst[heavy] - meanEst;\n        double devL = binSumEst[light] - meanEst;\n\n        int bestX = -1;\n        double bestDelta = 0; // we require negative delta (improvement)\n        for (int x : bins[heavy]) {\n            double w = w_est[x];\n            double newDevH = devH - w;\n            double newDevL = devL + w;\n            double oldObj = devH * devH + devL * devL;\n            double newObj = newDevH * newDevH + newDevL * newDevL;\n            double delta = newObj - oldObj;\n\n            if (bestX == -1 || delta < bestDelta) {\n                bestDelta = delta;\n                bestX = x;\n            }\n        }\n\n        if (bestX == -1) break;\n        if (bestDelta >= -1e-9) break; // no estimated improvement\n\n        moveItem(bestX, heavy, light);\n    }\n\n    // --- Use remaining queries (dummy) ---\n    while (judge.used < Q) {\n        // valid disjoint non-empty sets: {0}, {1}\n        int a = 0, b = 1;\n        if (a == b) b = (b + 1) % N;\n        if (b == a) b = (a + 1) % N;\n        vector<int> L{a}, R{b};\n        judge.doQuery(L, R);\n    }\n\n    // --- Output division ---\n    for (int i = 0; i < N; i++) {\n        if (i) cout << ' ';\n        cout << d_i[i];\n    }\n    cout << '\\n' << flush;\n    return 0;\n}","ahc026":"#include <bits/stdc++.h>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int n, m;\n    cin >> n >> m;\n    vector<vector<int>> st(m);\n    for (int i = 0; i < m; i++) {\n        st[i].resize(n / m);\n        for (int j = 0; j < n / m; j++) cin >> st[i][j];\n    }\n\n    vector<int> posStack(n + 1, -1), posIndex(n + 1, -1);\n    for (int i = 0; i < m; i++) {\n        for (int j = 0; j < (int)st[i].size(); j++) {\n            int x = st[i][j];\n            posStack[x] = i;\n            posIndex[x] = j;\n        }\n    }\n\n    vector<pair<int,int>> ops; // (v, i) where i=0 for op2\n    ops.reserve(5000);\n\n    const int INF = 1e9;\n\n    for (int v = 1; v <= n; v++) {\n        int s = posStack[v];\n        int idx = posIndex[v];\n\n        // v is already on top\n        if (idx == (int)st[s].size() - 1) {\n            ops.emplace_back(v, 0);\n            st[s].pop_back();\n            posStack[v] = -1;\n            posIndex[v] = -1;\n            continue;\n        }\n\n        // Need to move the chunk starting from the box immediately above v\n        int u = st[s][idx + 1];\n        vector<int> S(st[s].begin() + (idx + 1), st[s].end()); // moved boxes\n\n        int bestDest = -1;\n        // lexicographic key we construct as tuple<int,int,int>\n        // For inv==0: key = (0, minD, sizeD)  (minD smaller better)\n        // Else:        key = (inv, -minD, sizeD) (minD larger better via -minD)\n        tuple<int,int,int> bestKey;\n\n        for (int d = 0; d < m; d++) if (d != s) {\n            // inversion count between D and S: count pairs (x in D, y in S) with x < y\n            int inv = 0;\n            const auto &D = st[d];\n            for (int x : D) {\n                for (int y : S) {\n                    if (x < y) inv++;\n                }\n            }\n\n            int minD = INF;\n            if (!D.empty()) {\n                minD = *min_element(D.begin(), D.end());\n            }\n\n            int sizeD = (int)D.size();\n\n            tuple<int,int,int> key;\n            if (inv == 0) {\n                // fully safe (or empty destination)\n                key = {0, minD, sizeD};\n            } else {\n                key = {inv, -minD, sizeD};\n            }\n\n            if (bestDest == -1 || key < bestKey) {\n                bestDest = d;\n                bestKey = key;\n            }\n        }\n\n        // Operation 1: move box u (= S[0] bottom) and all above to destination bestDest\n        ops.emplace_back(u, bestDest + 1);\n\n        int startDest = (int)st[bestDest].size();\n        // append S to destination and update positions\n        for (int j = 0; j < (int)S.size(); j++) {\n            int y = S[j];\n            st[bestDest].push_back(y);\n            posStack[y] = bestDest;\n            posIndex[y] = startDest + j;\n        }\n        // remove S from source (suffix after idx)\n        st[s].erase(st[s].begin() + (idx + 1), st[s].end());\n\n        // Now v must be on top of source, carry it out\n        ops.emplace_back(v, 0);\n        st[s].pop_back();\n        posStack[v] = -1;\n        posIndex[v] = -1;\n    }\n\n    // Safety check\n    if ((int)ops.size() > 5000) return 0;\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 RNG {\n    uint64_t x;\n    explicit RNG(uint64_t seed) : x(seed) {}\n    uint64_t next_u64() {\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 next_int(int l, int r) { // inclusive\n        return l + (int)(next_u64() % (uint64_t)(r - l + 1));\n    }\n    double next_double(double l, double r) { // [l, r)\n        long double t = (long double)next_u64() / (long double)numeric_limits<uint64_t>::max();\n        return (double)((long double)l + t * (long double)(r - l));\n    }\n};\n\nstatic inline char dirChar(int N, int a, int b) {\n    int ai = a / N, aj = a % N;\n    int bi = b / N, bj = b % N;\n    if (bi == ai + 1 && bj == aj) return 'D';\n    if (bi == ai - 1 && bj == aj) return 'U';\n    if (bi == ai && bj == aj + 1) return 'R';\n    if (bi == ai && bj == aj - 1) return 'L';\n    return '?';\n}\n\nstruct EvalState {\n    long long numer; // sum_{t=L}^{2L-1} S_t\n    int L;\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(max(0, N - 1));\n    for (int i = 0; i < N - 1; i++) cin >> h[i];\n    vector<string> v(N);\n    for (int i = 0; i < N; i++) cin >> v[i];\n\n    int V = N * N;\n    vector<int> d(V);\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) cin >> d[i * N + j];\n    }\n\n    auto idx = [&](int i, int j) { return i * N + j; };\n    const int root = 0;\n\n    // Build adjacency graph (respecting walls)\n    vector<vector<int>> g(V);\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            int a = idx(i, j);\n            if (i + 1 < N && h[i][j] == '0') {\n                int b = idx(i + 1, j);\n                g[a].push_back(b);\n                g[b].push_back(a);\n            }\n            if (j + 1 < N && v[i][j] == '0') {\n                int b = idx(i, j + 1);\n                g[a].push_back(b);\n                g[b].push_back(a);\n            }\n        }\n    }\n\n    // BFS distances from root\n    vector<int> dist(V, -1);\n    queue<int> q;\n    dist[root] = 0;\n    q.push(root);\n    while (!q.empty()) {\n        int x = q.front(); q.pop();\n        for (int y : g[x]) if (dist[y] == -1) {\n            dist[y] = dist[x] + 1;\n            q.push(y);\n        }\n    }\n\n    // Candidate parents: neighbors with dist-1\n    vector<vector<int>> candParents(V);\n    for (int x = 0; x < V; x++) {\n        if (x == root) continue;\n        int dx = dist[x];\n        for (int y : g[x]) if (dist[y] == dx - 1) candParents[x].push_back(y);\n        if (candParents[x].empty()) candParents[x].push_back(root); // safety\n    }\n\n    vector<int> verts(V);\n    iota(verts.begin(), verts.end(), 0);\n    // deep-to-shallow order for subtree DP\n    sort(verts.begin(), verts.end(), [&](int a, int b) { return dist[a] > dist[b]; });\n\n    long long sum_d = 0;\n    for (int x : d) sum_d += x;\n\n    int L0 = 2 * (V - 1);\n\n    // Fast exact evaluation of average dirtiness:\n    // given pos array of length L (pos[k] = vertex moved into after k+1-th move in the cycle)\n    // compute numer = sum_{t=L}^{2L-1} S_t where S_t = total dirtiness at time t.\n    vector<int> last(V, 0), seen(V, 0);\n    int seen_id = 1;\n\n    auto evalByPos = [&](auto getPos, int L) -> EvalState {\n        // getPos(k) for 0 <= k < L\n        seen_id++;\n        if (seen_id == INT_MAX) {\n            fill(seen.begin(), seen.end(), 0);\n            seen_id = 1;\n        }\n\n        long long numer = 0;\n        long long sum_d_last = 0;\n\n        int T = 2 * L - 1;\n        for (int t = 1; t <= T; t++) {\n            int idxPos = (t - 1) % L;\n            int vv = getPos(idxPos);\n\n            int old = 0;\n            if (seen[vv] == seen_id) old = last[vv];\n            else seen[vv] = seen_id;\n\n            last[vv] = t;\n            sum_d_last += 1LL * d[vv] * (t - old);\n\n            long long S = 1LL * t * sum_d - sum_d_last;\n            if (t >= L) numer += S;\n        }\n        return {numer, L};\n    };\n\n    auto betterAvg = [&](const EvalState& A, const EvalState& B) -> bool {\n        // A.numer/A.L < B.numer/B.L\n        __int128 left = (__int128)A.numer * B.L;\n        __int128 right = (__int128)B.numer * A.L;\n        return left < right;\n    };\n\n    auto buildBase = [&](const vector<int>& parent, vector<vector<int>>& childrenOrder,\n                         vector<int>& basePos, string& baseMoves) {\n        for (int i = 0; i < V; i++) childrenOrder[i].clear();\n\n        for (int x = 0; x < V; x++) if (x != root) {\n            childrenOrder[parent[x]].push_back(x);\n        }\n\n        // already ordered by caller\n        basePos.clear();\n        baseMoves.clear();\n        basePos.reserve(L0);\n        baseMoves.reserve(L0);\n\n        // iterative DFS Euler tour on the tree\n        vector<pair<int,int>> st;\n        st.reserve(V);\n        st.push_back({root, 0});\n\n        while (!st.empty()) {\n            int u = st.back().first;\n            int &it = st.back().second;\n            if (it == (int)childrenOrder[u].size()) {\n                st.pop_back();\n                if (st.empty()) break;\n                int p = parent[u];\n                baseMoves.push_back(dirChar(N, u, p));\n                basePos.push_back(p);\n            } else {\n                int c = childrenOrder[u][it++];\n                baseMoves.push_back(dirChar(N, u, c));\n                basePos.push_back(c);\n                st.push_back({c, 0});\n            }\n        }\n        // basePos.size() should be L0\n        // (tree has V nodes => Euler tour length 2*(V-1))\n    };\n\n    // Random search for best base tree & child order\n    RNG rng((uint64_t)chrono::steady_clock::now().time_since_epoch().count());\n\n    vector<int> parent(V, -1);\n    vector<vector<int>> childrenOrder(V);\n\n    EvalState bestBase{(1LL<<62), L0};\n    vector<int> bestBasePos;\n    string bestBaseMoves;\n    vector<int> bestParent;\n    vector<vector<int>> bestChildrenOrder;\n\n    auto start = chrono::steady_clock::now();\n    double TIME_BASE = 1.25;\n\n    auto chooseParent = [&](int x, double alpha, double greedyProb) {\n        // candParents[x] are all dist-1 neighbors\n        auto &cp = candParents[x];\n        if (cp.empty()) return root;\n        if (rng.next_double(0.0, 1.0) < greedyProb) {\n            int best = cp[0];\n            for (int u : cp) if (d[u] > d[best]) best = u;\n            return best;\n        } else {\n            // weight ~ d[u]^alpha\n            double total = 0;\n            vector<double> w(cp.size());\n            for (int i = 0; i < (int)cp.size(); i++) {\n                w[i] = pow((double)d[cp[i]], alpha);\n                total += w[i];\n            }\n            double r = rng.next_double(0.0, total);\n            for (int i = 0; i < (int)cp.size(); i++) {\n                r -= w[i];\n                if (r <= 0) return cp[i];\n            }\n            return cp.back();\n        }\n    };\n\n    while (true) {\n        double elapsed = chrono::duration<double>(chrono::steady_clock::now() - start).count();\n        if (elapsed > TIME_BASE) break;\n\n        double alpha = rng.next_double(0.6, 2.2);\n        double greedyProb = rng.next_double(0.75, 0.98);\n        int orderType = rng.next_int(0, 2); // 0 subMax, 1 subSum, 2 d(child)\n        bool ascending = rng.next_int(0, 1);\n        double noiseRate = rng.next_double(0.0, 0.28);\n\n        // build parent\n        parent[root] = -1;\n        vector<int> byDistAsc = verts;\n        sort(byDistAsc.begin(), byDistAsc.end(), [&](int a, int b){ return dist[a] < dist[b]; });\n        for (int x : byDistAsc) {\n            if (x == root) continue;\n            parent[x] = chooseParent(x, alpha, greedyProb);\n        }\n\n        // build children lists (unsorted)\n        vector<vector<int>> children(V);\n        for (int i = 0; i < V; i++) children[i].clear();\n        for (int x = 0; x < V; x++) if (x != root) children[parent[x]].push_back(x);\n\n        // subtree DP\n        vector<long long> subMax(V), subSum(V);\n        for (int x : verts) { // deep -> shallow\n            subMax[x] = d[x];\n            subSum[x] = d[x];\n            for (int c : children[x]) {\n                subMax[x] = max(subMax[x], subMax[c]);\n                subSum[x] += subSum[c];\n            }\n        }\n\n        // order children\n        childrenOrder.assign(V, {});\n        for (int u = 0; u < V; u++) {\n            auto &ch = children[u];\n            childrenOrder[u] = ch;\n\n            if (ch.size() <= 1) continue;\n            vector<pair<double,int>> tmp;\n            tmp.reserve(ch.size());\n            for (int c : ch) {\n                double key;\n                if (orderType == 0) key = (double)subMax[c];\n                else if (orderType == 1) key = (double)subSum[c];\n                else key = (double)d[c];\n\n                double sign = rng.next_double(-1.0, 1.0);\n                double adj = key + noiseRate * key * sign;\n                tmp.push_back({adj, c});\n            }\n            sort(tmp.begin(), tmp.end(), [&](auto &A, auto &B) {\n                if (A.first != B.first) return ascending ? (A.first < B.first) : (A.first > B.first);\n                return A.second < B.second;\n            });\n            for (int i = 0; i < (int)ch.size(); i++) childrenOrder[u][i] = tmp[i].second;\n        }\n\n        // build base route\n        vector<int> basePos;\n        string baseMoves;\n        basePos.reserve(L0);\n        baseMoves.reserve(L0);\n\n        buildBase(parent, childrenOrder, basePos, baseMoves);\n        if ((int)basePos.size() != L0) continue; // safety\n\n        auto getPos = [&](int k) -> int { return basePos[k]; };\n        auto val = evalByPos(getPos, L0);\n\n        if (betterAvg(val, bestBase)) {\n            bestBase = val;\n            bestBasePos = std::move(basePos);\n            bestBaseMoves = std::move(baseMoves);\n            bestParent = parent;\n            bestChildrenOrder = childrenOrder;\n        }\n    }\n\n    // Extension search on top edges with consistent evaluation/output\n    int maxLen = 100000;\n    int baseL = L0;\n\n    // compute depth in best base tree\n    vector<int> depthTree(V, 0);\n    vector<int> byDistAsc = verts;\n    sort(byDistAsc.begin(), byDistAsc.end(), [&](int a, int b){ return dist[a] < dist[b]; });\n    depthTree[root] = 0;\n    for (int x : byDistAsc) {\n        if (x == root) continue;\n        depthTree[x] = depthTree[bestParent[x]] + 1;\n    }\n\n    // list undirected edges\n    vector<pair<int,int>> edges;\n    edges.reserve(V * 2);\n    for (int u = 0; u < V; u++) for (int w : g[u]) if (u < w) edges.push_back({u,w});\n\n    // edge ranking by potential shuttle value / overhead\n    struct EdgeCand { double score; int u,v; };\n    vector<EdgeCand> edgeC;\n    edgeC.reserve(edges.size());\n    for (auto [a,b] : edges) {\n        double best = max(\n            (double)(d[a] + d[b]) / (double)(depthTree[a] + depthTree[b] + 1),\n            (double)(d[a] + d[b]) / (double)(depthTree[a] + depthTree[b] + 1)\n        );\n        edgeC.push_back({best, a, b});\n    }\n    sort(edgeC.begin(), edgeC.end(), [&](auto &A, auto &B){ return A.score > B.score; });\n    int TOP_E = min<int>(30, edgeC.size());\n\n    EvalState bestAll = bestBase;\n    string bestAllRoute = bestBaseMoves;\n\n    auto buildChainRootTo = [&](int x) {\n        vector<int> chain;\n        int cur = x;\n        while (cur != root) {\n            chain.push_back(cur);\n            cur = bestParent[cur];\n        }\n        reverse(chain.begin(), chain.end());\n        return chain; // excludes root\n    };\n\n    // Build segment pos for a given s,t,m where:\n    // - start at root, go along tree to s\n    // - shuttle along edge (s,t) for m moves\n    // - then return from current end (depends on parity of m) to root along the tree\n    auto buildSegmentPos = [&](int s, int t, int m, vector<int>& segPos) {\n        segPos.clear();\n        segPos.reserve(depthTree[s] + m + max(depthTree[s], depthTree[t]));\n\n        // root -> s\n        int cur = root;\n        auto chainS = buildChainRootTo(s);\n        for (int nxt : chainS) {\n            segPos.push_back(nxt); // moved into nxt\n            cur = nxt;\n        }\n        // now at s\n        int curV = s;\n        for (int i = 0; i < m; i++) {\n            int nxt = (curV == s ? t : s);\n            segPos.push_back(nxt);\n            curV = nxt;\n        }\n        // return curV -> root via tree parents\n        while (curV != root) {\n            int nxt = bestParent[curV];\n            segPos.push_back(nxt);\n            curV = nxt;\n        }\n    };\n\n    // Evaluate full route consisting of basePos + segPos without allocating combined array.\n    auto evalFull = [&](const vector<int>& segPos) -> EvalState {\n        int segL = (int)segPos.size();\n        int L = baseL + segL;\n\n        auto getPos = [&](int k) -> int {\n            if (k < baseL) return bestBasePos[k];\n            return segPos[k - baseL];\n        };\n        return evalByPos(getPos, L);\n    };\n\n    auto buildSegmentMoves = [&](int s, int t, int m) -> string {\n        string seg;\n        int cur = root;\n\n        auto chainS = buildChainRootTo(s);\n        for (int nxt : chainS) {\n            seg.push_back(dirChar(N, cur, nxt));\n            cur = nxt;\n        }\n        int curV = s;\n        for (int i = 0; i < m; i++) {\n            int nxt = (curV == s ? t : s);\n            seg.push_back(dirChar(N, curV, nxt));\n            curV = nxt;\n        }\n        while (curV != root) {\n            int nxt = bestParent[curV];\n            seg.push_back(dirChar(N, curV, nxt));\n            curV = nxt;\n        }\n        return seg;\n    };\n\n    vector<int> segPos;\n    auto extStart = chrono::steady_clock::now();\n    double TIME_EXT = 0.70;\n\n    // Also consider k=0 already included as bestAll = bestBase\n    for (int ei = 0; ei < TOP_E; ei++) {\n        double elapsed = chrono::duration<double>(chrono::steady_clock::now() - extStart).count();\n        if (elapsed > TIME_EXT) break;\n\n        int u = edgeC[ei].u, vtx = edgeC[ei].v;\n        for (int ori = 0; ori < 2; ori++) {\n            int s = (ori == 0 ? u : vtx);\n            int t = (ori == 0 ? vtx : u);\n\n            // derive max m for even/odd end:\n            // - if m odd => end=t => total segLen = depth[s] + m + depth[t]\n            // - if m even => end=s => total segLen = depth[s] + m + depth[s] = 2*depth[s] + m\n            int oddMax = maxLen - baseL - depthTree[s] - depthTree[t]; // m must be odd and >=1\n            int evenMax = maxLen - baseL - 2 * depthTree[s];            // m must be even and >=2\n\n            vector<int> candidates;\n            auto addIf = [&](int m) {\n                if (m <= 0) return;\n                int end = (m % 2 ? t : s);\n                int segLen = depthTree[s] + m + depthTree[end];\n                if (baseL + segLen <= maxLen) candidates.push_back(m);\n            };\n\n            // near maxima\n            if (oddMax >= 1) {\n                int m = oddMax;\n                if (m % 2 == 0) m--;\n                if (m >= 1) {\n                    addIf(m);\n                    if (m - 2 >= 1) addIf(m - 2);\n                    if (m / 2 >= 1) addIf((m / 2) | 1); // make odd\n                }\n            }\n            if (evenMax >= 2) {\n                int m = evenMax;\n                if (m % 2 == 1) m--;\n                if (m >= 2) {\n                    addIf(m);\n                    if (m - 2 >= 2) addIf(m - 2);\n                    if (m / 2 >= 2) addIf((m / 2) & ~1); // make even\n                }\n            }\n\n            // small shuttles sometimes help\n            addIf(1);\n            addIf(2);\n            addIf(3);\n            addIf(4);\n\n            sort(candidates.begin(), candidates.end());\n            candidates.erase(unique(candidates.begin(), candidates.end()), candidates.end());\n\n            for (int m : candidates) {\n                // build segment pos\n                buildSegmentPos(s, t, m, segPos);\n                if ((int)segPos.size() + baseL > maxLen) continue;\n\n                auto val = evalFull(segPos);\n                if (betterAvg(val, bestAll)) {\n                    bestAll = val;\n                    bestAllRoute = bestBaseMoves + buildSegmentMoves(s, t, m);\n                }\n            }\n        }\n    }\n\n    // Output best route\n    cout << bestAllRoute << \"\\n\";\n    return 0;\n}","ahc028":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M;\n    cin >> N >> M;\n\n    int si, sj;\n    cin >> si >> sj;\n\n    vector<string> grid(N);\n    for (int i = 0; i < N; i++) cin >> grid[i];\n\n    vector<string> t(M);\n    for (int k = 0; k < M; k++) cin >> t[k];\n\n    auto idxOf = [N](int r, int c) { return r * N + c; };\n    auto coordOf = [N](int id) { return pair<int,int>{id / N, id % N}; };\n\n    int C = N * N;\n    int startCell = idxOf(si, sj);\n\n    vector<vector<int>> posByLetter(26);\n    for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) {\n        int a = grid[i][j] - 'A';\n        posByLetter[a].push_back(idxOf(i, j));\n    }\n\n    // dist between any two cells\n    vector<vector<int>> distCell(C, vector<int>(C, 0));\n    for (int a = 0; a < C; a++) {\n        auto [ar, ac] = coordOf(a);\n        for (int b = a; b < C; b++) {\n            auto [br, bc] = coordOf(b);\n            int d = abs(ar - br) + abs(ac - bc);\n            distCell[a][b] = distCell[b][a] = d;\n        }\n    }\n\n    // min dist from a cell to ANY cell containing given letter\n    vector<vector<int>> distCellToLetter(C, vector<int>(26, INT_MAX/4));\n    for (int p = 0; p < C; p++) {\n        for (int l = 0; l < 26; l++) {\n            int best = INT_MAX/4;\n            for (int q : posByLetter[l]) best = min(best, distCell[p][q]);\n            distCellToLetter[p][l] = best;\n        }\n    }\n\n    // min distance between any cell containing letter x and any cell containing y\n    vector<vector<int>> distLetter(26, vector<int>(26, INT_MAX/4));\n    for (int x = 0; x < 26; x++) for (int y = 0; y < 26; y++) {\n        int best = INT_MAX/4;\n        for (int p : posByLetter[x]) {\n            for (int q : posByLetter[y]) best = min(best, distCell[p][q]);\n        }\n        distLetter[x][y] = best;\n    }\n\n    vector<int> st(M), en(M);\n    for (int i = 0; i < M; i++) {\n        st[i] = t[i][0] - 'A';\n        en[i] = t[i][4] - 'A';\n    }\n\n    // overlapLen[i][j]: maximum r (0..4) such that suffix(t[i], r) == prefix(t[j], r)\n    vector<vector<uint8_t>> overlapLen(M, vector<uint8_t>(M, 0));\n    for (int i = 0; i < M; i++) for (int j = 0; j < M; j++) if (i != j) {\n        uint8_t best = 0;\n        for (int r = 4; r >= 0; r--) {\n            bool ok = true;\n            for (int k = 0; k < r; k++) {\n                if (t[i][5 - r + k] != t[j][k]) { ok = false; break; }\n            }\n            if (ok) { best = (uint8_t)r; break; }\n        }\n        overlapLen[i][j] = best;\n    }\n\n    vector<uint8_t> maxOverlapFrom(M, 0);\n    for (int i = 0; i < M; i++) {\n        uint8_t mx = 0;\n        for (int j = 0; j < M; j++) if (i != j) mx = max(mx, overlapLen[i][j]);\n        maxOverlapFrom[i] = mx;\n    }\n\n    // Build merged letter sequence from an order using overlaps.\n    auto buildSeq = [&](const vector<int>& order) -> vector<char> {\n        vector<char> seq;\n        seq.reserve(5 * M);\n        auto addStringFrom = [&](int idx, int fromPos) {\n            for (int p = fromPos; p < 5; p++) seq.push_back(t[idx][p]);\n        };\n        addStringFrom(order[0], 0);\n        for (int i = 1; i < M; i++) {\n            int prev = order[i-1], cur = order[i];\n            int r = overlapLen[prev][cur];\n            addStringFrom(cur, r);\n        }\n        return seq;\n    };\n\n    // Beam search simulation: minimize cost for the fixed letter sequence.\n    auto simulateBeam = [&](const vector<int>& order) -> pair<ll, vector<pair<int,int>>> {\n        vector<char> seq = buildSeq(order);\n        int L = (int)seq.size();\n\n        // beam width (small enough for speed, large enough to improve)\n        const int BEAM = 28;\n\n        vector<vector<int>> cellsAt(L);\n        vector<vector<int>> parentAt(L);\n        vector<vector<ll>> costAt(L);\n\n        // position 0\n        int l0 = seq[0] - 'A';\n        const vector<int>& cand0 = posByLetter[l0];\n\n        vector<tuple<ll,int,int>> vec; // cost, cell, parentIdx(-1)\n        vec.reserve(cand0.size());\n        for (int c : cand0) {\n            ll cost = (ll)distCell[startCell][c] + 1;\n            vec.emplace_back(cost, c, -1);\n        }\n        nth_element(vec.begin(), vec.begin() + min((int)vec.size(), BEAM) - 1, vec.end(),\n                    [](auto &a, auto &b){ return get<0>(a) < get<0>(b); });\n        int take0 = min((int)vec.size(), BEAM);\n        vec.resize(take0);\n        sort(vec.begin(), vec.end(), [](auto &a, auto &b){ return get<0>(a) < get<0>(b); });\n\n        cellsAt[0].resize(take0);\n        parentAt[0].assign(take0, -1);\n        costAt[0].resize(take0);\n        for (int i = 0; i < take0; i++) {\n            cellsAt[0][i] = get<1>(vec[i]);\n            costAt[0][i] = get<0>(vec[i]);\n        }\n\n        // forward DP\n        for (int pos = 1; pos < L; pos++) {\n            int l = seq[pos] - 'A';\n            const vector<int>& cand = posByLetter[l];\n\n            const auto &prevCells = cellsAt[pos-1];\n            const auto &prevCosts = costAt[pos-1];\n            int prevSz = (int)prevCells.size();\n\n            // compute best transition into each candidate cell\n            vector<tuple<ll,int,int>> bestForCand; // cost, cell, parentIdx\n            bestForCand.reserve(cand.size());\n\n            for (int c : cand) {\n                ll best = (1LL<<62);\n                int bestParent = -1;\n                // min over beam states\n                for (int pi = 0; pi < prevSz; pi++) {\n                    ll v = prevCosts[pi] + (ll)distCell[prevCells[pi]][c] + 1;\n                    if (v < best) {\n                        best = v;\n                        bestParent = pi;\n                    }\n                }\n                bestForCand.emplace_back(best, c, bestParent);\n            }\n\n            int take = min((int)bestForCand.size(), BEAM);\n            // select top-k by cost\n            nth_element(bestForCand.begin(), bestForCand.begin() + take - 1, bestForCand.end(),\n                        [](auto &a, auto &b){ return get<0>(a) < get<0>(b); });\n            bestForCand.resize(take);\n            sort(bestForCand.begin(), bestForCand.end(), [](auto &a, auto &b){ return get<0>(a) < get<0>(b); });\n\n            cellsAt[pos].resize(take);\n            parentAt[pos].resize(take);\n            costAt[pos].resize(take);\n            for (int i = 0; i < take; i++) {\n                cellsAt[pos][i] = get<1>(bestForCand[i]);\n                parentAt[pos][i] = get<2>(bestForCand[i]);\n                costAt[pos][i] = get<0>(bestForCand[i]);\n            }\n        }\n\n        // choose best end\n        int idx = (int)(min_element(costAt[L-1].begin(), costAt[L-1].end()) - costAt[L-1].begin());\n        ll bestCost = costAt[L-1][idx];\n\n        // reconstruct chosen cells\n        vector<int> chosenCells(L);\n        int curIdx = idx;\n        for (int pos = L-1; pos >= 0; pos--) {\n            chosenCells[pos] = cellsAt[pos][curIdx];\n            curIdx = parentAt[pos][curIdx];\n            if (pos == 0) break;\n        }\n\n        vector<pair<int,int>> ops;\n        ops.reserve(L);\n        for (int pos = 0; pos < L; pos++) ops.push_back(coordOf(chosenCells[pos]));\n        return {bestCost, ops};\n    };\n\n    // Candidate starting strings: use a slightly deeper proxy (first+second letter)\n    vector<pair<int,int>> startCand; // (proxy, idx)\n    startCand.reserve(M);\n    for (int i = 0; i < M; i++) {\n        int lStart = st[i];\n        int lSecond = t[i][1] - 'A';\n\n        ll proxy = (1LL<<62);\n        for (int c : posByLetter[lStart]) {\n            // move to c for first char, then minimal move to any cell of second char\n            ll v = distCell[startCell][c] + (ll)distCellToLetter[c][lSecond] + 1;\n            proxy = min(proxy, v);\n        }\n        startCand.push_back({(int)min<ll>(proxy, INT_MAX), i});\n    }\n    sort(startCand.begin(), startCand.end());\n\n    // More restarts but still bounded by time\n    int RESTARTS = 10;\n\n    // Random tie-breaking helper\n    std::mt19937 rng(712367);\n\n    ll bestCost = (1LL<<62);\n    vector<pair<int,int>> bestOps;\n\n    for (int rep = 0; rep < RESTARTS; rep++) {\n        int startIdx = startCand[rep].second;\n\n        vector<int> order;\n        order.reserve(M);\n\n        vector<char> used(M, 0);\n        order.push_back(startIdx);\n        used[startIdx] = 1;\n\n        int cur = startIdx;\n\n        for (int step = 1; step < M; step++) {\n            int bestR = -1;\n            int bestMx = -1;\n            int bestD = INT_MAX;\n\n            // First gather best by lexicographic-like criteria:\n            // 1) overlapLen[cur][j] (higher better)\n            // 2) dist between letters en[cur] -> st[j] (lower better)\n            // 3) maxOverlapFrom[j] (higher better)\n            vector<int> cand;\n            for (int j = 0; j < M; j++) if (!used[j]) {\n                int r = overlapLen[cur][j];\n                int d = distLetter[en[cur]][st[j]];\n                int mx = (int)maxOverlapFrom[j];\n                if (r > bestR ||\n                    (r == bestR && d < bestD) ||\n                    (r == bestR && d == bestD && mx > bestMx)) {\n                    bestR = r; bestD = d; bestMx = mx;\n                    cand.clear();\n                    cand.push_back(j);\n                } else if (r == bestR && d == bestD && mx == bestMx) {\n                    cand.push_back(j);\n                }\n            }\n\n            // Randomly pick among equally good candidates to diversify\n            int pick = cand.empty() ? -1 : cand[rng() % cand.size()];\n            used[pick] = 1;\n            order.push_back(pick);\n            cur = pick;\n        }\n\n        auto [cost, ops] = simulateBeam(order);\n        if ((int)ops.size() > 5000) continue; // safety\n        if (cost < bestCost) {\n            bestCost = cost;\n            bestOps = std::move(ops);\n        }\n    }\n\n    for (auto [i, j] : bestOps) cout << i << ' ' << j << '\\n';\n    return 0;\n}","ahc030":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic long double Phi(long double z) {\n    return 0.5L * (1.0L + erf(z / sqrtl(2.0L)));\n}\n\n// Posterior mean E[v | r] with a uniform prior over v=0..vmax.\n// v is the true sum of oil reserves in the queried k cells.\nstatic long double posteriorMeanV(int k, long long r, long double eps,\n                                   int M, long long totalOil) {\n    long double alpha = 1.0L - 2.0L * eps; // mu = k*eps + v*alpha\n    long double sigma2 = (long double)k * eps * (1.0L - eps);\n    long double sigma = sqrtl(max(sigma2, (long double)1e-30));\n\n    int vmax = (int)min<long long>((long long)k * (long long)M, totalOil);\n    vmax = max(vmax, 0);\n\n    auto like = [&](int v) -> long double {\n        long double mu = (long double)k * eps + (long double)v * alpha;\n\n        // x ~ N(mu, sigma^2), output is max(0, round(x)).\n        // Assume \"round\" corresponds to half-up: round(x)=t iff x in [t-0.5, t+0.5).\n        if (r == 0) {\n            // output 0 iff round(x) <= 0  <=> x < 0.5\n            long double z = (0.5L - mu) / sigma;\n            return Phi(z);\n        } else {\n            long double lo = (long double)r - 0.5L;\n            long double hi = (long double)r + 0.5L;\n            long double z1 = (lo - mu) / sigma;\n            long double z2 = (hi - mu) / sigma;\n            long double ans = Phi(z2) - Phi(z1);\n            return max((long double)0.0L, ans);\n        }\n    };\n\n    long double sumP = 0.0L, sumVP = 0.0L;\n    for (int v = 0; v <= vmax; v++) {\n        long double p = like(v);\n        sumP += p;\n        sumVP += (long double)v * p;\n    }\n    if (sumP < 1e-35L) {\n        // Fallback: inverse-of-mean (rough)\n        long double v_est = ((long double)r - (long double)k * eps) / max(alpha, (long double)1e-12);\n        v_est = max((long double)0.0L, min(v_est, (long double)vmax));\n        return v_est;\n    }\n    return sumVP / sumP;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M;\n    long double eps;\n    cin >> N >> M >> eps;\n\n    long long totalOil = 0;\n    for (int k = 0; k < M; k++) {\n        int d;\n        cin >> d;\n        totalOil += d;\n        for (int t = 0; t < d; t++) {\n            int i, j;\n            cin >> i >> j;\n        }\n    }\n\n    auto drill_query = [&](int i, int j) -> long long {\n        cout << \"q 1 \" << i << \" \" << j << \"\\n\";\n        cout.flush();\n        long long v;\n        cin >> v;\n        return v;\n    };\n\n    auto div_query_k4 = [&](int i0, int j0) -> long long {\n        // Cells: (i0,j0), (i0+1,j0), (i0,j0+1), (i0+1,j0+1)\n        cout << \"q 4 \"\n             << i0 << \" \" << j0 << \" \"\n             << i0 + 1 << \" \" << j0 << \" \"\n             << i0 << \" \" << j0 + 1 << \" \"\n             << i0 + 1 << \" \" << j0 + 1 << \"\\n\";\n        cout.flush();\n        long long r;\n        cin >> r;\n        return r;\n    };\n\n    const long long NN = 1LL * N * N;\n    long double density = (long double)totalOil / (long double)NN;\n\n    // If density is high, divination overhead is likely not worth it.\n    if (density >= 0.58L) {\n        vector<vector<long long>> val(N, vector<long long>(N, 0));\n        long long sumDrilled = 0;\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                long long v = drill_query(i, j);\n                val[i][j] = v;\n                sumDrilled += v;\n            }\n        }\n        vector<pair<int,int>> ans;\n        for (int i = 0; i < N; i++) for (int j = 0; j < N; j++)\n            if (val[i][j] > 0) ans.push_back({i, j});\n\n        cout << \"a \" << ans.size();\n        for (auto [i, j] : ans) cout << \" \" << i << \" \" << j;\n        cout << \"\\n\";\n        cout.flush();\n        int ok; cin >> ok;\n        return 0;\n    }\n\n    // Choose 2x2 tilings (offsets). Goal: better coverage especially when N is odd,\n    // but keep divination count controlled by density.\n    vector<pair<int,int>> offsets;\n    offsets.push_back({0, 0});\n\n    if (N % 2 == 0) {\n        // N even: one tiling already covers everything; optionally add (1,1).\n        if (density < 0.45L) offsets.push_back({1, 1});\n    } else {\n        // N odd: use offsets to cover border-parity cells more robustly.\n        offsets.push_back({1, 0});\n        offsets.push_back({0, 1});\n        if (density < 0.35L) offsets.push_back({1, 1}); // extra only when sparse\n    }\n\n    vector<long double> score(NN, 0.0L);\n    vector<int> cnt(NN, 0);\n\n    for (auto [si, sj] : offsets) {\n        for (int i0 = si; i0 + 1 < N; i0 += 2) {\n            for (int j0 = sj; j0 + 1 < N; j0 += 2) {\n                long long r = div_query_k4(i0, j0);\n                long double expectedV = posteriorMeanV(4, r, eps, M, totalOil);\n                long double perCell = expectedV / 4.0L;\n\n                int idx00 = (i0) * N + (j0);\n                int idx10 = (i0 + 1) * N + (j0);\n                int idx01 = (i0) * N + (j0 + 1);\n                int idx11 = (i0 + 1) * N + (j0 + 1);\n\n                score[idx00] += perCell; cnt[idx00]++;\n                score[idx10] += perCell; cnt[idx10]++;\n                score[idx01] += perCell; cnt[idx01]++;\n                score[idx11] += perCell; cnt[idx11]++;\n            }\n        }\n    }\n\n    // Fallback for uncovered cells (can happen if we didn't include enough offsets).\n    for (int idx = 0; idx < (int)NN; idx++) {\n        if (cnt[idx] > 0) score[idx] /= (long double)cnt[idx];\n        else score[idx] = density; // expected v per cell\n    }\n\n    vector<int> order(NN);\n    iota(order.begin(), order.end(), 0);\n    sort(order.begin(), order.end(), [&](int a, int b) {\n        if (score[a] != score[b]) return score[a] > score[b];\n        return a < b;\n    });\n\n    vector<vector<long long>> val(N, vector<long long>(N, -1));\n    long long sumDrilled = 0;\n\n    for (int idx : order) {\n        int i = idx / N;\n        int j = idx % N;\n        if (val[i][j] == -1) {\n            long long v = drill_query(i, j);\n            val[i][j] = v;\n            sumDrilled += v;\n            if (sumDrilled == totalOil) break; // guarantees remaining are all zero\n        }\n    }\n\n    vector<pair<int,int>> ans;\n    for (int i = 0; i < N; i++) for (int j = 0; j < N; j++)\n        if (val[i][j] > 0) ans.push_back({i, j});\n\n    cout << \"a \" << ans.size();\n    for (auto [i, j] : ans) cout << \" \" << i << \" \" << j;\n    cout << \"\\n\";\n    cout.flush();\n\n    int ok; 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; // FIX: read W properly\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    // For each day, choose integer widths w_k >= 1, sum w_k = W\n    // to minimize sum_k 100*max(0, a[d][k] - w_k*W).\n    for (int d = 0; d < D; d++) {\n        vector<int> w(N, 1);\n        int S = W - N; // total increments to distribute\n\n        // w0[k] = max w such that a > w*W (i.e., cost positive when w <= w0)\n        // so for w > w0, cost becomes 0.\n        vector<int> w0(N, 0);\n        vector<int> rem(N, 0); // rem = a - w0*W for w0>=1\n\n        for (int k = 0; k < N; k++) {\n            int ak = a[d][k];\n            w0[k] = (ak - 1) / W; // can be 0\n            if (w0[k] >= 1) rem[k] = ak - w0[k] * W; // in [1..W]\n        }\n\n        const long long NEG_FULL = -100LL * W; // decrease by 100W when still positive\n        const long long INF = (1LL << 60);\n\n        auto delta_of = [&](int k) -> long long {\n            if (w[k] >= W) return INF; // cannot increase further\n            int wk = w[k];\n            if (w0[k] == 0) return 0LL; // already zero-cost at w=1\n            if (wk < w0[k]) return NEG_FULL;              // linear region: -100W\n            if (wk == w0[k]) return -100LL * rem[k];    // final step to zero\n            return 0LL;                                   // wk > w0 => already zero\n        };\n\n        // Min-heap by delta (most negative first = biggest cost reduction)\n        priority_queue<pair<long long,int>, vector<pair<long long,int>>, greater<pair<long long,int>>> pq;\n        for (int k = 0; k < N; k++) pq.push({delta_of(k), k});\n\n        for (int step = 0; step < S; step++) {\n            auto [del, k] = pq.top();\n            pq.pop();\n            // Feasibility: there must always be some k with w[k] < W remaining\n            // under sum constraint sum w = W.\n            w[k]++;\n            pq.push({delta_of(k), k});\n        }\n\n        int curX = 0;\n        for (int k = 0; k < N; k++) {\n            int x0 = curX;\n            int x1 = curX + w[k];\n            curX = x1;\n\n            // Rectangle: (x0,0) to (x1,W)\n            cout << x0 << ' ' << 0 << ' ' << x1 << ' ' << W << '\\n';\n        }\n    }\n\n    return 0;\n}","ahc032":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int MOD = 998244353;\n\nstruct OpInfo {\n    array<uint8_t, 9> idx;   // cell ids affected (0..80 for N=9)\n    array<int, 9> add;       // add value for that cell (mod MOD)\n    uint64_t lo = 0, hi = 0; // bitmask of affected cells (0..63 in lo, 64..80 in hi)\n};\n\nstatic inline void maskSet(OpInfo &op, int cell) {\n    if (cell < 64) op.lo |= (1ULL << cell);\n    else op.hi |= (1ULL << (cell - 64));\n}\nstatic inline bool maskHas(const OpInfo &op, int cell) {\n    if (cell < 64) return (op.lo >> cell) & 1ULL;\n    else return (op.hi >> (cell - 64)) & 1ULL;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, K;\n    cin >> N >> M >> K;\n\n    vector<vector<int>> a(N, vector<int>(N));\n    for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) cin >> a[i][j];\n\n    vector<vector<vector<int>>> s(M, vector<vector<int>>(3, vector<int>(3)));\n    for (int m = 0; m < M; m++)\n        for (int i = 0; i < 3; i++)\n            for (int j = 0; j < 3; j++)\n                cin >> s[m][i][j];\n\n    const int NN = N * N; // 81\n    if (NN != 81) {\n        // Problem constraints say N=9, but keep safe fallback.\n        // Output 0 operations.\n        cout << 0 << \"\\n\";\n        return 0;\n    }\n\n    // Enumerate all possible operations (m, p, q) without rotation.\n    vector<OpInfo> ops;\n    vector<array<uint8_t, 3>> meta; // {m,p,q}\n    ops.reserve(M * (N - 2) * (N - 2));\n    meta.reserve(M * (N - 2) * (N - 2));\n\n    for (int m = 0; m < M; m++) {\n        for (int p = 0; p <= N - 3; p++) {\n            for (int q = 0; q <= N - 3; q++) {\n                OpInfo op;\n                int t = 0;\n                for (int di = 0; di < 3; di++) {\n                    for (int dj = 0; dj < 3; dj++) {\n                        int ii = p + di, jj = q + dj;\n                        int cell = ii * N + jj;\n                        op.idx[t] = (uint8_t)cell;\n                        op.add[t] = s[m][di][dj] % MOD;\n                        maskSet(op, cell);\n                        t++;\n                    }\n                }\n                ops.push_back(op);\n                meta.push_back({(uint8_t)m, (uint8_t)p, (uint8_t)q});\n            }\n        }\n    }\n    const int numOps = (int)ops.size(); // 980\n\n    // For fast lookup newAdd on any cell for each op: opAddCell[op][cell] (0 if not touched).\n    vector<array<int, 81>> opAddCell(numOps);\n    for (int opId = 0; opId < numOps; opId++) {\n        opAddCell[opId].fill(0);\n        for (int t = 0; t < 9; t++) {\n            int cell = ops[opId].idx[t];\n            opAddCell[opId][cell] = ops[opId].add[t];\n        }\n    }\n\n    array<int, 81> initX{};\n    for (int i = 0; i < N; i++)\n        for (int j = 0; j < N; j++)\n            initX[i * N + j] = a[i][j] % MOD;\n\n    auto sumScore = [&](const array<int,81>& x) -> long long {\n        long long sc = 0;\n        for (int i = 0; i < NN; i++) sc += x[i];\n        return sc;\n    };\n\n    auto deltaInsert = [&](int opId, const array<int,81>& x) -> long long {\n        long long d = 0;\n        const auto &op = ops[opId];\n        for (int t = 0; t < 9; t++) {\n            int cell = op.idx[t];\n            int oldv = x[cell];\n            int nv = oldv + op.add[t];\n            if (nv >= MOD) nv -= MOD;\n            d += (long long)nv - oldv;\n        }\n        return d;\n    };\n\n    // deltaReplace: score change if remove oldOp and add newOp on current x\n    auto deltaReplace = [&](int oldOpId, int newOpId, const array<int,81>& x) -> long long {\n        long long d = 0;\n        const auto &oldOp = ops[oldOpId];\n        const auto &newOp = ops[newOpId];\n\n        // Cells in oldOp\n        for (int t = 0; t < 9; t++) {\n            int cell = oldOp.idx[t];\n            int oldv = x[cell];\n            int oldAdd = opAddCell[oldOpId][cell]; // same as oldOp.add for that cell\n            int newAdd = opAddCell[newOpId][cell]; // 0 if new doesn't touch\n            int tmp = oldv + newAdd - oldAdd; // in [-(MOD-1), 2MOD-2]\n            if (tmp < 0) tmp += MOD;\n            else if (tmp >= MOD) tmp -= MOD;\n            d += (long long)tmp - oldv;\n        }\n\n        // Cells in newOp but not in oldOp\n        for (int t = 0; t < 9; t++) {\n            int cell = newOp.idx[t];\n            if (maskHas(oldOp, cell)) continue;\n            int oldv = x[cell];\n            int newAdd = opAddCell[newOpId][cell];\n            int tmp = oldv + newAdd;\n            if (tmp >= MOD) tmp -= MOD;\n            d += (long long)tmp - oldv;\n        }\n        return d;\n    };\n\n    auto applyAdd = [&](int opId, array<int,81>& x) {\n        const auto &op = ops[opId];\n        for (int t = 0; t < 9; t++) {\n            int cell = op.idx[t];\n            int nv = x[cell] + op.add[t];\n            if (nv >= MOD) nv -= MOD;\n            x[cell] = nv;\n        }\n    };\n\n    auto applyRemove = [&](int opId, array<int,81>& x) {\n        const auto &op = ops[opId];\n        for (int t = 0; t < 9; t++) {\n            int cell = op.idx[t];\n            int nv = x[cell] - op.add[t];\n            if (nv < 0) nv += MOD;\n            x[cell] = nv;\n        }\n    };\n\n    auto nowMs = []() -> int {\n        using namespace std::chrono;\n        static auto st = steady_clock::now();\n        return (int)duration_cast<milliseconds>(steady_clock::now() - st).count();\n    };\n\n    // Greedy initialization (fixed size K)\n    auto greedyInit = [&](uint64_t seed) -> vector<int> {\n        mt19937_64 rng(seed);\n        array<int,81> x = initX;\n        vector<int> chosen;\n        chosen.reserve(K);\n\n        const int TOPS = 8;\n        for (int step = 0; step < K; step++) {\n            // find top TOPS by deltaInsert\n            array<long long, TOPS> bestD;\n            array<int, TOPS> bestId;\n            int sz = 0;\n\n            for (int opId = 0; opId < numOps; opId++) {\n                long long d = deltaInsert(opId, x);\n                if (sz < TOPS) {\n                    bestD[sz] = d;\n                    bestId[sz] = opId;\n                    sz++;\n                    // insertion sort for descending\n                    for (int i = sz - 1; i > 0; i--) {\n                        if (bestD[i] > bestD[i - 1]) {\n                            swap(bestD[i], bestD[i - 1]);\n                            swap(bestId[i], bestId[i - 1]);\n                        }\n                    }\n                } else {\n                    if (d > bestD[TOPS - 1]) {\n                        bestD[TOPS - 1] = d;\n                        bestId[TOPS - 1] = opId;\n                        // bubble up\n                        for (int i = TOPS - 1; i > 0; i--) {\n                            if (bestD[i] > bestD[i - 1]) {\n                                swap(bestD[i], bestD[i - 1]);\n                                swap(bestId[i], bestId[i - 1]);\n                            }\n                        }\n                    }\n                }\n            }\n\n            int pick = (int)(rng() % sz); // sz<=TOPS\n            int opId = bestId[pick];\n            chosen.push_back(opId);\n            applyAdd(opId, x);\n        }\n        return chosen;\n    };\n\n    auto anneal = [&](vector<int> opsVec, uint64_t seed, int timeBudgetMs) -> pair<long long, vector<int>> {\n        mt19937_64 rng(seed);\n\n        array<int,81> x = initX;\n        for (int opId : opsVec) applyAdd(opId, x);\n        long long curScore = sumScore(x);\n\n        long long bestScore = curScore;\n        vector<int> bestOps = opsVec;\n\n        // biased candidate set (refreshed periodically)\n        vector<int> bias;\n        bias.reserve(220);\n\n        auto refreshBias = [&]() {\n            // compute deltaInsert for all operations on current x\n            vector<pair<long long,int>> vec;\n            vec.reserve(numOps);\n            for (int opId = 0; opId < numOps; opId++) {\n                long long d = deltaInsert(opId, x);\n                vec.push_back({d, opId});\n            }\n            sort(vec.begin(), vec.end(), [&](auto &p1, auto &p2){ return p1.first > p2.first; });\n            int B = min<int>(220, (int)vec.size());\n            bias.clear();\n            for (int i = 0; i < B; i++) bias.push_back(vec[i].second);\n        };\n\n        // initialize bias once\n        refreshBias();\n\n        int startMs = nowMs();\n        int lastRefresh = startMs;\n\n        // parameters\n        const int SAMPLE_REP_BASE = 90; // replaced candidates to evaluate\n        const int SAMPLE_REP_LATE = 50; // reduced later\n        const int REFRESH_MS = 120;     // refresh bias every ~120ms\n\n        int it = 0;\n        while (true) {\n            int elapsed = nowMs() - startMs;\n            if (elapsed >= timeBudgetMs) break;\n\n            // Temperature schedule\n            double prog = (double)elapsed / (double)timeBudgetMs; // 0..1\n            double T0 = 2.5e9;\n            double T1 = 2.0e6;\n            double T = T0 + (T1 - T0) * prog;\n\n            // Refresh bias\n            if (nowMs() - lastRefresh >= REFRESH_MS) {\n                refreshBias();\n                lastRefresh = nowMs();\n            }\n\n            it++;\n            int sz = (int)opsVec.size();\n            // replacement-only (fixed size K)\n            int pos = (int)(rng() % sz);\n            int oldOp = opsVec[pos];\n\n            int sampleRep = (int) (SAMPLE_REP_BASE * (1.0 - prog) + SAMPLE_REP_LATE * prog);\n\n            long long bestD = LLONG_MIN;\n            int bestNew = oldOp;\n\n            // Always consider some biased candidates\n            for (int t = 0; t < sampleRep; t++) {\n                int cand;\n                // Mix bias and uniform\n                if (!bias.empty() && (rng() % 100) < 70) cand = bias[rng() % bias.size()];\n                else cand = (int)(rng() % numOps);\n\n                if (cand == oldOp) continue;\n                long long d = deltaReplace(oldOp, cand, x);\n                if (d > bestD) {\n                    bestD = d;\n                    bestNew = cand;\n                }\n            }\n\n            if (bestNew == oldOp) continue;\n\n            // Metropolis acceptance\n            bool accept = (bestD >= 0);\n            if (!accept) {\n                double diff = (double)bestD; // negative\n                double z = diff / T;\n                if (z < -40.0) accept = false;\n                else {\n                    double prob = exp(z);\n                    double u = (double)rng() / (double)rng.max();\n                    accept = (u < prob);\n                }\n            }\n\n            if (accept) {\n                applyRemove(oldOp, x);\n                applyAdd(bestNew, x);\n                opsVec[pos] = bestNew;\n                curScore += bestD;\n\n                if (curScore > bestScore) {\n                    bestScore = curScore;\n                    bestOps = opsVec;\n                }\n            }\n        }\n\n        return {bestScore, bestOps};\n    };\n\n    // global time\n    int globalStart = nowMs();\n    int TIME = 1850; // keep safe margin\n\n    long long bestScore = -1;\n    vector<int> bestOps;\n\n    // very small number of restarts; incremental moves are cheap now\n    int restarts = 3;\n    for (int r = 0; r < restarts; r++) {\n        if (nowMs() - globalStart > TIME - 50) break;\n        uint64_t seed = 123456789ULL + (uint64_t)r * 998244353ULL;\n\n        // build initial fixed-K ops\n        vector<int> initOps = greedyInit(seed ^ 0x9e3779b97f4a7c15ULL);\n\n        int timeLeft = TIME - (nowMs() - globalStart);\n        if (timeLeft < 200) timeLeft = 200;\n\n        auto [sc, opsBest] = anneal(std::move(initOps), seed + 12345ULL, timeLeft);\n        if (sc > bestScore) {\n            bestScore = sc;\n            bestOps = std::move(opsBest);\n        }\n    }\n\n    // Output exactly K operations (always legal)\n    int L = (int)bestOps.size();\n    if (L > K) L = K;\n    cout << L << \"\\n\";\n    for (int i = 0; i < L; i++) {\n        int opId = bestOps[i];\n        auto [m,p,q] = meta[opId];\n        cout << (int)m << \" \" << (int)p << \" \" << (int)q << \"\\n\";\n    }\n    return 0;\n}","ahc033":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic inline int manhattan(int x1,int y1,int x2,int y2){\n    return abs(x1-x2)+abs(y1-y2);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    cin >> N;\n    vector<vector<int>> A(N, vector<int>(N));\n    for(int i=0;i<N;i++) for(int j=0;j<N;j++) cin >> A[i][j];\n\n    const int TOTAL = N*N;\n    const int MAX_T = 10000;\n\n    // grid[x][y] = container id or -1\n    vector<vector<int>> grid(N, vector<int>(N, -1));\n\n    // position tracking for each container id\n    // px[id], py[id]:\n    //  -3 : not placed yet\n    //  -2 : dispatched\n    //  -1 : held by crane\n    vector<int> px(TOTAL, -3), py(TOTAL, -3);\n\n    // receiving progress per row\n    vector<int> recvNext(N, 0);\n\n    // disp[g][k] whether container (g*N + k) has been dispatched from gate g\n    vector<vector<bool>> disp(N, vector<bool>(N, false));\n\n    // nextK[g] = smallest k such that disp[g][k] == false\n    vector<int> nextK(N, 0);\n\n    // crane0 state\n    int cx = 0, cy = 0;\n    bool holding = false;\n    int heldId = -1;\n\n    // plan while not holding: pick (pickX,pickY), then release to (relX,relY)\n    bool planned = false;\n    int pickX = -1, pickY = -1;\n    int relX = -1, relY = -1;\n\n    auto moveNotHolding = [&](int x, int y, int tx, int ty) -> char {\n        // x-first (doesn't matter for blocking because not holding)\n        if (x < tx) return 'D';\n        if (x > tx) return 'U';\n        if (y < ty) return 'R';\n        if (y > ty) return 'L';\n        return '.';\n    };\n\n    auto moveHolding = [&](int x, int y, int tx, int ty) -> char {\n        // right-first to leave column 0 quickly\n        if (y < ty) return 'R';\n        if (y > ty) return 'L';\n        if (x < tx) return 'D';\n        if (x > tx) return 'U';\n        return '.';\n    };\n\n    vector<char> ops0;\n    ops0.reserve(MAX_T);\n\n    int dispatchedTotal = 0;\n\n    // buffer columns: 1..N-2 (for N=5 => 1..3)\n    vector<pair<int,int>> bufferCells;\n    for(int x=0;x<N;x++){\n        for(int y=1;y<=N-2;y++) bufferCells.push_back({x,y});\n    }\n\n    for (int t = 0; t < MAX_T; t++) {\n        // ---- step1: place arriving containers on receiving gates (i,0) ----\n        for (int i = 0; i < N; i++) {\n            if (recvNext[i] >= N) continue;\n            if (grid[i][0] != -1) continue; // already occupied\n\n            // blocked only if crane0 is holding at that exact square\n            if (holding && cx == i && cy == 0) continue;\n\n            int id = A[i][recvNext[i]];\n            grid[i][0] = id;\n            px[id] = i; py[id] = 0;\n            recvNext[i]++;\n        }\n\n        // ---- step2: action for crane0 ----\n        char act0 = '.';\n        if (t == 0) {\n            act0 = '.'; // keep away from small cranes at turn 0\n        } else if (holding) {\n            if (cx == relX && cy == relY) {\n                act0 = 'Q';\n            } else {\n                act0 = moveHolding(cx, cy, relX, relY);\n            }\n        } else {\n            if (!planned) {\n                // Decide next plan\n                // 1) Try dispatching any expected-min container if available\n                long long bestCost = (1LL<<60);\n                int bestPickX = -1, bestPickY = -1, bestGate = -1;\n\n                for(int g=0; g<N; g++){\n                    int k = nextK[g];\n                    if (k >= N) continue;\n                    int id = g*N + k;\n                    int x = px[id], y = py[id];\n                    if (x < 0) continue;         // not on board / held / dispatched\n                    if (grid[x][y] != id) continue;\n\n                    // allow only receiving (y=0) or buffer (1..N-2)\n                    if (!(y == 0 || (1 <= y && y <= N-2))) continue;\n\n                    long long cost = 0;\n                    cost += manhattan(cx, cy, x, y);               // move to pick\n                    cost += manhattan(x, y, g, N-1);             // move to release at dispatch gate (g, N-1)\n\n                    if (cost < bestCost || (cost == bestCost && id < bestGate)) {\n                        bestCost = cost;\n                        bestPickX = x;\n                        bestPickY = y;\n                        bestGate = g;\n                    }\n                }\n\n                if (bestPickX != -1) {\n                    planned = true;\n                    pickX = bestPickX; pickY = bestPickY;\n                    relX = bestGate; relY = N-1;\n                } else {\n                    // Determine empty buffer cells\n                    vector<pair<int,int>> emptyBuf;\n                    emptyBuf.reserve(bufferCells.size());\n                    for (auto [bx,by] : bufferCells) {\n                        if (grid[bx][by] == -1) emptyBuf.push_back({bx,by});\n                    }\n\n                    if (!emptyBuf.empty()) {\n                        // 2) Buffer not full: store a receiving container into a good buffer cell\n                        long long bestStoreCost = (1LL<<60);\n                        int selRX=-1, selRY=-1, selPX=-1, selPY=-1;\n\n                        long long bestGap = (1LL<<60);\n                        for (int r = 0; r < N; r++) {\n                            if (grid[r][0] == -1) continue;\n                            int id = grid[r][0];\n                            int g = id / N;\n                            int k = id % N;\n\n                            // choose best empty buffer cell for row g if possible\n                            int bestBx=-1, bestBy=-1;\n                            int bestLocalCost = INT_MAX;\n\n                            // prefer row g\n                            for(int y=1; y<=N-2; y++){\n                                if (grid[g][y] == -1){\n                                    int lc = manhattan(r,0,g,y);\n                                    if (lc < bestLocalCost){\n                                        bestLocalCost = lc;\n                                        bestBx = g; bestBy = y;\n                                    }\n                                }\n                            }\n                            // if none in row g, pick best among all empty\n                            if (bestBx == -1) {\n                                bestLocalCost = INT_MAX;\n                                for (auto [bx,by] : emptyBuf) {\n                                    int lc = manhattan(r,0,bx,by);\n                                    if (lc < bestLocalCost){\n                                        bestLocalCost = lc;\n                                        bestBx = bx; bestBy = by;\n                                    }\n                                }\n                            }\n\n                            long long cost = 0;\n                            cost += manhattan(cx, cy, r, 0);\n                            cost += manhattan(r, 0, bestBx, bestBy);\n\n                            long long gap = (long long)k - nextK[g]; // >=0\n\n                            if (cost < bestStoreCost ||\n                                (cost == bestStoreCost && gap < bestGap) ||\n                                (cost == bestStoreCost && gap == bestGap && id < grid[selPX][selPY])) {\n                                bestStoreCost = cost;\n                                bestGap = gap;\n                                selPX = r; selPY = 0;\n                                selRX = bestBx; selRY = bestBy;\n                            }\n                        }\n\n                        if (selPX == -1) {\n                            // fallback: stay\n                            planned = false;\n                        } else {\n                            planned = true;\n                            pickX = selPX; pickY = selPY;\n                            relX = selRX; relY = selRY;\n                        }\n                    } else {\n                        // 3) Buffer full: must dispatch something from buffer (out-of-order may happen)\n                        long long bestDispCost = (1LL<<60);\n                        long long bestGap = (1LL<<60);\n                        int selPX=-1, selPY=-1, selGate=-1;\n\n                        for (auto [bx,by] : bufferCells) {\n                            int id = grid[bx][by];\n                            if (id == -1) continue;\n                            int g = id / N;\n                            int k = id % N;\n\n                            long long cost = 0;\n                            cost += manhattan(cx, cy, bx, by);\n                            cost += manhattan(bx, by, g, N-1);\n\n                            long long gap = (long long)k - nextK[g]; // >=0\n\n                            if (cost < bestDispCost ||\n                                (cost == bestDispCost && gap < bestGap) ||\n                                (cost == bestDispCost && gap == bestGap && id < selGate)) {\n                                bestDispCost = cost;\n                                bestGap = gap;\n                                selPX = bx; selPY = by;\n                                selGate = g;\n                            }\n                        }\n\n                        if (selPX != -1) {\n                            planned = true;\n                            pickX = selPX; pickY = selPY;\n                            relX = selGate; relY = N-1;\n                        } else {\n                            planned = false; // should not happen\n                        }\n                    }\n                }\n            }\n\n            // execute plan (not holding)\n            if (planned && cx == pickX && cy == pickY) {\n                act0 = 'P';\n            } else if (planned) {\n                act0 = moveNotHolding(cx, cy, pickX, pickY);\n            } else {\n                act0 = '.';\n            }\n        }\n\n        // ---- record actions ----\n        ops0.push_back(act0);\n\n        // ---- apply crane0 action (step2) ----\n        if (!holding) {\n            if (act0 == 'P') {\n                // pick at current cell\n                if (grid[cx][cy] == -1) return 0; // illegal\n                heldId = grid[cx][cy];\n                grid[cx][cy] = -1;\n                px[heldId] = -1; py[heldId] = -1;\n                holding = true;\n                planned = false; // picked; now holding will move to relX/relY\n            } else if (act0 == 'Q') {\n                return 0; // illegal\n            } else if (act0 == 'U' || act0 == 'D' || act0 == 'L' || act0 == 'R') {\n                int nx=cx, ny=cy;\n                if (act0=='U') nx--;\n                if (act0=='D') nx++;\n                if (act0=='L') ny--;\n                if (act0=='R') ny++;\n                if (!(0<=nx && nx<N && 0<=ny && ny<N)) return 0;\n                cx = nx; cy = ny;\n            } else {\n                // '.'\n            }\n        } else {\n            if (act0 == 'Q') {\n                if (grid[cx][cy] != -1) return 0; // illegal\n                grid[cx][cy] = heldId;\n                px[heldId] = cx; py[heldId] = cy;\n                holding = false;\n                heldId = -1;\n                // after Q, rel target irrelevant\n            } else if (act0 == 'U' || act0 == 'D' || act0 == 'L' || act0 == 'R') {\n                // large crane can move onto occupied squares while holding\n                int nx=cx, ny=cy;\n                if (act0=='U') nx--;\n                if (act0=='D') nx++;\n                if (act0=='L') ny--;\n                if (act0=='R') ny++;\n                if (!(0<=nx && nx<N && 0<=ny && ny<N)) return 0;\n                cx = nx; cy = ny;\n            } else if (act0 == 'P') {\n                return 0;\n            } else {\n                // '.'\n            }\n        }\n\n        // ---- step3: dispatch from dispatch gates (i, N-1) ----\n        for (int i = 0; i < N; i++) {\n            if (grid[i][N-1] != -1) {\n                int id = grid[i][N-1];\n                grid[i][N-1] = -1;\n                px[id] = -2; py[id] = -2;\n                dispatchedTotal++;\n\n                int g = id / N;\n                int k = id % N;\n                if (!disp[g][k]) disp[g][k] = true;\n                while (nextK[g] < N && disp[g][nextK[g]]) nextK[g]++;\n            }\n        }\n\n        if (dispatchedTotal == TOTAL) break;\n    }\n\n    int L = (int)ops0.size();\n    if (L == 0) {\n        // should not happen\n        cout << \".\\n\";\n        return 0;\n    }\n\n    // Output\n    // Small cranes: bomb at turn 0, then '.' for the rest.\n    // Large crane: ops0.\n    vector<string> out(N);\n    out[0].assign(ops0.begin(), ops0.end());\n    for (int i = 1; i < N; i++) {\n        out[i] = \"B\";\n        if (L > 1) out[i] += string(L - 1, '.');\n    }\n\n    for (int i = 0; i < N; i++) {\n        cout << out[i] << \"\\n\";\n    }\n    return 0;\n}","ahc034":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic inline int manhattan(int r1, int c1, int r2, int c2) {\n    return abs(r1 - r2) + abs(c1 - c2);\n}\nstatic inline int cellId(int r, int c, int N) { return r * N + c; }\nstatic inline pair<int,int> cellRC(int id, int N) { return {id / N, id % N}; }\n\nstatic inline void movePath(int &r, int &c, int nr, int nc, vector<string> &ops) {\n    while (r < nr) { ops.push_back(\"D\"); r++; }\n    while (r > nr) { ops.push_back(\"U\"); r--; }\n    while (c < nc) { ops.push_back(\"R\"); c++; }\n    while (c > nc) { ops.push_back(\"L\"); c--; }\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++) for (int j = 0; j < N; j++) cin >> h[i][j];\n\n    vector<int> sources, sinks;\n    vector<int> posAmt(N*N, 0), negAmt(N*N, 0);\n    for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) {\n        int id = cellId(i,j,N);\n        if (h[i][j] > 0) { sources.push_back(id); posAmt[id] = h[i][j]; }\n        else if (h[i][j] < 0) { sinks.push_back(id); negAmt[id] = -h[i][j]; }\n    }\n\n    if (sources.empty()) return 0; // already all zeros\n\n    const int V = N*N;\n\n    // Precompute dist\n    vector<vector<int>> dist(V, vector<int>(V, 0));\n    for (int a = 0; a < V; a++) {\n        auto [ra, ca] = cellRC(a, N);\n        for (int b = 0; b < V; b++) {\n            auto [rb, cb] = cellRC(b, N);\n            dist[a][b] = abs(ra - rb) + abs(ca - cb);\n        }\n    }\n\n    // Average distance from each cell to all cells (excluding itself)\n    vector<double> avgDist(V, 0.0);\n    for (int a = 0; a < V; a++) {\n        long long sum = 0;\n        for (int b = 0; b < V; b++) if (b != a) sum += dist[a][b];\n        avgDist[a] = (double)sum / (double)(V - 1);\n    }\n\n    // ---- 1) Global greedy matching by increasing distance ----\n    int S = (int)sources.size();\n    int D = (int)sinks.size();\n\n    vector<int> remS(S), remD(D);\n    for (int i = 0; i < S; i++) remS[i] = posAmt[sources[i]];\n    for (int j = 0; j < D; j++) remD[j] = negAmt[sinks[j]];\n\n    vector<vector<int>> alloc(S, vector<int>(D, 0));\n\n    struct Edge { int cost; int si; int dj; };\n    vector<Edge> edges;\n    edges.reserve((size_t)S * (size_t)D);\n    for (int i = 0; i < S; i++) for (int j = 0; j < D; j++) {\n        edges.push_back({dist[sources[i]][sinks[j]], i, j});\n    }\n    sort(edges.begin(), edges.end(), [](const Edge& a, const Edge& b){\n        if (a.cost != b.cost) return a.cost < b.cost;\n        if (a.si != b.si) return a.si < b.si;\n        return a.dj < b.dj;\n    });\n\n    for (auto &e : edges) {\n        int i = e.si, j = e.dj;\n        if (remS[i] == 0 || remD[j] == 0) continue;\n        int x = min(remS[i], remD[j]);\n        alloc[i][j] += x;\n        remS[i] -= x;\n        remD[j] -= x;\n    }\n\n    // (Sanity: all should be satisfied)\n    // since total sum is 0, this greedy allocation across complete bipartite should work.\n    // Still, we won't assert to avoid UB in judge, but we rely on it.\n\n    // ---- 2) Build jobs per source ----\n    struct Job {\n        int sourceId;\n        int totalLoad; // <= 100\n        vector<int> targetIds;\n        vector<int> amounts;\n        long long internalCost; // move cost + 2*totalLoad\n    };\n\n    vector<Job> jobs;\n    jobs.reserve(S);\n    for (int i = 0; i < S; i++) {\n        Job jb;\n        jb.sourceId = sources[i];\n        jb.totalLoad = posAmt[jb.sourceId];\n        jb.internalCost = (1LL<<62);\n\n        for (int j = 0; j < D; j++) if (alloc[i][j] > 0) {\n            jb.targetIds.push_back(sinks[j]);\n            jb.amounts.push_back(alloc[i][j]);\n        }\n        jobs.push_back(std::move(jb));\n    }\n\n    // ---- 3) Decide internal order per job (multiple trials) ----\n    std::mt19937 rng(123456789);\n\n    auto computeInternalCost = [&](int sourceId, int totalLoad,\n                                     const vector<int> &ordT,\n                                     const vector<int> &ordA) -> long long {\n        int cur = sourceId;\n        int load = totalLoad;\n        long long moveCost = 0;\n        for (int t = 0; t < (int)ordT.size(); t++) {\n            int tid = ordT[t];\n            int amt = ordA[t];\n            moveCost += 1LL * dist[cur][tid] * (100 + load);\n            load -= amt;\n            cur = tid;\n        }\n        // loading cost = totalLoad, unloading cost sum=totalLoad\n        return moveCost + 2LL * totalLoad;\n    };\n\n    for (auto &jb : jobs) {\n        int k = (int)jb.targetIds.size();\n        if (k == 0) { // should not happen since totalLoad>0 and sum=0\n            jb.internalCost = 2LL * jb.totalLoad;\n            continue;\n        }\n        if (k == 1) {\n            jb.internalCost = computeInternalCost(jb.sourceId, jb.totalLoad,\n                                                   jb.targetIds, jb.amounts);\n            continue;\n        }\n\n        // Number of trials depends on k\n        int trials = (k <= 12 ? 12 : (k <= 30 ? 9 : 7));\n        int topK = 3;\n\n        vector<int> bestOrdIdx;\n        long long bestCost = (1LL<<62);\n\n        // prepare arrays for local use\n        vector<int> tids = jb.targetIds;\n        vector<int> amts = jb.amounts;\n\n        for (int tt = 0; tt < trials; tt++) {\n            vector<char> used(k, 0);\n            int usedCnt = 0;\n            int cur = jb.sourceId;\n            int load = jb.totalLoad;\n\n            vector<int> ordIdx;\n            ordIdx.reserve(k);\n\n            while (usedCnt < k) {\n                int rem = k - usedCnt;\n\n                // score each candidate\n                vector<pair<double,int>> cand;\n                cand.reserve(rem);\n                for (int i = 0; i < k; i++) if (!used[i]) {\n                    int tid = tids[i];\n                    int amt = amts[i];\n\n                    // immediate move cost with current load\n                    double imm = 1.0 * dist[cur][tid] * (100 + load);\n\n                    // estimated future distance where unloading amt helps:\n                    // after taking this, remaining legs approx (rem-1) * avgDist[tid]\n                    // load-dependent part only: future cost saving ~= amt * futureDist\n                    double futureDistEst = (double)(rem - 1) * avgDist[tid];\n                    double save = 1.0 * amt * futureDistEst;\n\n                    double score = imm - save; // lower is better\n                    cand.push_back({score, i});\n                }\n\n                // pick among best topK by score (randomized)\n                nth_element(cand.begin(), cand.begin() + min(topK, (int)cand.size()) - 1, cand.end(),\n                            [](auto &a, auto &b){ return a.first < b.first; });\n                int take = min(topK, (int)cand.size());\n                // sort just top part for stability\n                sort(cand.begin(), cand.begin() + take, [](auto &a, auto &b){ return a.first < b.first; });\n\n                int pickPos = (take == 1 ? 0 : (int)(rng() % take));\n                int idx = cand[pickPos].second;\n\n                used[idx] = 1;\n                usedCnt++;\n                ordIdx.push_back(idx);\n\n                cur = tids[idx];\n                load -= amts[idx];\n            }\n\n            vector<int> ordT, ordA;\n            ordT.reserve(k); ordA.reserve(k);\n            for (int idx : ordIdx) { ordT.push_back(tids[idx]); ordA.push_back(amts[idx]); }\n\n            long long cost = computeInternalCost(jb.sourceId, jb.totalLoad, ordT, ordA);\n            if (cost < bestCost) {\n                bestCost = cost;\n                bestOrdIdx = std::move(ordIdx);\n                // store best order in-place to avoid recompute later\n            }\n        }\n\n        // build final order from bestOrdIdx\n        vector<int> finalT, finalA;\n        finalT.reserve(k); finalA.reserve(k);\n        for (int idx : bestOrdIdx) {\n            finalT.push_back(tids[idx]);\n            finalA.push_back(amts[idx]);\n        }\n\n        // small local improvement: adjacent swaps (only when k small)\n        if (k <= 26) {\n            bool improved = true;\n            int pass = 0;\n            while (improved && pass < 3) {\n                improved = false;\n                pass++;\n                for (int i = 0; i + 1 < k; i++) {\n                    // try swap i and i+1\n                    swap(finalT[i], finalT[i+1]);\n                    swap(finalA[i], finalA[i+1]);\n                    long long c2 = computeInternalCost(jb.sourceId, jb.totalLoad, finalT, finalA);\n                    if (c2 <= bestCost) {\n                        bestCost = c2;\n                        improved = true;\n                    } else {\n                        // revert\n                        swap(finalT[i], finalT[i+1]);\n                        swap(finalA[i], finalA[i+1]);\n                    }\n                }\n            }\n        }\n\n        jb.targetIds = finalT;\n        jb.amounts = finalA;\n        jb.internalCost = bestCost;\n    }\n\n    // ---- 4) Execute jobs in greedy outer order ----\n    vector<string> ops;\n    ops.reserve(100000);\n\n    vector<char> done(jobs.size(), 0);\n    int doneCnt = 0;\n\n    int curR = 0, curC = 0;\n    int curId = 0;\n\n    while (doneCnt < (int)jobs.size()) {\n        int bestJ = -1;\n        long long bestScore = (1LL<<62);\n\n        for (int j = 0; j < (int)jobs.size(); j++) if (!done[j]) {\n            long long ext = 1LL * 100 * dist[curId][jobs[j].sourceId]; // truck empty currently\n            long long total = ext + jobs[j].internalCost;\n            if (total < bestScore) {\n                bestScore = total;\n                bestJ = j;\n            }\n        }\n\n        if (bestJ < 0) break; // should not happen\n\n        Job &jb = jobs[bestJ];\n\n        // move empty to source\n        auto [sr, sc] = cellRC(jb.sourceId, N);\n        movePath(curR, curC, sr, sc, ops);\n        curId = jb.sourceId;\n\n        // load once\n        ops.push_back(\"+\" + to_string(jb.totalLoad));\n\n        // unload sequence\n        int r = curR, c = curC;\n        for (int t = 0; t < (int)jb.targetIds.size(); t++) {\n            int tid = jb.targetIds[t];\n            int amt = jb.amounts[t];\n            auto [tr, tc] = cellRC(tid, N);\n            movePath(r, c, tr, tc, ops);\n            ops.push_back(\"-\" + to_string(amt));\n            curId = tid;\n        }\n        curR = r; curC = c;\n\n        done[bestJ] = 1;\n        doneCnt++;\n\n        if ((int)ops.size() > 100000) {\n            // Very unlikely with this strategy, but avoid illegal output.\n            return 0;\n        }\n    }\n\n    for (auto &s : ops) cout << s << \"\\n\";\n    return 0;\n}","ahc035":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\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    int N, M, T;\n    cin >> N >> M >> T;\n\n    const int seed_count = 2 * N * (N - 1);\n    const int C = N * N;\n\n    vector<vector<int>> X(seed_count, vector<int>(M));\n    for (int k = 0; k < seed_count; k++) {\n        for (int l = 0; l < M; l++) cin >> X[k][l];\n    }\n\n    auto posId = [&](int i, int j) { return i * N + j; };\n\n    // Grid edges (for objective): right + down\n    vector<pair<int,int>> edges;\n    edges.reserve(seed_count);\n    for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) {\n        if (i + 1 < N) edges.push_back({posId(i, j), posId(i + 1, j)});\n        if (j + 1 < N) edges.push_back({posId(i, j), posId(i, j + 1)});\n    }\n    // incident edge indices per position\n    vector<vector<int>> incident(C);\n    for (int ei = 0; ei < (int)edges.size(); ei++) {\n        auto [u, v] = edges[ei];\n        incident[u].push_back(ei);\n        incident[v].push_back(ei);\n    }\n\n    // 4-neighborhood positions\n    vector<vector<int>> adjPos(C);\n    vector<int> degPos(C, 0);\n    for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) {\n        int u = posId(i, j);\n        auto addNb = [&](int ni, int nj) {\n            if (0 <= ni && ni < N && 0 <= nj && nj < N) {\n                adjPos[u].push_back(posId(ni, nj));\n            }\n        };\n        addNb(i-1, j); addNb(i+1, j); addNb(i, j-1); addNb(i, j+1);\n        degPos[u] = (int)adjPos[u].size();\n    }\n\n    // aff[p][q] = list of edge indices affected by swapping positions p and q\n    vector<vector<vector<int>>> aff(C, vector<vector<int>>(C));\n    for (int p = 0; p < C; p++) {\n        for (int q = 0; q < C; q++) if (p != q) {\n            // union incident[p] and incident[q]\n            vector<int> tmp;\n            tmp.reserve(incident[p].size() + incident[q].size());\n            vector<char> mark(edges.size(), 0);\n            for (int ei : incident[p]) {\n                if (!mark[ei]) { mark[ei] = 1; tmp.push_back(ei); }\n            }\n            for (int ei : incident[q]) {\n                if (!mark[ei]) { mark[ei] = 1; tmp.push_back(ei); }\n            }\n            aff[p][q] = std::move(tmp);\n        }\n    }\n\n    mt19937_64 rng((uint64_t)chrono::high_resolution_clock::now().time_since_epoch().count());\n\n    // Choose the best adjacent cell pair (u,v) by degree(u)+degree(v)\n    auto bestDegreePair = [&]() -> pair<int,int> {\n        int best = -1;\n        vector<pair<int,int>> cand;\n        for (auto [u, v] : edges) {\n            int sc = degPos[u] + degPos[v];\n            if (sc > best) {\n                best = sc;\n                cand.clear();\n                cand.push_back({u, v});\n            } else if (sc == best) {\n                cand.push_back({u, v});\n            }\n        }\n        if (cand.empty()) return {0, 1};\n        auto pr = cand[(size_t)(rng() % cand.size())];\n        return pr;\n    };\n\n    vector<int> bestDegreeEdgePair = {bestDegreePair().first, bestDegreePair().second};\n\n    auto solve_one_turn = [&]() -> vector<int> {\n        // V_k\n        vector<int> V(seed_count, 0);\n        for (int k = 0; k < seed_count; k++) {\n            int s = 0;\n            for (int l = 0; l < M; l++) s += X[k][l];\n            V[k] = s;\n        }\n\n        // Precompute edge proxy score between seeds\n        // Blend:\n        //   UB^2 (optimistic) + tail^2 (EV+Z*sd clamped by UB)\n        const double Z = 2.0;\n        const double alphaUB = 0.8;\n\n        vector<vector<ll>> score(seed_count, vector<ll>(seed_count, 0));\n\n        // argmax per component\n        vector<int> argMax(M, 0);\n        for (int l = 0; l < M; l++) {\n            int bestk = 0;\n            for (int k = 1; k < seed_count; k++) if (X[k][l] > X[bestk][l]) bestk = k;\n            argMax[l] = bestk;\n        }\n\n        for (int a = 0; a < seed_count; a++) {\n            for (int b = a; b < seed_count; b++) {\n                int ub = 0;\n                double EV = (V[a] + V[b]) / 2.0;\n                double varSum = 0.0;\n                for (int l = 0; l < M; l++) {\n                    int xa = X[a][l], xb = X[b][l];\n                    ub += max(xa, xb);\n                    double d = (double)xa - (double)xb;\n                    varSum += (d * d) / 4.0;\n                }\n                double sd = sqrt(max(0.0, varSum));\n                double tail = EV + Z * sd;\n                if (tail > (double)ub) tail = (double)ub;\n\n                ll ub2 = 1LL * ub * ub;\n                ll tail2 = (ll)(tail * tail + 0.5);\n\n                ll sc = (ll)(alphaUB * (double)ub2 + (1.0 - alphaUB) * (double)tail2 + 0.5);\n                score[a][b] = score[b][a] = sc;\n            }\n        }\n\n        // Candidate seeds: topV + argMax\n        vector<int> byV(seed_count);\n        iota(byV.begin(), byV.end(), 0);\n        sort(byV.begin(), byV.end(), [&](int a, int b){ return V[a] > V[b]; });\n\n        vector<int> cand;\n        int topV = min(seed_count, 28);\n        for (int i = 0; i < topV; i++) cand.push_back(byV[i]);\n        for (int l = 0; l < M; l++) cand.push_back(argMax[l]);\n        sort(cand.begin(), cand.end());\n        cand.erase(unique(cand.begin(), cand.end()), cand.end());\n\n        // Best adjacent seed pair under proxy\n        ll bestPairScore = -1;\n        int bestA = cand[0], bestB = cand[0];\n        for (int i = 0; i < (int)cand.size(); i++) {\n            for (int j = i + 1; j < (int)cand.size(); j++) {\n                int a = cand[i], b = cand[j];\n                ll sc = score[a][b];\n                if (sc > bestPairScore ||\n                    (sc == bestPairScore && V[a] + V[b] > V[bestA] + V[bestB])) {\n                    bestPairScore = sc;\n                    bestA = a; bestB = b;\n                }\n            }\n        }\n        if (bestA == bestB) bestB = byV[min(1, (int)byV.size()-1)];\n\n        // Choose 36 seeds biased by score with bestA/bestB and V\n        vector<char> used(seed_count, 0);\n        vector<int> chosen;\n        chosen.reserve(C);\n\n        auto addSeed = [&](int k) {\n            if (!used[k]) { used[k] = 1; chosen.push_back(k); }\n        };\n        addSeed(bestA);\n        addSeed(bestB);\n        for (int l = 0; l < M; l++) addSeed(argMax[l]);\n\n        vector<pair<ll,int>> weights;\n        weights.reserve(seed_count);\n        for (int k = 0; k < seed_count; k++) if (!used[k]) {\n            ll w = score[bestA][k] + score[bestB][k] + 1000LL * (ll)V[k];\n            weights.push_back({w, k});\n        }\n        sort(weights.begin(), weights.end(), [&](auto &p1, auto &p2){ return p1.first > p2.first; });\n        for (auto &pr : weights) {\n            if ((int)chosen.size() >= C) break;\n            addSeed(pr.second);\n        }\n        for (int k = 0; k < seed_count && (int)chosen.size() < C; k++) if (!used[k]) addSeed(k);\n\n        auto calcObj = [&](const vector<int>& Apos) -> ll {\n            ll obj = 0;\n            for (int ei = 0; ei < (int)edges.size(); ei++) {\n                auto [u, v] = edges[ei];\n                obj += score[Apos[u]][Apos[v]];\n            }\n            return obj;\n        };\n\n        // Multiple restarts\n        int restarts = 6;\n        int iters = 13000;\n\n        vector<int> bestApos(C, 0);\n        ll bestObj = LLONG_MIN;\n\n        auto [uBest, vBest] = bestDegreePair();\n\n        for (int r = 0; r < restarts; r++) {\n            uint64_t seedR = splitmix64(rng() + (uint64_t)r * 998244353ULL);\n            mt19937_64 rg(seedR);\n\n            vector<int> Apos(C, -1);\n            vector<int> remaining = chosen;\n\n            auto takeSeed = [&](int k) {\n                auto it = find(remaining.begin(), remaining.end(), k);\n                if (it != remaining.end()) remaining.erase(it);\n            };\n\n            // Place bestA/bestB on best-degree adjacent cells\n            Apos[uBest] = bestA; takeSeed(bestA);\n            if (vBest != uBest) { Apos[vBest] = bestB; takeSeed(bestB); }\n\n            // Track filled and filled neighbor counts\n            vector<int> filledCnt(C, 0);\n            vector<char> isFilled(C, 0), isUnfilled(C, 1);\n\n            int filled = 0;\n            for (int p = 0; p < C; p++) if (Apos[p] != -1) {\n                isFilled[p] = 1;\n                isUnfilled[p] = 0;\n                filled++;\n            }\n            for (int p = 0; p < C; p++) if (isFilled[p]) {\n                for (int nb : adjPos[p]) filledCnt[nb]++;\n            }\n\n            auto pickNextPos = [&]() -> int {\n                int bestCnt = -1;\n                int bestDeg = -1;\n                vector<int> ties;\n                for (int p = 0; p < C; p++) if (isUnfilled[p]) {\n                    int cnt = filledCnt[p];\n                    int dg = degPos[p];\n                    if (cnt > bestCnt || (cnt == bestCnt && dg > bestDeg)) {\n                        bestCnt = cnt;\n                        bestDeg = dg;\n                        ties.clear();\n                        ties.push_back(p);\n                    } else if (cnt == bestCnt && dg == bestDeg) {\n                        ties.push_back(p);\n                    }\n                }\n                if (ties.empty()) {\n                    // fallback\n                    for (int p = 0; p < C; p++) if (isUnfilled[p]) return p;\n                }\n                return ties[(size_t)(rg() % ties.size())];\n            };\n\n            // Fill to all assigned\n            while (filled < C) {\n                int p = pickNextPos();\n\n                // candidate seed gain by local neighborhood\n                vector<pair<ll,int>> candGain;\n                candGain.reserve(remaining.size());\n                for (int s : remaining) {\n                    ll gsum = 0;\n                    for (int nb : adjPos[p]) if (Apos[nb] != -1) gsum += score[s][Apos[nb]];\n                    candGain.push_back({gsum, s});\n                }\n\n                int topK = min<int>(5, candGain.size());\n                if (topK == 0) break;\n\n                nth_element(candGain.begin(), candGain.begin() + topK, candGain.end(),\n                             [&](auto &a, auto &b){ return a.first > b.first; });\n                candGain.resize(topK);\n\n                sort(candGain.begin(), candGain.end(),\n                     [&](auto &a, auto &b){ return a.first > b.first; });\n\n                int pickIdx = (topK == 1 ? 0 : (int)(rg() % topK));\n                int seedSel = candGain[pickIdx].second;\n\n                Apos[p] = seedSel;\n                takeSeed(seedSel);\n\n                isUnfilled[p] = 0;\n                isFilled[p] = 1;\n                filled++;\n\n                for (int nb : adjPos[p]) filledCnt[nb]++;\n            }\n\n            ll curObj = calcObj(Apos);\n            if (curObj > bestObj) { bestObj = curObj; bestApos = Apos; }\n\n            double avgEdge = (double)curObj / (double)edges.size();\n            double temp0 = max(1.0, avgEdge * 0.8);\n\n            // SA swaps\n            for (int it = 0; it < iters; it++) {\n                int p = (int)(rg() % C);\n                int q = (int)(rg() % C);\n                if (p == q) continue;\n                int sp = Apos[p], sq = Apos[q];\n                if (sp == sq) continue;\n\n                ll delta = 0;\n                for (int ei : aff[p][q]) {\n                    auto [u, v] = edges[ei];\n\n                    int su_old = (u == p ? sp : (u == q ? sq : Apos[u]));\n                    int sv_old = (v == p ? sp : (v == q ? sq : Apos[v]));\n                    ll oldTerm = score[su_old][sv_old];\n\n                    int su_new = (u == p ? sq : (u == q ? sp : Apos[u]));\n                    int sv_new = (v == p ? sq : (v == q ? sp : Apos[v]));\n                    ll newTerm = score[su_new][sv_new];\n\n                    delta += newTerm - oldTerm;\n                }\n\n                if (delta >= 0) {\n                    swap(Apos[p], Apos[q]);\n                    curObj += delta;\n                } else {\n                    double t = temp0 * (1.0 - (double)it / iters);\n                    t = t * t + 1e-9;\n                    double pr = exp((double)delta / t);\n                    double roll = uniform_real_distribution<double>(0.0, 1.0)(rg);\n                    if (roll < pr) {\n                        swap(Apos[p], Apos[q]);\n                        curObj += delta;\n                    }\n                }\n\n                if (curObj > bestObj) { bestObj = curObj; bestApos = Apos; }\n            }\n        }\n\n        return bestApos;\n    };\n\n    for (int tt = 0; tt < T; tt++) {\n        vector<int> A = solve_one_turn();\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                if (j) cout << ' ';\n                cout << A[posId(i,j)];\n            }\n            cout << '\\n';\n        }\n        cout.flush();\n\n        for (int k = 0; k < seed_count; k++) {\n            for (int l = 0; l < M; l++) cin >> X[k][l];\n        }\n    }\n    return 0;\n}","ahc038":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Pt { int x, y; };\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, V;\n    cin >> N >> M >> V;\n    vector<string> s(N), t(N);\n    for (int i = 0; i < N; i++) cin >> s[i];\n    for (int i = 0; i < N; i++) cin >> t[i];\n\n    vector<vector<int>> occ(N, vector<int>(N, 0));\n    for (int i = 0; i < N; i++)\n        for (int j = 0; j < N; j++)\n            occ[i][j] = (s[i][j] == '1');\n\n    vector<Pt> A, B; // A: src = initial 1, target 0 ; B: dst = initial 0, target 1\n    for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) {\n        int si = (s[i][j] == '1');\n        int ti = (t[i][j] == '1');\n        if (si && !ti) A.push_back({i, j});\n        if (!si && ti) B.push_back({i, j});\n    }\n\n    // Arm design: V' = 2, root(0) -> fingertip(1), edge length 1\n    // initial direction extends right.\n    int Vp = 2;\n    cout << Vp << \"\\n\";\n    cout << 0 << \" \" << 1 << \"\\n\";\n\n    auto inRange = [&](int x, int y) {\n        return 0 <= x && x < N && 0 <= y && y < N;\n    };\n\n    // dir: 0=R,1=D,2=L,3=U, fingertip = root + (dx[dir], dy[dir])\n    array<int,4> dx{0, 1, 0, -1};\n    array<int,4> dy{1, 0, -1, 0};\n\n    // Choose initial root so that fingertip points right and stays in range.\n    // We'll try to put fingertip near centroid of A.\n    int dir = 0; // right\n    int rx = 0, ry = 0;\n    if (!A.empty()) {\n        double cx = 0, cy = 0;\n        for (auto &p : A) { cx += p.x; cy += p.y; }\n        cx /= (double)A.size();\n        cy /= (double)A.size();\n\n        // fingertip will be at (fx,fy) = (rx+dx[dir], ry+dy[dir]) = (rx, ry+1)\n        // => root y = fy-1 must be in range => need fy in [1..N-1]\n        Pt best = A[0];\n        double bestD = 1e100;\n        for (auto &p : A) {\n            if (p.y < 1 || p.y >= N) continue;\n            double d = (p.x - cx)*(p.x - cx) + (p.y - cy)*(p.y - cy);\n            if (d < bestD) { bestD = d; best = p; }\n        }\n        rx = best.x;\n        ry = best.y - 1;\n        if (!inRange(rx, ry)) { rx = 0; ry = 0; }\n    }\n    cout << rx << \" \" << ry << \"\\n\";\n\n    if (A.empty()) return 0;\n\n    // State encoding: id = ((x*N + y)*4 + dir)\n    int S = N * N * 4;\n    auto encode = [&](int x, int y, int d) {\n        return ((x * N + y) * 4 + d);\n    };\n\n    vector<int> rootX(S), rootY(S), dirOf(S);\n    for (int x = 0; x < N; x++) for (int y = 0; y < N; y++) for (int d = 0; d < 4; d++) {\n        int id = encode(x,y,d);\n        rootX[id] = x; rootY[id] = y; dirOf[id] = d;\n    }\n\n    struct Edge { int to; char mv; char rot; };\n\n    // Precompute adjacency.\n    // Operation 1: move root inside grid only (required).\n    // Operation 2: rotate subtree at fingertip (no grid constraint).\n    // Operation order: move then rotate then later P.\n    array<pair<char,pair<int,int>>,5> moves = {{\n        {'.',{0,0}}, {'U',{-1,0}}, {'D',{1,0}}, {'L',{0,-1}}, {'R',{0,1}}\n    }};\n    // For output, 'L' means CCW, 'R' means CW.\n    // dir update:\n    // CCW (L): Right -> Up => dir-1 => (d+3)%4\n    // CW (R): Right -> Down => dir+1 => (d+1)%4\n    array<pair<char,int>,3> rots = {{\n        {'.',0}, {'L',3}, {'R',1}\n    }};\n\n    vector<vector<Edge>> adj(S);\n    for (int id = 0; id < S; id++) {\n        int x = rootX[id], y = rootY[id], d = dirOf[id];\n        for (auto &mv : moves) {\n            char mvChar = mv.first;\n            int mx = mv.second.first, my = mv.second.second;\n            int nx = x + mx, ny = y + my;\n            if (!inRange(nx, ny)) continue; // operation 1 constraint\n            for (auto &rt : rots) {\n                char rotChar = rt.first;\n                int nd = (d + rt.second) & 3;\n                int to = encode(nx, ny, nd);\n                adj[id].push_back({to, mvChar, rotChar});\n            }\n        }\n    }\n\n    vector<int> dist(S), prevState(S);\n    vector<char> prevMv(S), prevRot(S);\n\n    auto bfsFrom = [&](int startState) {\n        fill(dist.begin(), dist.end(), -1);\n        queue<int> q;\n        dist[startState] = 0;\n        q.push(startState);\n        while(!q.empty()){\n            int v = q.front(); q.pop();\n            for (auto &e : adj[v]) {\n                int u = e.to;\n                if (dist[u] != -1) continue;\n                dist[u] = dist[v] + 1;\n                prevState[u] = v;\n                prevMv[u] = e.mv;\n                prevRot[u] = e.rot;\n                q.push(u);\n            }\n        }\n    };\n\n    auto reconstructPath = [&](int startState, int goalState) {\n        vector<pair<char,char>> steps;\n        if (startState == goalState) return steps; // empty\n        int cur = goalState;\n        while (cur != startState) {\n            steps.push_back({prevMv[cur], prevRot[cur]});\n            cur = prevState[cur];\n        }\n        reverse(steps.begin(), steps.end());\n        return steps;\n    };\n\n    auto candidateStatesForFingertip = [&](Pt target) {\n        vector<int> cand;\n        for (int d = 0; d < 4; d++) {\n            int crx = target.x - dx[d];\n            int cry = target.y - dy[d];\n            if (!inRange(crx, cry)) continue; // root must be inside\n            cand.push_back(encode(crx, cry, d));\n        }\n        return cand;\n    };\n\n    int fx = rx + dx[dir], fy = ry + dy[dir];\n    (void)fx; (void)fy;\n\n    bool holding = false;\n\n    auto applyMoveSim = [&](char mv) {\n        if (mv == 'U') rx--;\n        else if (mv == 'D') rx++;\n        else if (mv == 'L') ry--;\n        else if (mv == 'R') ry++;\n    };\n    auto applyRotSim = [&](char rot) {\n        if (rot == 'L') dir = (dir + 3) & 3;\n        else if (rot == 'R') dir = (dir + 1) & 3;\n    };\n\n    vector<string> ops;\n    ops.reserve(100000);\n\n    auto segmentTo = [&](Pt target, bool doPickup) {\n        // BFS from current arm state\n        int startState = encode(rx, ry, dir);\n        bfsFrom(startState);\n\n        // Choose best reachable state where fingertip==target\n        auto cand = candidateStatesForFingertip(target);\n        int bestState = -1;\n        int bestD = INT_MAX;\n        for (int st : cand) {\n            if (dist[st] == -1) continue;\n            if (dist[st] < bestD) {\n                bestD = dist[st];\n                bestState = st;\n            } else if (dist[st] == bestD) {\n                // tie-break deterministic: smaller id\n                bestState = min(bestState, st);\n            }\n        }\n        if (bestState == -1) {\n            // Should not happen on valid grid; just do nothing.\n            return;\n        }\n\n        auto steps = reconstructPath(startState, bestState);\n\n        // Ensure grabbing/placing semantics\n        // P means: if holding==false then pickup from cell; else release to cell.\n        // We'll output P exactly at the moment fingertip is over target.\n        auto doPAtTarget = [&]() {\n            int tx = target.x, ty = target.y;\n            if (doPickup) {\n                // we want simulator to pickup, so holding must be false\n                if (holding) {\n                    // would release instead -> illegal possibly\n                    // In contest environment, better to just abort.\n                    exit(0);\n                }\n                if (occ[tx][ty] != 1) {\n                    // This is exactly what caused the WA previously.\n                    exit(0);\n                }\n                occ[tx][ty] = 0;\n                holding = true;\n            } else {\n                // want release, so holding must be true\n                if (!holding) exit(0);\n                if (occ[tx][ty] != 0) {\n                    exit(0);\n                }\n                occ[tx][ty] = 1;\n                holding = false;\n            }\n        };\n\n        if (steps.empty()) {\n            // Already at fingertip==target at start.\n            // Need to output one turn with P (previous code missed this -> WA).\n            string st;\n            st.push_back('.'); // no move\n            st.push_back('.'); // no rotation\n            st.push_back('.'); // vertex 0 not fingertip\n            st.push_back('P'); // vertex 1 do P\n            ops.push_back(st);\n            doPAtTarget();\n            return;\n        }\n\n        for (int i = 0; i < (int)steps.size(); i++) {\n            char mv = steps[i].first;\n            char rot = steps[i].second;\n            bool last = (i == (int)steps.size() - 1);\n\n            string st;\n            st.push_back(mv);\n            st.push_back(rot);\n            st.push_back('.');                // vertex 0\n            st.push_back(last ? 'P' : '.');  // fingertip action\n\n            ops.push_back(st);\n\n            // simulate state after op1+op2 (before op3)\n            applyMoveSim(mv);\n            applyRotSim(rot);\n\n            if (last) {\n                // now fingertip at target\n                doPAtTarget();\n            }\n        }\n    };\n\n    auto manhattan = [&](Pt p, Pt q) {\n        return abs(p.x - q.x) + abs(p.y - q.y);\n    };\n\n    // Main loop: move all src in A to some dst in B.\n    while (!A.empty() && !B.empty()) {\n        if ((int)ops.size() >= 100000) break;\n\n        // current fingertip position\n        Pt curTip{rx + dx[dir], ry + dy[dir]};\n\n        // BFS once to estimate pickup distance for candidates\n        int startState = encode(rx, ry, dir);\n        bfsFrom(startState);\n\n        // take top-K closest sources by Manhattan\n        vector<int> idx(A.size());\n        iota(idx.begin(), idx.end(), 0);\n        sort(idx.begin(), idx.end(), [&](int i, int j) {\n            return manhattan(curTip, A[i]) < manhattan(curTip, A[j]);\n        });\n\n        int Ksamp = min<int>(20, (int)idx.size());\n\n        long long bestCost = (1LL<<60);\n        int bestAi = idx[0];\n        int bestBj = 0;\n\n        // For each candidate source, estimate pickupTurns by min(dist[state] where fingertip==src)\n        // and pair with nearest destination by Manhattan.\n        for (int cs = 0; cs < Ksamp; cs++) {\n            int ai = idx[cs];\n            Pt src = A[ai];\n\n            int pickupTurns = INT_MAX;\n            auto candSrc = candidateStatesForFingertip(src);\n            for (int st : candSrc) if (dist[st] != -1) pickupTurns = min(pickupTurns, dist[st]);\n            if (pickupTurns == INT_MAX) continue;\n\n            int nearestJ = 0;\n            int bestDmn = INT_MAX;\n            for (int j = 0; j < (int)B.size(); j++) {\n                int dm = manhattan(src, B[j]);\n                if (dm < bestDmn) { bestDmn = dm; nearestJ = j; }\n            }\n\n            long long est = (long long)pickupTurns + (long long)bestDmn;\n            if (est < bestCost) {\n                bestCost = est;\n                bestAi = ai;\n                bestBj = nearestJ;\n            }\n        }\n\n        Pt src = A[bestAi];\n        Pt dst = B[bestBj];\n\n        // remove selected\n        A[bestAi] = A.back(); A.pop_back();\n        B[bestBj] = B.back(); B.pop_back();\n\n        // execute pickup and release\n        segmentTo(src, true);\n        segmentTo(dst, false);\n    }\n\n    for (auto &st : ops) cout << st << \"\\n\";\n    return 0;\n}","ahc039":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int MAXC = 100000;\n\nstruct Pt {\n    int x, y;\n    int w; // +1 mackerel, -1 sardine\n};\n\n// Static 2D range sum for points with weights using Fenwick tree of sorted y-lists.\n// Supports sum of weights in rectangle [xL..xR] x [yB..yT] (inclusive) in ~O(log^2 N).\nstruct RangeSum2D {\n    int nx = 0;\n    vector<int> xvals;                 // unique sorted x of points\n    vector<vector<int>> yList;        // Fenwick nodes: sorted y values\n    vector<vector<long long>> pref;  // Fenwick nodes: prefix sums of weights aligned with yList\n\n    RangeSum2D() = default;\n\n    explicit RangeSum2D(const vector<Pt>& pts) {\n        build(pts);\n    }\n\n    void build(const vector<Pt>& pts) {\n        xvals.clear();\n        xvals.reserve(pts.size());\n        for (auto &p : pts) xvals.push_back(p.x);\n        sort(xvals.begin(), xvals.end());\n        xvals.erase(unique(xvals.begin(), xvals.end()), xvals.end());\n\n        nx = (int)xvals.size();\n        yList.assign(nx + 1, {});\n        vector<vector<pair<int,int>>> tmp(nx + 1);\n\n        for (auto &p : pts) {\n            int xi = (int)(lower_bound(xvals.begin(), xvals.end(), p.x) - xvals.begin()) + 1; // 1-indexed\n            for (int i = xi; i <= nx; i += i & -i) {\n                tmp[i].push_back({p.y, p.w});\n            }\n        }\n\n        yList.resize(nx + 1);\n        pref.assign(nx + 1, {});\n        for (int i = 1; i <= nx; i++) {\n            auto &v = tmp[i];\n            sort(v.begin(), v.end(), [](auto &a, auto &b) {\n                return a.first < b.first;\n            });\n            yList[i].resize(v.size());\n            pref[i].resize(v.size());\n            long long run = 0;\n            for (size_t j = 0; j < v.size(); j++) {\n                yList[i][j] = v[j].first;\n                run += (long long)v[j].second;\n                pref[i][j] = run;\n            }\n        }\n    }\n\n    long long prefSum(int X, int Y) const {\n        if (X < 0 || Y < 0) return 0;\n        // number of xvals <= X\n        int xi = (int)(upper_bound(xvals.begin(), xvals.end(), X) - xvals.begin()); // can be 0..nx\n        long long res = 0;\n        for (int i = xi; i > 0; i -= i & -i) {\n            const auto &ys = yList[i];\n            if (ys.empty()) continue;\n            int k = (int)(upper_bound(ys.begin(), ys.end(), Y) - ys.begin()); // count <=Y\n            if (k > 0) res += pref[i][k - 1];\n        }\n        return res;\n    }\n\n    long long sumRect(int xL, int xR, int yB, int yT) const {\n        if (xL > xR || yB > yT) return 0;\n        xL = max(xL, 0); xR = min(xR, MAXC);\n        yB = max(yB, 0); yT = min(yT, MAXC);\n        if (xL > xR || yB > yT) return 0;\n        long long A = prefSum(xR, yT);\n        long long B = prefSum(xL - 1, yT);\n        long long C = prefSum(xR, yB - 1);\n        long long D = prefSum(xL - 1, yB - 1);\n        return A - B - C + D;\n    }\n};\n\n// Clamp/normalize to a non-degenerate rectangle with integer coords in [0..MAXC].\n// Ensures xL < xR and yB < yT.\nstatic inline void normalizeRect(int &xL, int &xR, int &yB, int &yT) {\n    xL = max(0, min(MAXC, xL));\n    xR = max(0, min(MAXC, xR));\n    yB = max(0, min(MAXC, yB));\n    yT = max(0, min(MAXC, yT));\n    if (xL > xR) swap(xL, xR);\n    if (yB > yT) swap(yB, yT);\n\n    if (xL == xR) {\n        if (xR < MAXC) xR = xL + 1;\n        else xL = xL - 1;\n    }\n    if (yB == yT) {\n        if (yT < MAXC) yT = yB + 1;\n        else yB = yB - 1;\n    }\n\n    // Final ensure\n    xL = max(0, min(MAXC, xL));\n    xR = max(0, min(MAXC, xR));\n    yB = max(0, min(MAXC, yB));\n    yT = max(0, min(MAXC, yT));\n    if (xL > xR) swap(xL, xR);\n    if (yB > yT) swap(yB, yT);\n    if (xL == xR) { if (xR < MAXC) xR++; else xL--; }\n    if (yB == yT) { if (yT < MAXC) yT++; else yB--; }\n}\n\nstatic inline long long exactLScore(const RangeSum2D &ds,\n                                    int xL, int xR, int yB, int yT,\n                                    int xM, int yM, int type) {\n    // Requires xL < xM < xR and yB < yM < yT\n    // type:\n    // 0: keep bottom + right-upper\n    // 1: keep bottom + left-upper\n    // 2: keep top + right-lower\n    // 3: keep top + left-lower\n    // We use union of two rectangles minus overlap line y=yM.\n    if (!(xL < xM && xM < xR && yB < yM && yM < yT)) return LLONG_MIN / 4;\n\n    auto rect = [&](int a, int b, int c, int d) -> long long {\n        if (a > b || c > d) return 0LL;\n        return ds.sumRect(a, b, c, d);\n    };\n\n    if (type == 0) {\n        // [xL..xR]x[yB..yM]  U  [xM..xR]x[yM..yT]\n        long long s1 = rect(xL, xR, yB, yM);\n        long long s2 = rect(xM, xR, yM, yT);\n        long long ov = rect(xM, xR, yM, yM);\n        return s1 + s2 - ov;\n    } else if (type == 1) {\n        // [xL..xR]x[yB..yM]  U  [xL..xM]x[yM..yT]\n        long long s1 = rect(xL, xR, yB, yM);\n        long long s2 = rect(xL, xM, yM, yT);\n        long long ov = rect(xL, xM, yM, yM);\n        return s1 + s2 - ov;\n    } else if (type == 2) {\n        // [xL..xR]x[yM..yT]  U  [xM..xR]x[yB..yM]\n        long long s1 = rect(xL, xR, yM, yT);\n        long long s2 = rect(xM, xR, yB, yM);\n        long long ov = rect(xM, xR, yM, yM);\n        return s1 + s2 - ov;\n    } else {\n        // type==3:\n        // [xL..xR]x[yM..yT]  U  [xL..xM]x[yB..yM]\n        long long s1 = rect(xL, xR, yM, yT);\n        long long s2 = rect(xL, xM, yB, yM);\n        long long ov = rect(xL, xM, yM, yM);\n        return s1 + s2 - ov;\n    }\n}\n\nstatic inline vector<int> sampleInRange(const vector<int> &sortedUniq, int L, int R, int cap, bool strictInside = false) {\n    if (L > R) swap(L, R);\n    int lo = strictInside ? L + 1 : L;\n    int hi = strictInside ? R - 1 : R;\n    lo = max(lo, 0);\n    hi = min(hi, MAXC);\n    if (lo > hi) return {};\n    auto itL = lower_bound(sortedUniq.begin(), sortedUniq.end(), lo);\n    auto itR = upper_bound(sortedUniq.begin(), sortedUniq.end(), hi);\n    vector<int> cand(itL, itR);\n    if ((int)cand.size() <= cap) return cand;\n    // deterministic downsample by stride\n    vector<int> out;\n    out.reserve(cap);\n    int n = (int)cand.size();\n    for (int i = 0; i < cap; i++) {\n        out.push_back(cand[(long long)i * n / cap]);\n    }\n    sort(out.begin(), out.end());\n    out.erase(unique(out.begin(), out.end()), out.end());\n    return out;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    cin >> N;\n    vector<Pt> pts;\n    pts.reserve(2 * N);\n    for (int i = 0; i < N; i++) {\n        int x, y; cin >> x >> y;\n        pts.push_back({x, y, +1});\n    }\n    for (int i = 0; i < N; i++) {\n        int x, y; cin >> x >> y;\n        pts.push_back({x, y, -1});\n    }\n\n    RangeSum2D ds(pts);\n\n    // candidate coordinate universe: {0,MAXC} U {point coords} U {\u00b11}\n    vector<int> xs, ys;\n    xs.reserve(2 * N);\n    ys.reserve(2 * N);\n    for (auto &p : pts) { xs.push_back(p.x); ys.push_back(p.y); }\n    sort(xs.begin(), xs.end());\n    xs.erase(unique(xs.begin(), xs.end()), xs.end());\n    sort(ys.begin(), ys.end());\n    ys.erase(unique(ys.begin(), ys.end()), ys.end());\n\n    auto buildAllCand = [&](const vector<int>& base) {\n        vector<int> all;\n        all.reserve(base.size() * 3 + 2);\n        all.push_back(0);\n        all.push_back(MAXC);\n        for (int v : base) {\n            all.push_back(v);\n            if (0 <= v - 1) all.push_back(v - 1);\n            if (v + 1 <= MAXC) all.push_back(v + 1);\n        }\n        sort(all.begin(), all.end());\n        all.erase(unique(all.begin(), all.end()), all.end());\n        return all;\n    };\n\n    vector<int> allX = buildAllCand(xs);\n    vector<int> allY = buildAllCand(ys);\n\n    // Coarse grid for candidate outer rectangles\n    // Grid sum uses cell weights; then refined with exact ds.\n    const int G = 150;\n    const int SZ = MAXC + 1; // 100001\n\n    auto cellOf = [&](int v) -> int {\n        return (int)((long long)v * G / SZ); // 0..G-1\n    };\n    auto lowerBoundCell = [&](int c) -> int { // inclusive\n        return (int)((long long)c * SZ / G);\n    };\n    auto upperBoundCell = [&](int c) -> int { // inclusive\n        long long ub = (long long)(c + 1) * SZ / G - 1;\n        ub = max(0LL, min((long long)MAXC, ub));\n        return (int)ub;\n    };\n\n    vector<vector<int>> A(G, vector<int>(G, 0));\n    for (auto &p : pts) {\n        int cx = cellOf(p.x);\n        int cy = cellOf(p.y);\n        A[cx][cy] += p.w;\n    }\n\n    auto kadane = [&](const vector<long long>& arr)->tuple<long long,int,int>{\n        long long cur = arr[0], best = arr[0];\n        int curL = 0, bestL = 0, bestR = 0;\n        for (int i = 1; i < G; i++) {\n            if (cur < 0) { cur = arr[i]; curL = i; }\n            else cur += arr[i];\n            if (cur > best) { best = cur; bestL = curL; bestR = i; }\n        }\n        return {best, bestL, bestR};\n    };\n\n    struct CellRect { long long sum; int x0,x1,y0,y1; };\n    const int TOPK = 8;\n\n    // keep top K by sum in a min-heap\n    struct MinCmp { bool operator()(const CellRect& a, const CellRect& b) const { return a.sum > b.sum; } };\n    priority_queue<CellRect, vector<CellRect>, MinCmp> minpq;\n\n    vector<long long> temp(G);\n    for (int x0 = 0; x0 < G; x0++) {\n        fill(temp.begin(), temp.end(), 0LL);\n        for (int x1 = x0; x1 < G; x1++) {\n            for (int y = 0; y < G; y++) temp[y] += A[x1][y];\n            auto [s, yl, yr] = kadane(temp);\n            CellRect cr{s, x0, x1, yl, yr};\n            if ((int)minpq.size() < TOPK) minpq.push(cr);\n            else if (cr.sum > minpq.top().sum) { minpq.pop(); minpq.push(cr); }\n        }\n    }\n\n    vector<CellRect> candCells;\n    while (!minpq.empty()) { candCells.push_back(minpq.top()); minpq.pop(); }\n    sort(candCells.begin(), candCells.end(), [](auto &a, auto &b){ return a.sum > b.sum; });\n\n    mt19937_64 rng((uint64_t)chrono::high_resolution_clock::now().time_since_epoch().count());\n\n    long long bestScore = LLONG_MIN;\n    bool bestIsL = false;\n    int best_xL=0, best_xR=0, best_yB=0, best_yT=0;\n    int best_xM=0, best_yM=0, best_type=0;\n\n    auto considerRect = [&](int xL,int xR,int yB,int yT){\n        normalizeRect(xL,xR,yB,yT);\n        long long d = ds.sumRect(xL,xR,yB,yT);\n        if (d > bestScore) {\n            bestScore = d;\n            bestIsL = false;\n            best_xL=xL; best_xR=xR; best_yB=yB; best_yT=yT;\n        }\n    };\n\n    auto considerL = [&](int xL,int xR,int yB,int yT,int xM,int yM,int type){\n        if (!(xL < xM && xM < xR && yB < yM && yM < yT)) return;\n        long long d = exactLScore(ds, xL,xR,yB,yT,xM,yM,type);\n        if (d > bestScore) {\n            bestScore = d;\n            bestIsL = true;\n            best_xL=xL; best_xR=xR; best_yB=yB; best_yT=yT;\n            best_xM=xM; best_yM=yM; best_type=type;\n        }\n    };\n\n    // local improvement for rectangles\n    auto localImproveRect = [&](int xL,int xR,int yB,int yT){\n        normalizeRect(xL,xR,yB,yT);\n        int curL=xL, curR=xR, curB=yB, curT=yT;\n        long long curBest = ds.sumRect(curL,curR,curB,curT);\n\n        const int RANGE = 5500;\n        const int CAP = 140;\n\n        vector<int> candX = sampleInRange(allX, curL - RANGE, curR + RANGE, CAP, false);\n        vector<int> candY = sampleInRange(allY, curB - RANGE, curT + RANGE, CAP, false);\n\n        // ensure current boundaries included\n        candX.push_back(curL); candX.push_back(curR);\n        candY.push_back(curB); candY.push_back(curT);\n        sort(candX.begin(), candX.end()); candX.erase(unique(candX.begin(), candX.end()), candX.end());\n        sort(candY.begin(), candY.end()); candY.erase(unique(candY.begin(), candY.end()), candY.end());\n\n        auto randInt = [&](int m) { return (int)(rng() % (uint64_t)m); };\n\n        // random rectangle tries\n        int RND_TRIES = 260;\n        for (int it = 0; it < RND_TRIES; it++) {\n            int a = candX[randInt((int)candX.size())];\n            int b = candX[randInt((int)candX.size())];\n            int c = candY[randInt((int)candY.size())];\n            int d = candY[randInt((int)candY.size())];\n            int nL=min(a,b), nR=max(a,b), nB=min(c,d), nT=max(c,d);\n            if (nR - nL < 1 || nT - nB < 1) continue;\n            long long val = ds.sumRect(nL,nR,nB,nT);\n            if (val > curBest) {\n                curBest = val;\n                curL=nL; curR=nR; curB=nB; curT=nT;\n                // small update of candidate lists (optional; keep simple)\n            }\n        }\n\n        // coordinate descent (a few sweeps)\n        int sweeps = 3;\n        for (int sw = 0; sw < sweeps; sw++) {\n            bool improved = false;\n\n            // optimize xL\n            {\n                long long bestV = curBest;\n                int bestX = curL;\n                for (int nxL : candX) {\n                    if (nxL >= curR) continue;\n                    long long val = ds.sumRect(nxL, curR, curB, curT);\n                    if (val > bestV) { bestV = val; bestX = nxL; }\n                }\n                if (bestX != curL) { curL = bestX; curBest = bestV; improved = true; }\n            }\n            // optimize xR\n            {\n                long long bestV = curBest;\n                int bestX = curR;\n                for (int nxR : candX) {\n                    if (nxR <= curL) continue;\n                    long long val = ds.sumRect(curL, nxR, curB, curT);\n                    if (val > bestV) { bestV = val; bestX = nxR; }\n                }\n                if (bestX != curR) { curR = bestX; curBest = bestV; improved = true; }\n            }\n            // optimize yB\n            {\n                long long bestV = curBest;\n                int bestY = curB;\n                for (int nyB : candY) {\n                    if (nyB >= curT) continue;\n                    long long val = ds.sumRect(curL, curR, nyB, curT);\n                    if (val > bestV) { bestV = val; bestY = nyB; }\n                }\n                if (bestY != curB) { curB = bestY; curBest = bestV; improved = true; }\n            }\n            // optimize yT\n            {\n                long long bestV = curBest;\n                int bestY = curT;\n                for (int nyT : candY) {\n                    if (nyT <= curB) continue;\n                    long long val = ds.sumRect(curL, curR, curB, nyT);\n                    if (val > bestV) { bestV = val; bestY = nyT; }\n                }\n                if (bestY != curT) { curT = bestY; curBest = bestV; improved = true; }\n            }\n\n            if (!improved) break;\n        }\n\n        considerRect(curL,curR,curB,curT);\n        return array<int,4>{curL,curR,curB,curT};\n    };\n\n    // refine top grid candidates\n    vector<array<int,4>> improvedRects;\n    improvedRects.reserve(TOPK);\n\n    for (auto &cc : candCells) {\n        int xL = lowerBoundCell(cc.x0);\n        int xR = upperBoundCell(cc.x1);\n        int yB = lowerBoundCell(cc.y0);\n        int yT = upperBoundCell(cc.y1);\n        auto r = localImproveRect(xL,xR,yB,yT);\n        improvedRects.push_back(r);\n    }\n\n    // pick best few rectangles to try L-shapes\n    sort(improvedRects.begin(), improvedRects.end(), [&](auto &a, auto &b){\n        long long sa = ds.sumRect(a[0],a[1],a[2],a[3]);\n        long long sb = ds.sumRect(b[0],b[1],b[2],b[3]);\n        return sa > sb;\n    });\n    if ((int)improvedRects.size() > 5) improvedRects.resize(5);\n\n    auto tryRandomLOnRect = [&](int xL,int xR,int yB,int yT){\n        if (!(xL + 1 < xR && yB + 1 < yT)) return; // need strict inner point\n        vector<int> innerX = sampleInRange(allX, xL, xR, 90, true); // strict inside\n        vector<int> innerY = sampleInRange(allY, yB, yT, 90, true); // strict inside\n        if (innerX.empty() || innerY.empty()) return;\n\n        int TRIES = 700;\n        uniform_int_distribution<int> distType(0,3);\n\n        auto randPick = [&](const vector<int> &v)->int{\n            return v[(size_t)(rng() % (uint64_t)v.size())];\n        };\n\n        for (int it=0; it<TRIES; it++) {\n            int xM = randPick(innerX);\n            int yM = randPick(innerY);\n            int type = distType(rng);\n            considerL(xL,xR,yB,yT,xM,yM,type);\n        }\n    };\n\n    for (auto &r : improvedRects) {\n        tryRandomLOnRect(r[0],r[1],r[2],r[3]);\n    }\n\n    // Semi-exhaustive L search on the best rectangle to push further\n    if (!improvedRects.empty()) {\n        auto r = improvedRects[0];\n        int xL=r[0], xR=r[1], yB=r[2], yT=r[3];\n        if (xL + 1 < xR && yB + 1 < yT) {\n            vector<int> innerX = sampleInRange(allX, xL, xR, 60, true);\n            vector<int> innerY = sampleInRange(allY, yB, yT, 60, true);\n            if (!innerX.empty() && !innerY.empty()) {\n                for (int type=0; type<4; type++) {\n                    for (int xM : innerX) {\n                        for (int yM : innerY) {\n                            // ensure strict\n                            if (xL < xM && xM < xR && yB < yM && yM < yT) {\n                                considerL(xL,xR,yB,yT,xM,yM,type);\n                            }\n                        }\n                    }\n                }\n            }\n        }\n    }\n\n    // Output polygon (rectangle or L-shape)\n    if (!bestIsL) {\n        cout << 4 << \"\\n\";\n        cout << best_xL << \" \" << best_yB << \"\\n\";\n        cout << best_xR << \" \" << best_yB << \"\\n\";\n        cout << best_xR << \" \" << best_yT << \"\\n\";\n        cout << best_xL << \" \" << best_yT << \"\\n\";\n    } else {\n        int xL=best_xL, xR=best_xR, yB=best_yB, yT=best_yT;\n        int xM=best_xM, yM=best_yM, type=best_type;\n\n        vector<pair<int,int>> v;\n        // CCW polygons\n        if (type == 0) { // missing top-left\n            v = {{xR,yB},{xL,yB},{xL,yM},{xM,yM},{xM,yT},{xR,yT}};\n        } else if (type == 1) { // missing top-right\n            v = {{xL,yB},{xR,yB},{xR,yM},{xM,yM},{xM,yT},{xL,yT}};\n        } else if (type == 2) { // missing bottom-left\n            v = {{xM,yM},{xL,yM},{xL,yT},{xR,yT},{xR,yB},{xM,yB}};\n        } else { // type == 3, missing bottom-right\n            v = {{xM,yM},{xR,yM},{xR,yT},{xL,yT},{xL,yB},{xM,yB}};\n        }\n\n        // Safety: ensure distinct vertices\n        sort(v.begin(), v.end());\n        v.erase(unique(v.begin(), v.end()), v.end());\n        // If something went wrong and duplicates removed, fall back to rectangle.\n        if ((int)v.size() != 6) {\n            cout << 4 << \"\\n\";\n            cout << best_xL << \" \" << best_yB << \"\\n\";\n            cout << best_xR << \" \" << best_yB << \"\\n\";\n            cout << best_xR << \" \" << best_yT << \"\\n\";\n            cout << best_xL << \" \" << best_yT << \"\\n\";\n        } else {\n            // Output in the intended order (reconstruct, not sorted)\n            if (type == 0) v = {{xR,yB},{xL,yB},{xL,yM},{xM,yM},{xM,yT},{xR,yT}};\n            if (type == 1) v = {{xL,yB},{xR,yB},{xR,yM},{xM,yM},{xM,yT},{xL,yT}};\n            if (type == 2) v = {{xM,yM},{xL,yM},{xL,yT},{xR,yT},{xR,yB},{xM,yB}};\n            if (type == 3) v = {{xM,yM},{xR,yM},{xR,yT},{xL,yT},{xL,yB},{xM,yB}};\n\n            cout << 6 << \"\\n\";\n            for (auto &p : v) cout << p.first << \" \" << p.second << \"\\n\";\n        }\n    }\n\n    return 0;\n}","ahc040":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct SplitMix64 {\n    uint64_t x;\n    explicit SplitMix64(uint64_t seed) : x(seed) {}\n    uint64_t next_u64() {\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 next_int(int l, int r) { // inclusive\n        return l + (int)(next_u64() % (uint64_t)(r - l + 1));\n    }\n    double next_double() { // [0,1)\n        return (next_u64() >> 11) * (1.0 / 9007199254740992.0);\n    }\n};\n\nstatic inline long long choosePrefRotU(int i, const vector<long long>& wp, const vector<long long>& hp) {\n    // dir U: x step uses width -> minimize width\n    // rot=0 => width=wp, rot=1 => width=hp\n    return (hp[i] < wp[i]) ? 1LL : 0LL;\n}\nstatic inline long long choosePrefRotL(int i, const vector<long long>& wp, const vector<long long>& hp) {\n    // dir L: y step uses height -> minimize height\n    // rot=0 => height=hp, rot=1 => height=wp\n    return (wp[i] < hp[i]) ? 1LL : 0LL;\n}\n\nstruct Layout {\n    vector<int> rot;      // 0/1\n    vector<char> dir;     // 'U' or 'L'\n};\n\nstatic long long simulateObjBprev(const Layout& lay,\n                                   const vector<long long>& wp,\n                                   const vector<long long>& hp,\n                                   int N) {\n    // b_i = i-1 (and b_0 = -1), overlap-free guaranteed by slide simulation.\n    vector<long long> x(N), y(N), w(N), h(N);\n\n    long long W = 0, H = 0;\n    for (int i = 0; i < N; i++) {\n        if (lay.rot[i] == 0) { w[i] = wp[i]; h[i] = hp[i]; }\n        else { w[i] = hp[i]; h[i] = wp[i]; }\n\n        if (lay.dir[i] == 'U') {\n            if (i == 0) x[i] = 0;\n            else x[i] = x[i-1] + w[i-1]; // align with right edge of b=i-1\n            long long yy = 0;\n            for (int j = 0; j < i; j++) {\n                // x intervals overlap?\n                if (x[i] < x[j] + w[j] && x[j] < x[i] + w[i]) {\n                    yy = max(yy, y[j] + h[j]);\n                }\n            }\n            y[i] = yy;\n        } else { // 'L'\n            if (i == 0) y[i] = 0;\n            else y[i] = y[i-1] + h[i-1]; // align with bottom edge of b=i-1\n            long long xx = 0;\n            for (int j = 0; j < i; j++) {\n                // y intervals overlap?\n                if (y[i] < y[j] + h[j] && y[j] < y[i] + h[i]) {\n                    xx = max(xx, x[j] + w[j]);\n                }\n            }\n            x[i] = xx;\n        }\n        W = max(W, x[i] + w[i]);\n        H = max(H, y[i] + h[i]);\n    }\n    return W + H;\n}\n\nstatic long long simulateWHEvalBprev(const Layout& lay,\n                                      const vector<long long>& wp,\n                                      const vector<long long>& hp,\n                                      int N,\n                                      long long &Wout, long long &Hout) {\n    vector<long long> x(N), y(N), w(N), h(N);\n    long long W = 0, H = 0;\n\n    for (int i = 0; i < N; i++) {\n        if (lay.rot[i] == 0) { w[i] = wp[i]; h[i] = hp[i]; }\n        else { w[i] = hp[i]; h[i] = wp[i]; }\n\n        if (lay.dir[i] == 'U') {\n            if (i == 0) x[i] = 0;\n            else x[i] = x[i-1] + w[i-1];\n            long long yy = 0;\n            for (int j = 0; j < i; j++) {\n                if (x[i] < x[j] + w[j] && x[j] < x[i] + w[i]) {\n                    yy = max(yy, y[j] + h[j]);\n                }\n            }\n            y[i] = yy;\n        } else {\n            if (i == 0) y[i] = 0;\n            else y[i] = y[i-1] + h[i-1];\n            long long xx = 0;\n            for (int j = 0; j < i; j++) {\n                if (y[i] < y[j] + h[j] && y[j] < y[i] + h[i]) {\n                    xx = max(xx, x[j] + w[j]);\n                }\n            }\n            x[i] = xx;\n        }\n        W = max(W, x[i] + w[i]);\n        H = max(H, y[i] + h[i]);\n    }\n    Wout = W; Hout = H;\n    return W + H;\n}\n\n// Exact rotation optimization for the all-U chain:\n// objective = sum(width_i) + max(height_i), with width/height depend on rot.\nstatic vector<int> bestRotAllU(const vector<long long>& wp, const vector<long long>& hp) {\n    int N = (int)wp.size();\n    vector<long long> cand;\n    cand.reserve(2*N);\n    for(int i=0;i<N;i++){ cand.push_back(hp[i]); cand.push_back(wp[i]); }\n    sort(cand.begin(), cand.end());\n    cand.erase(unique(cand.begin(), cand.end()), cand.end());\n\n    const long long INF = (1LL<<62);\n    long long bestObj = INF;\n    long long bestH = cand[0];\n    vector<int> bestRot(N,0);\n\n    for(long long Hcap: cand) {\n        bool ok = true;\n        long long sumW = 0;\n        vector<int> rot(N,0);\n        for(int i=0;i<N;i++){\n            bool can0 = (hp[i] <= Hcap); // rot=0 => height=hp\n            bool can1 = (wp[i] <= Hcap); // rot=1 => height=wp\n            if(!can0 && !can1){ ok=false; break; }\n            int r;\n            long long w0 = wp[i], w1 = hp[i];\n            if(can0 && can1){\n                r = (w0 < w1) ? 0 : 1; // minimize width\n                if(w0==w1) r=0;\n            } else r = can0 ? 0 : 1;\n            rot[i]=r;\n            long long wi = (rot[i]==0 ? wp[i] : hp[i]);\n            sumW += wi;\n        }\n        if(!ok) continue;\n        long long obj = sumW + Hcap;\n        if(obj < bestObj){\n            bestObj = obj;\n            bestH = Hcap;\n            bestRot = rot;\n        }\n    }\n    (void)bestH;\n    return bestRot;\n}\n\n// Exact rotation optimization for the all-L chain:\n// objective = max(width_i) + sum(height_i)\nstatic vector<int> bestRotAllL(const vector<long long>& wp, const vector<long long>& hp) {\n    int N = (int)wp.size();\n    vector<long long> cand;\n    cand.reserve(2*N);\n    for(int i=0;i<N;i++){ cand.push_back(wp[i]); cand.push_back(hp[i]); }\n    sort(cand.begin(), cand.end());\n    cand.erase(unique(cand.begin(), cand.end()), cand.end());\n\n    const long long INF = (1LL<<62);\n    long long bestObj = INF;\n    long long bestW = cand[0];\n    vector<int> bestRot(N,0);\n\n    for(long long Wcap: cand) {\n        bool ok = true;\n        long long sumH = 0;\n        vector<int> rot(N,0);\n        for(int i=0;i<N;i++){\n            bool can0 = (wp[i] <= Wcap); // rot=0 => width=wp\n            bool can1 = (hp[i] <= Wcap); // rot=1 => width=hp\n            if(!can0 && !can1){ ok=false; break; }\n            int r;\n            long long h0 = hp[i], h1 = wp[i]; // height contributed\n            if(can0 && can1){\n                r = (h0 < h1) ? 0 : 1; // minimize height\n                if(h0==h1) r=0;\n            } else r = can0 ? 0 : 1;\n            rot[i]=r;\n            long long hi = (rot[i]==0 ? hp[i] : wp[i]);\n            sumH += hi;\n        }\n        if(!ok) continue;\n        long long obj = Wcap + sumH;\n        if(obj < bestObj){\n            bestObj = obj;\n            bestW = Wcap;\n            bestRot = rot;\n        }\n    }\n    (void)bestW;\n    return bestRot;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, T;\n    long long sigma;\n    cin >> N >> T >> sigma;\n    vector<long long> wp(N), hp(N);\n    for(int i=0;i<N;i++) cin >> wp[i] >> hp[i];\n\n    // Seed\n    uint64_t seed = 0x123456789abcdef0ULL;\n    seed ^= (uint64_t)N * 1000003ULL;\n    seed ^= (uint64_t)T * 10007ULL;\n    seed ^= (uint64_t)sigma * 911382323ULL;\n    for(int i=0;i<N;i++){\n        seed ^= (uint64_t)(wp[i] + 1000003LL*hp[i] + (i+1)*10007LL);\n        seed *= 1099511628211ULL;\n    }\n    SplitMix64 rng(seed);\n\n    // Baselines\n    Layout allU, allL;\n    allU.dir.assign(N,'U');\n    allL.dir.assign(N,'L');\n    allU.rot = bestRotAllU(wp,hp);\n    allL.rot = bestRotAllL(wp,hp);\n\n    vector<Layout> init;\n    init.push_back(allU);\n    init.push_back(allL);\n\n    // Split patterns\n    vector<int> splits = {N/4, N/2, 3*N/4};\n    for(int s: splits){\n        s = max(0, min(N, s));\n        Layout lay;\n        lay.dir.resize(N);\n        lay.rot.resize(N);\n        for(int i=0;i<N;i++){\n            lay.dir[i] = (i < s ? 'U' : 'L');\n            if(lay.dir[i]=='U') lay.rot[i] = (int)choosePrefRotU(i, wp, hp);\n            else lay.rot[i] = (int)choosePrefRotL(i, wp, hp);\n        }\n        init.push_back(lay);\n        // also reverse\n        Layout lay2 = lay;\n        for(int i=0;i<N;i++) lay2.dir[i] = (lay2.dir[i]=='U'?'L':'U');\n        for(int i=0;i<N;i++){\n            lay2.rot[i] = (lay2.dir[i]=='U' ? (int)choosePrefRotU(i,wp,hp) : (int)choosePrefRotL(i,wp,hp));\n        }\n        init.push_back(lay2);\n    }\n\n    // Alternating\n    for(int start=0; start<2; start++){\n        Layout lay;\n        lay.dir.resize(N);\n        lay.rot.resize(N);\n        for(int i=0;i<N;i++){\n            lay.dir[i] = ((i+start)%2==0 ? 'U' : 'L');\n            lay.rot[i] = (lay.dir[i]=='U' ? (int)choosePrefRotU(i,wp,hp) : (int)choosePrefRotL(i,wp,hp));\n        }\n        init.push_back(lay);\n    }\n\n    // Random initial\n    for(int k=0;k<4;k++){\n        Layout lay;\n        lay.dir.resize(N);\n        lay.rot.resize(N);\n        for(int i=0;i<N;i++){\n            lay.dir[i] = (rng.next_int(0,1)==0 ? 'U' : 'L');\n            // correlate rotation with dir preference, with some randomness\n            int pref = (lay.dir[i]=='U' ? (int)choosePrefRotU(i,wp,hp) : (int)choosePrefRotL(i,wp,hp));\n            lay.rot[i] = (rng.next_double() < 0.85 ? pref : pref^1);\n        }\n        init.push_back(lay);\n    }\n\n    // Rank init by predicted objective and pick top few to try\n    vector<pair<long long,int>> order;\n    order.reserve(init.size());\n    for(int i=0;i<(int)init.size();i++){\n        long long pred = simulateObjBprev(init[i], wp, hp, N);\n        order.push_back({pred,i});\n    }\n    sort(order.begin(), order.end());\n\n    int K = min(T, 10);\n    vector<Layout> tried;\n    tried.reserve(K);\n\n    Layout cur = init[order[0].second];\n    long long curMeas = (1LL<<62);\n\n    Layout bestLay = cur;\n    long long bestMeas = (1LL<<62);\n\n    auto outputLayout = [&](const Layout& lay){\n        cout << N << \"\\n\";\n        for(int i=0;i<N;i++){\n            int p = i;\n            int r = lay.rot[i];\n            char d = lay.dir[i];\n            int b = (i==0 ? -1 : i-1); // fixed b=i-1 for legality\n            cout << p << \" \" << r << \" \" << d << \" \" << b << \"\\n\";\n        }\n        cout << flush;\n    };\n\n    for(int ti=0; ti<K; ti++){\n        int idx = order[ti].second;\n        Layout cand = init[idx];\n        outputLayout(cand);\n        long long Wp,Hp;\n        cin >> Wp >> Hp;\n        long long meas = Wp + Hp;\n\n        tried.push_back(cand);\n\n        if(meas < bestMeas){\n            bestMeas = meas;\n            bestLay = cand;\n        }\n        if(meas < curMeas){\n            curMeas = meas;\n            cur = cand;\n        }\n    }\n\n    // For critical-index bias, compute from current best layout\n    auto computeCritical = [&](const Layout& lay, vector<int>& critical){\n        // run full simulation with arrays to identify indices reaching max W or max H (in predicted world).\n        vector<long long> x(N), y(N), w(N), h(N);\n        long long W=0,H=0;\n        for(int i=0;i<N;i++){\n            if(lay.rot[i]==0){ w[i]=wp[i]; h[i]=hp[i]; }\n            else { w[i]=hp[i]; h[i]=wp[i]; }\n            if(lay.dir[i]=='U'){\n                x[i] = (i==0?0:x[i-1]+w[i-1]);\n                long long yy=0;\n                for(int j=0;j<i;j++){\n                    if(x[i] < x[j]+w[j] && x[j] < x[i]+w[i]) yy=max(yy, y[j]+h[j]);\n                }\n                y[i]=yy;\n            } else {\n                y[i] = (i==0?0:y[i-1]+h[i-1]);\n                long long xx=0;\n                for(int j=0;j<i;j++){\n                    if(y[i] < y[j]+h[j] && y[j] < y[i]+h[i]) xx=max(xx, x[j]+w[j]);\n                }\n                x[i]=xx;\n            }\n            W=max(W, x[i]+w[i]);\n            H=max(H, y[i]+h[i]);\n        }\n        critical.clear();\n        for(int i=0;i<N;i++){\n            if(x[i]+w[i]==W || y[i]+h[i]==H) critical.push_back(i);\n        }\n        if(critical.empty()) critical.push_back(0);\n    };\n\n    vector<int> critical;\n    computeCritical(bestLay, critical);\n\n    auto mutateCandidate = [&](const Layout& base) {\n        Layout cand = base;\n\n        // sometimes do a global split reset\n        if(rng.next_double() < 0.12){\n            int s = rng.next_int(0, N);\n            for(int i=0;i<N;i++){\n                cand.dir[i] = (i < s ? 'U' : 'L');\n                cand.rot[i] = (cand.dir[i]=='U' ? (int)choosePrefRotU(i,wp,hp) : (int)choosePrefRotL(i,wp,hp));\n            }\n        } else {\n            int k = rng.next_int(1, 4);\n            for(int t=0;t<k;t++){\n                int i;\n                if(rng.next_double() < 0.55) i = critical[rng.next_int(0,(int)critical.size()-1)];\n                else i = rng.next_int(0, N-1);\n\n                int op = rng.next_int(0, 5);\n                if(op <= 1){\n                    // flip dir, maybe re-pick rotation for that dir\n                    cand.dir[i] = (cand.dir[i]=='U' ? 'L' : 'U');\n                    if(rng.next_double() < 0.7){\n                        cand.rot[i] = (cand.dir[i]=='U' ? (int)choosePrefRotU(i,wp,hp) : (int)choosePrefRotL(i,wp,hp));\n                    }\n                } else if(op <= 3){\n                    // flip rotation\n                    cand.rot[i] ^= 1;\n                } else {\n                    // set to preferred rotation for current dir\n                    cand.rot[i] = (cand.dir[i]=='U' ? (int)choosePrefRotU(i,wp,hp) : (int)choosePrefRotL(i,wp,hp));\n                    // sometimes also flip dir\n                    if(rng.next_double() < 0.25) cand.dir[i] = (cand.dir[i]=='U' ? 'L' : 'U');\n                }\n            }\n        }\n\n        return cand;\n    };\n\n    long long dummyW,dummyH;\n    for(int t = K; t < T; t++){\n        // choose base to mutate from\n        const Layout& base = (rng.next_double() < 0.75 ? bestLay : cur);\n\n        // generate several candidates and pick the best predicted\n        const int M = 8;\n        Layout bestCand = base;\n        long long bestPred = (1LL<<62);\n\n        for(int j=0;j<M;j++){\n            Layout cand = mutateCandidate(base);\n            long long pred = simulateObjBprev(cand, wp, hp, N);\n            if(pred < bestPred){\n                bestPred = pred;\n                bestCand = std::move(cand);\n            }\n        }\n\n        // Output best predicted candidate\n        outputLayout(bestCand);\n        cin >> dummyW >> dummyH;\n        long long meas = dummyW + dummyH;\n\n        if(meas < bestMeas){\n            bestMeas = meas;\n            bestLay = bestCand;\n            computeCritical(bestLay, critical);\n        }\n\n        // SA-like update of current using measured objective\n        bool accept = false;\n        if(meas <= curMeas){\n            accept = true;\n        } else {\n            // temperature schedule\n            long double prog = (long double)(t+1) / (long double)T;\n            long double temp = 200000.0L * (1.0L - prog) + 20000.0L; // tuned\n            long double delta = (long double)meas - (long double)curMeas;\n            long double prob = expl(-delta / temp);\n            if(rng.next_double() < prob) accept = true;\n        }\n\n        if(accept){\n            cur = bestCand;\n            curMeas = meas;\n        }\n    }\n\n    return 0;\n}","ahc041":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct RNG {\n    mt19937 rng;\n    RNG() {\n        rng.seed((uint32_t)chrono::steady_clock::now().time_since_epoch().count());\n    }\n    int randint(int l, int r) { // inclusive\n        uniform_int_distribution<int> dist(l, r);\n        return dist(rng);\n    }\n    template<class T>\n    void shuffle_vec(vector<T>& v) { shuffle(v.begin(), v.end(), rng); }\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<long long> A(N);\n    for (int i = 0; i < N; i++) cin >> A[i];\n\n    vector<vector<int>> g(N);\n    for (int i = 0; i < M; i++) {\n        int u, v;\n        cin >> u >> v;\n        g[u].push_back(v);\n        g[v].push_back(u);\n    }\n\n    // coordinates irrelevant for this heuristic\n    for (int i = 0; i < N; i++) {\n        int x, y;\n        cin >> x >> y;\n    }\n\n    // Precompute potential:\n    // pot[s] = sum_{u reachable within dist<=H from s} (dist(s,u)+1) * A[u]\n    vector<long long> pot(N, 0);\n    vector<int> dist(N, -1);\n    queue<int> q;\n    for (int s = 0; s < N; s++) {\n        fill(dist.begin(), dist.end(), -1);\n        while (!q.empty()) q.pop();\n        dist[s] = 0;\n        q.push(s);\n        long long ps = 0;\n        while (!q.empty()) {\n            int x = q.front(); q.pop();\n            ps += (long long)(dist[x] + 1) * A[x];\n            if (dist[x] == H) continue;\n            for (int y : g[x]) {\n                if (dist[y] != -1) continue;\n                dist[y] = dist[x] + 1;\n                q.push(y);\n            }\n        }\n        pot[s] = ps;\n    }\n\n    const double TL = 1.93; // keep some safety margin\n\n    RNG R;\n    auto start = chrono::steady_clock::now();\n\n    vector<int> bestParent(N, -1);\n    long long bestScore = LLONG_MIN;\n\n    // Buffers for BFS evaluation/claim\n    vector<char> assigned(N, 0);\n    vector<int> parent(N, -1);\n    vector<int> seen(N, 0), dtmp(N, 0);\n    int timer = 1;\n\n    // Unassigned set with O(1) deletion\n    vector<int> unass, posInUnass;\n    unass.reserve(N);\n\n    auto remove_from_unass = [&](int v) {\n        int p = posInUnass[v];\n        if (p < 0) return;\n        int w = unass.back();\n        unass[p] = w;\n        posInUnass[w] = p;\n        unass.pop_back();\n        posInUnass[v] = -1;\n    };\n\n    auto eval_root = [&](int root) -> long long {\n        timer++;\n        long long sc = 0;\n        queue<int> qq;\n        seen[root] = timer;\n        dtmp[root] = 0;\n        qq.push(root);\n        sc += A[root]; // (0+1)*A\n\n        while (!qq.empty()) {\n            int x = qq.front(); qq.pop();\n            int dx = dtmp[x];\n            if (dx == H) continue;\n            for (int y : g[x]) {\n                if (assigned[y]) continue;\n                if (seen[y] == timer) continue;\n                seen[y] = timer;\n                dtmp[y] = dx + 1;\n                sc += (long long)(dtmp[y] + 1) * A[y];\n                qq.push(y);\n            }\n        }\n        return sc;\n    };\n\n    auto claim_root = [&](int root) -> long long {\n        timer++;\n        long long sc = 0;\n        queue<int> qq;\n\n        // root\n        seen[root] = timer;\n        dtmp[root] = 0;\n        parent[root] = -1;\n        assigned[root] = 1;\n        qq.push(root);\n        sc += A[root];\n\n        // track nodes visited to remove from unass\n        vector<int> visited;\n        visited.reserve(256);\n        visited.push_back(root);\n\n        while (!qq.empty()) {\n            int x = qq.front(); qq.pop();\n            int dx = dtmp[x];\n            if (dx == H) continue;\n            for (int y : g[x]) {\n                if (assigned[y]) continue;\n                if (seen[y] == timer) continue;\n                seen[y] = timer;\n                dtmp[y] = dx + 1;\n                parent[y] = x;\n                assigned[y] = 1;\n                sc += (long long)(dtmp[y] + 1) * A[y];\n                qq.push(y);\n                visited.push_back(y);\n            }\n        }\n\n        for (int v : visited) remove_from_unass(v);\n        return sc;\n    };\n\n    auto pick_topk = [&](vector<int>& out, const vector<int>& universe, auto getter, int k) {\n        out.clear();\n        if ((int)universe.size() <= k) {\n            out = universe;\n            return;\n        }\n        vector<pair<long long,int>> arr;\n        arr.reserve(universe.size());\n        for (int v : universe) arr.push_back({getter(v), v});\n\n        k = min(k, (int)arr.size());\n        // FIX: nth_element nth must be in [begin, end)\n        nth_element(arr.begin(), arr.begin() + (k - 1), arr.end(),\n                    [&](auto &a, auto &b){ return a.first > b.first; });\n        out.reserve(k);\n        for (int i = 0; i < k; i++) out.push_back(arr[i].second);\n    };\n\n    // Number of independent attempts (bounded by TL)\n    int attempts = 0;\n    while (true) {\n        double elapsed = chrono::duration<double>(chrono::steady_clock::now() - start).count();\n        if (elapsed > TL) break;\n        attempts++;\n\n        fill(assigned.begin(), assigned.end(), 0);\n        fill(parent.begin(), parent.end(), -1);\n\n        unass.clear();\n        unass.reserve(N);\n        posInUnass.assign(N, -1);\n        for (int i = 0; i < N; i++) {\n            posInUnass[i] = i;\n            unass.push_back(i);\n        }\n\n        long long totalScore = 0;\n\n        while (!unass.empty()) {\n            int remaining = (int)unass.size();\n\n            // Tuned parameters\n            int K = min(24, remaining);\n            int topPotCnt = min(12, K);\n            int topACnt   = min(10, K - topPotCnt);\n            int randCnt   = max(0, K - topPotCnt - topACnt);\n\n            vector<int> cand;\n            cand.reserve(K);\n\n            vector<int> topPot, topA;\n            pick_topk(topPot, unass, [&](int v){ return pot[v]; }, topPotCnt);\n            pick_topk(topA,   unass, [&](int v){ return A[v]; }, topACnt);\n\n            cand.insert(cand.end(), topPot.begin(), topPot.end());\n            cand.insert(cand.end(), topA.begin(), topA.end());\n\n            // Random extras from the remaining vertices not yet in cand\n            vector<char> inCand(N, 0);\n            for (int v : cand) inCand[v] = 1;\n\n            for (int it = 0; it < 4000 && (int)cand.size() < K; it++) {\n                int idx = R.randint(0, remaining - 1);\n                int v = unass[idx];\n                if (!inCand[v]) {\n                    inCand[v] = 1;\n                    cand.push_back(v);\n                }\n            }\n\n            // If still short, fill deterministically\n            if ((int)cand.size() < K) {\n                for (int v : unass) {\n                    if (!inCand[v]) {\n                        inCand[v] = 1;\n                        cand.push_back(v);\n                        if ((int)cand.size() == K) break;\n                    }\n                }\n            }\n\n            // Evaluate candidates\n            // Sort by score desc then A desc\n            vector<pair<long long,int>> scored;\n            scored.reserve(K);\n            for (int r : cand) {\n                long long sc = eval_root(r);\n                scored.push_back({sc, r});\n            }\n\n            sort(scored.begin(), scored.end(), [&](auto &p1, auto &p2){\n                if (p1.first != p2.first) return p1.first > p2.first;\n                return A[p1.second] > A[p2.second];\n            });\n\n            // Choose among topKeep near-best roots (more exploration than before)\n            int topKeep = min(6, (int)scored.size());\n            int pickIdx = (topKeep == 1 ? 0 : R.randint(0, topKeep - 1));\n            int chosenRoot = scored[pickIdx].second;\n\n            long long gain = claim_root(chosenRoot);\n            totalScore += gain;\n        }\n\n        if (totalScore > bestScore) {\n            bestScore = totalScore;\n            bestParent = parent;\n        }\n    }\n\n    for (int i = 0; i < N; i++) {\n        cout << bestParent[i] << (i + 1 == N ? '\\n' : ' ');\n    }\n    return 0;\n}","ahc042":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int INF = 1e9;\n\nstruct Candidate {\n    vector<int> upLen, downLen, leftLen, rightLen;\n    long long T = (1LL<<60);\n    bool covered = false;\n};\n\nstruct OniCell {\n    int r, c;\n};\n\nenum Dir { UP=0, DOWN=1, LEFT=2, RIGHT=3 };\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<vector<char>> fuku(N, vector<char>(N, 0));\n    vector<OniCell> oni;\n    oni.reserve(2*N);\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (C[i][j] == 'o') fuku[i][j] = 1;\n            else if (C[i][j] == 'x') {\n                oniId[i][j] = (int)oni.size();\n                oni.push_back({i,j});\n            }\n        }\n    }\n\n    int M = (int)oni.size(); // should be 2N\n    // Precompute max safe lengths for each line-direction.\n    // upLen[j] can be at most number of rows before first fuku in column j.\n    // downLen[j] can be at most number of rows after last fuku in column j.\n    vector<int> maxUp(N), maxDown(N), maxLeft(N), maxRight(N);\n\n    for (int j = 0; j < N; j++) {\n        int first = N, last = -1;\n        for (int i = 0; i < N; i++) {\n            if (fuku[i][j]) {\n                first = min(first, i);\n                last = max(last, i);\n            }\n        }\n        maxUp[j] = first; // L <= first\n        maxDown[j] = (last == -1 ? N : (N - 1 - last)); // L <= N-1-last\n    }\n    for (int i = 0; i < N; i++) {\n        int first = N, last = -1;\n        for (int j = 0; j < N; j++) {\n            if (fuku[i][j]) {\n                first = min(first, j);\n                last = max(last, j);\n            }\n        }\n        maxLeft[i] = first; // L <= first\n        maxRight[i] = (last == -1 ? N : (N - 1 - last)); // L <= N-1-last\n    }\n\n    auto allCovered = [&](const Candidate& cand) -> bool {\n        for (int id = 0; id < M; id++) {\n            int i = oni[id].r, j = oni[id].c;\n            bool ok =\n                (i < cand.upLen[j]) ||\n                (i >= N - cand.downLen[j]) ||\n                (j < cand.leftLen[i]) ||\n                (j >= N - cand.rightLen[i]);\n            if (!ok) return false;\n        }\n        return true;\n    };\n\n    auto computeT = [&](const Candidate& cand) -> long long {\n        long long sum = 0;\n        for (int j = 0; j < N; j++) sum += cand.upLen[j] + cand.downLen[j];\n        for (int i = 0; i < N; i++) sum += cand.leftLen[i] + cand.rightLen[i];\n        return 2LL * sum;\n    };\n\n    auto prune = [&](Candidate cand, const vector<int>& orderUpDownLeftRight) -> Candidate {\n        // Local pruning: repeatedly try to decrease each variable by 1 if coverage remains.\n        // orderUpDownLeftRight encodes which variable index to try:\n        //   0..N-1: UP col\n        //   N..2N-1: DOWN col\n        //   2N..3N-1: LEFT row\n        //   3N..4N-1: RIGHT row\n        bool changed = true;\n        while (changed) {\n            changed = false;\n            for (int idx : orderUpDownLeftRight) {\n                auto canSet = [&](int newLen) -> bool {\n                    int before = newLen + 0; (void)before;\n                    // set temporarily and check coverage\n                    Candidate tmp = cand;\n                    int d = idx / N;\n                    int pos = idx % N;\n                    if (d == 0) tmp.upLen[pos] = newLen;\n                    else if (d == 1) tmp.downLen[pos] = newLen;\n                    else if (d == 2) tmp.leftLen[pos] = newLen;\n                    else tmp.rightLen[pos] = newLen;\n                    return allCovered(tmp);\n                };\n\n                int d = idx / N;\n                int pos = idx % N;\n                int curLen = 0;\n                if (d == 0) curLen = cand.upLen[pos];\n                else if (d == 1) curLen = cand.downLen[pos];\n                else if (d == 2) curLen = cand.leftLen[pos];\n                else curLen = cand.rightLen[pos];\n\n                while (curLen > 0) {\n                    int newLen = curLen - 1;\n                    if (!canSet(newLen)) break;\n                    curLen = newLen;\n                    if (d == 0) cand.upLen[pos] = newLen;\n                    else if (d == 1) cand.downLen[pos] = newLen;\n                    else if (d == 2) cand.leftLen[pos] = newLen;\n                    else cand.rightLen[pos] = newLen;\n                    changed = true;\n                }\n            }\n        }\n        cand.T = computeT(cand);\n        cand.covered = allCovered(cand);\n        return cand;\n    };\n\n    // Baseline: for each Oni, pick cheapest safe direction; then group by maximum required length.\n    auto baselineCandidate = [&]() -> Candidate {\n        Candidate cand;\n        cand.upLen.assign(N, 0);\n        cand.downLen.assign(N, 0);\n        cand.leftLen.assign(N, 0);\n        cand.rightLen.assign(N, 0);\n\n        for (int id = 0; id < M; id++) {\n            int i = oni[id].r, j = oni[id].c;\n            // required lengths\n            int reqU = (i+1 <= maxUp[j] ? i+1 : INF);\n            int reqD = (N-i <= maxDown[j] ? (N-i) : INF);\n            int reqL = (j+1 <= maxLeft[i] ? (j+1) : INF);\n            int reqR = (N-j <= maxRight[i] ? (N-j) : INF);\n\n            int best = min({reqU, reqD, reqL, reqR});\n            if (best == INF) {\n                // Should never happen due to guarantee.\n                // Fallback: do nothing here.\n                continue;\n            }\n            // tie-break order: U, D, L, R\n            if (reqU == best) cand.upLen[j] = max(cand.upLen[j], reqU);\n            else if (reqD == best) cand.downLen[j] = max(cand.downLen[j], reqD);\n            else if (reqL == best) cand.leftLen[i] = max(cand.leftLen[i], reqL);\n            else cand.rightLen[i] = max(cand.rightLen[i], reqR);\n        }\n\n        cand.T = computeT(cand);\n        cand.covered = allCovered(cand);\n        // Prune with a fixed order\n        vector<int> order;\n        order.reserve(4*N);\n        for (int idx = 0; idx < 4*N; idx++) order.push_back(idx);\n        cand = prune(cand, order);\n        return cand;\n    };\n\n    auto greedyAttempt = [&](int variant, std::mt19937& rng) -> Candidate {\n        // variant controls evaluation; all greedy attempts end with pruning.\n        vector<int> upLen(N,0), downLen(N,0), leftLen(N,0), rightLen(N,0);\n        vector<char> covered(M, 0);\n        int uncovered = M;\n\n        auto curLen = [&](Dir dir, int line) -> int {\n            if (dir == UP) return upLen[line];\n            if (dir == DOWN) return downLen[line];\n            if (dir == LEFT) return leftLen[line];\n            return rightLen[line];\n        };\n        auto& lenRef = [&](Dir dir, int line) -> int& {\n            if (dir == UP) return upLen[line];\n            if (dir == DOWN) return downLen[line];\n            if (dir == LEFT) return leftLen[line];\n            return rightLen[line];\n        };\n\n        auto computeGain = [&](Dir dir, int line, int newLen, int cur) -> int {\n            // gain = number of uncovered Oni newly removed by increasing cur -> newLen\n            int gain = 0;\n            if (cur == newLen) return 0;\n\n            if (dir == UP) {\n                int j = line;\n                for (int r = cur; r < newLen; r++) {\n                    int id = oniId[r][j];\n                    if (id != -1 && !covered[id]) gain++;\n                }\n            } else if (dir == DOWN) {\n                int j = line;\n                // newly included rows: [N-newLen, N-cur-1]\n                for (int r = N - newLen; r < N - cur; r++) {\n                    int id = oniId[r][j];\n                    if (id != -1 && !covered[id]) gain++;\n                }\n            } else if (dir == LEFT) {\n                int i = line;\n                for (int c = cur; c < newLen; c++) {\n                    int id = oniId[i][c];\n                    if (id != -1 && !covered[id]) gain++;\n                }\n            } else { // RIGHT\n                int i = line;\n                for (int c = N - newLen; c < N - cur; c++) {\n                    int id = oniId[i][c];\n                    if (id != -1 && !covered[id]) gain++;\n                }\n            }\n            return gain;\n        };\n\n        auto applyExtend = [&](Dir dir, int line, int newLen) {\n            int cur = curLen(dir, line);\n            if (newLen <= cur) return;\n            // Mark all newly covered Oni\n            if (dir == UP) {\n                int j = line;\n                for (int r = cur; r < newLen; r++) {\n                    int id = oniId[r][j];\n                    if (id != -1 && !covered[id]) {\n                        covered[id] = 1;\n                        uncovered--;\n                    }\n                }\n            } else if (dir == DOWN) {\n                int j = line;\n                for (int r = N - newLen; r < N - cur; r++) {\n                    int id = oniId[r][j];\n                    if (id != -1 && !covered[id]) {\n                        covered[id] = 1;\n                        uncovered--;\n                    }\n                }\n            } else if (dir == LEFT) {\n                int i = line;\n                for (int c = cur; c < newLen; c++) {\n                    int id = oniId[i][c];\n                    if (id != -1 && !covered[id]) {\n                        covered[id] = 1;\n                        uncovered--;\n                    }\n                }\n            } else {\n                int i = line;\n                for (int c = N - newLen; c < N - cur; c++) {\n                    int id = oniId[i][c];\n                    if (id != -1 && !covered[id]) {\n                        covered[id] = 1;\n                        uncovered--;\n                    }\n                }\n            }\n            lenRef(dir, line) = newLen;\n        };\n\n        struct Action {\n            Dir dir;\n            int line;\n            int req;\n            int gain;\n            long long costInc;\n            long double val;\n        };\n\n        while (uncovered > 0) {\n            long double bestVal = -1e100;\n            long long bestCost = (1LL<<60);\n            vector<Action> ties;\n\n            for (int id = 0; id < M; id++) {\n                if (covered[id]) continue;\n                int i = oni[id].r, j = oni[id].c;\n\n                // UP: req = i+1\n                {\n                    int req = i + 1;\n                    int cur = upLen[j];\n                    if (req <= maxUp[j] && cur < req) {\n                        int gain = computeGain(UP, j, req, cur);\n                        long long costInc = 2LL * (req - cur);\n                        long double val;\n                        if (variant == 0) val = (long double)gain / (long double)costInc;\n                        else if (variant == 1) val = (long double)gain * 1000.0L - (long double)costInc;\n                        else val = (long double)gain * gain / (long double)costInc;\n                        Action a{UP, j, req, gain, costInc, val};\n                        if (val > bestVal + 1e-15L) {\n                            bestVal = val;\n                            bestCost = costInc;\n                            ties.clear();\n                            ties.push_back(a);\n                        } else if (fabsl(val - bestVal) <= 1e-15L) {\n                            if (costInc < bestCost) {\n                                bestCost = costInc;\n                                ties.clear();\n                                ties.push_back(a);\n                            } else if (costInc == bestCost) {\n                                ties.push_back(a);\n                            } else {\n                                ties.push_back(a); // keep; tie list will be pruned by random pick\n                            }\n                        }\n                    }\n                }\n                // DOWN: req = N-i\n                {\n                    int req = N - i;\n                    int cur = downLen[j];\n                    if (req <= maxDown[j] && cur < req) {\n                        int gain = computeGain(DOWN, j, req, cur);\n                        long long costInc = 2LL * (req - cur);\n                        long double val;\n                        if (variant == 0) val = (long double)gain / (long double)costInc;\n                        else if (variant == 1) val = (long double)gain * 1000.0L - (long double)costInc;\n                        else val = (long double)gain * gain / (long double)costInc;\n                        Action a{DOWN, j, req, gain, costInc, val};\n                        if (val > bestVal + 1e-15L) {\n                            bestVal = val;\n                            bestCost = costInc;\n                            ties.clear();\n                            ties.push_back(a);\n                        } else if (fabsl(val - bestVal) <= 1e-15L) {\n                            if (costInc < bestCost) {\n                                bestCost = costInc;\n                                ties.clear();\n                                ties.push_back(a);\n                            } else if (costInc == bestCost) {\n                                ties.push_back(a);\n                            } else {\n                                ties.push_back(a);\n                            }\n                        }\n                    }\n                }\n                // LEFT: req = j+1\n                {\n                    int req = j + 1;\n                    int cur = leftLen[i];\n                    if (req <= maxLeft[i] && cur < req) {\n                        int gain = computeGain(LEFT, i, req, cur);\n                        long long costInc = 2LL * (req - cur);\n                        long double val;\n                        if (variant == 0) val = (long double)gain / (long double)costInc;\n                        else if (variant == 1) val = (long double)gain * 1000.0L - (long double)costInc;\n                        else val = (long double)gain * gain / (long double)costInc;\n                        Action a{LEFT, i, req, gain, costInc, val};\n                        if (val > bestVal + 1e-15L) {\n                            bestVal = val;\n                            bestCost = costInc;\n                            ties.clear();\n                            ties.push_back(a);\n                        } else if (fabsl(val - bestVal) <= 1e-15L) {\n                            if (costInc < bestCost) {\n                                bestCost = costInc;\n                                ties.clear();\n                                ties.push_back(a);\n                            } else if (costInc == bestCost) {\n                                ties.push_back(a);\n                            } else {\n                                ties.push_back(a);\n                            }\n                        }\n                    }\n                }\n                // RIGHT: req = N-j\n                {\n                    int req = N - j;\n                    int cur = rightLen[i];\n                    if (req <= maxRight[i] && cur < req) {\n                        int gain = computeGain(RIGHT, i, req, cur);\n                        long long costInc = 2LL * (req - cur);\n                        long double val;\n                        if (variant == 0) val = (long double)gain / (long double)costInc;\n                        else if (variant == 1) val = (long double)gain * 1000.0L - (long double)costInc;\n                        else val = (long double)gain * gain / (long double)costInc;\n                        Action a{RIGHT, i, req, gain, costInc, val};\n                        if (val > bestVal + 1e-15L) {\n                            bestVal = val;\n                            bestCost = costInc;\n                            ties.clear();\n                            ties.push_back(a);\n                        } else if (fabsl(val - bestVal) <= 1e-15L) {\n                            if (costInc < bestCost) {\n                                bestCost = costInc;\n                                ties.clear();\n                                ties.push_back(a);\n                            } else if (costInc == bestCost) {\n                                ties.push_back(a);\n                            } else {\n                                ties.push_back(a);\n                            }\n                        }\n                    }\n                }\n            }\n\n            // Choose among ties\n            Action chosen = ties[0];\n            if (!ties.empty()) {\n                if (variant == 0) {\n                    // random among best-value ties\n                    std::uniform_int_distribution<int> dist(0, (int)ties.size()-1);\n                    chosen = ties[dist(rng)];\n                } else {\n                    // deterministic: smallest costInc then largest gain\n                    chosen = *min_element(ties.begin(), ties.end(), [&](const Action& a, const Action& b){\n                        if (a.costInc != b.costInc) return a.costInc < b.costInc;\n                        if (a.gain != b.gain) return a.gain > b.gain;\n                        return a.req < b.req;\n                    });\n                }\n            }\n            applyExtend(chosen.dir, chosen.line, chosen.req);\n        }\n\n        Candidate cand;\n        cand.upLen = upLen;\n        cand.downLen = downLen;\n        cand.leftLen = leftLen;\n        cand.rightLen = rightLen;\n        cand.T = computeT(cand);\n        cand.covered = allCovered(cand);\n\n        // prune\n        vector<int> order;\n        order.reserve(4*N);\n        // fixed order for stability\n        for (int idx = 0; idx < 4*N; idx++) order.push_back(idx);\n        cand = prune(cand, order);\n        return cand;\n    };\n\n    Candidate best = baselineCandidate();\n\n    // Greedy attempts (bounded)\n    // N=20 => T limit is 1600, baseline should already be feasible, but we still improve score.\n    auto tryGreedy = [&](int variant, int tries) {\n        std::mt19937 rng(1234567 + variant*1000);\n        for (int t = 0; t < tries; t++) {\n            Candidate cand = greedyAttempt(variant, rng);\n            long long Tlimit = 4LL * N * N;\n            if (!cand.covered) continue;\n            if (cand.T > Tlimit) continue;\n            if (cand.T < best.T) best = cand;\n            // advance RNG\n            rng();\n        }\n    };\n\n    tryGreedy(0, 18);\n    tryGreedy(1, 6);\n    tryGreedy(2, 6);\n\n    // Output operations according to best lengths.\n    // Ensure within limit\n    long long Tlimit = 4LL * N * N;\n    if (!best.covered || best.T > Tlimit) {\n        // This should not happen; baseline should always be feasible.\n        // As a last resort, just output baseline without further pruning (but we already pruned).\n        best = baselineCandidate();\n    }\n\n    vector<pair<char,int>> ops;\n    ops.reserve((size_t)best.T);\n\n    for (int j = 0; j < N; j++) {\n        int L = best.upLen[j];\n        if (L > 0) {\n            for (int k = 0; k < L; k++) ops.push_back({'U', j});\n            for (int k = 0; k < L; k++) ops.push_back({'D', j});\n        }\n        int R = best.downLen[j];\n        if (R > 0) {\n            for (int k = 0; k < R; k++) ops.push_back({'D', j});\n            for (int k = 0; k < R; k++) ops.push_back({'U', j});\n        }\n    }\n    for (int i = 0; i < N; i++) {\n        int L = best.leftLen[i];\n        if (L > 0) {\n            for (int k = 0; k < L; k++) ops.push_back({'L', i});\n            for (int k = 0; k < L; k++) ops.push_back({'R', i});\n        }\n        int R = best.rightLen[i];\n        if (R > 0) {\n            for (int k = 0; k < R; k++) ops.push_back({'R', i});\n            for (int k = 0; k < R; k++) ops.push_back({'L', i});\n        }\n    }\n\n    if ((long long)ops.size() > Tlimit) {\n        // Should not happen; but safeguard\n        ops.resize((size_t)Tlimit);\n    }\n\n    cout << ops.size() << \"\\n\";\n    for (auto &[ch, p] : ops) {\n        cout << ch << \" \" << p << \"\\n\";\n    }\n    return 0;\n}","ahc044":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int MAXN = 100;\nstatic constexpr int L_CONST = 500000;\n\nstruct State {\n    long long err;\n    array<int, MAXN> cnt{};\n    array<int, MAXN> oddUse{};\n    array<int, MAXN> evenUse{};\n};\n\nstatic inline long long calcErrFromCnt(const array<int, MAXN>& cnt, const array<int, MAXN>& T, int N) {\n    long long e = 0;\n    for (int i = 0; i < N; i++) e += llabs((long long)cnt[i] - (long long)T[i]);\n    return e;\n}\n\nstatic long long simulate(const vector<int>& a, const vector<int>& b,\n                           const array<int, MAXN>& T,\n                           int N, int L,\n                           State &st) {\n    st.cnt.fill(0);\n    st.oddUse.fill(0);\n    st.evenUse.fill(0);\n\n    int x = 0;\n    st.cnt[x] = 1;\n    for (int week = 2; week <= L; week++) {\n        if (st.cnt[x] & 1) {\n            st.oddUse[x]++;\n            x = a[x];\n        } else {\n            st.evenUse[x]++;\n            x = b[x];\n        }\n        st.cnt[x]++;\n    }\n    st.err = calcErrFromCnt(st.cnt, T, N);\n    return st.err;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, L;\n    cin >> N >> L;\n    array<int, MAXN> T{};\n    for (int i = 0; i < N; i++) cin >> T[i];\n\n    // RNG\n    mt19937_64 rng((uint64_t)chrono::high_resolution_clock::now().time_since_epoch().count());\n\n    // Choose destination using residual rem (bigger is more desirable).\n    auto chooseCandidate = [&](const vector<long long>& rem) -> int {\n        const int K = min(25, N);\n        vector<pair<long long,int>> v;\n        v.reserve(N);\n        for (int i = 0; i < N; i++) v.push_back({rem[i], i});\n        nth_element(v.begin(), v.begin() + K, v.end(),\n                    [&](auto &p, auto &q){ return p.first > q.first; });\n        v.resize(K);\n        long long mn = v[0].first, mx = v[0].first;\n        for (auto &p : v) { mn = min(mn, p.first); mx = max(mx, p.first); }\n        long long offset = -mn + 1; // make weights positive\n        vector<long long> w(K);\n        long long sumw = 0;\n        for (int i = 0; i < K; i++) {\n            w[i] = v[i].first + offset;\n            if (w[i] < 1) w[i] = 1;\n            sumw += w[i];\n        }\n        uniform_int_distribution<long long> dist(1, sumw);\n        long long r = dist(rng);\n        for (int i = 0; i < K; i++) {\n            if (r <= w[i]) return v[i].second;\n            r -= w[i];\n        }\n        return v.back().second;\n    };\n\n    // Randomized greedy constructor (similar spirit to yours, but slightly stronger).\n    auto buildMapping = [&](int seedOffset) -> pair<long long, pair<vector<int>, vector<int>>> {\n        // unique seed per build\n        // (We can't reseed rng globally safely; we'll just use it as-is and vary behavior via seedOffset.)\n        vector<int> a(N, -1), b(N, -1);\n        vector<long long> rem(N);\n        for (int i = 0; i < N; i++) rem[i] = T[i];\n\n        array<int, MAXN> cnt{};\n        cnt.fill(0);\n\n        int x = 0;\n        cnt[x] = 1;\n        rem[x]--;\n\n        for (int week = 2; week <= L; week++) {\n            if (cnt[x] & 1) {\n                if (a[x] == -1) {\n                    // small random perturbation by swapping a little preference\n                    int y = chooseCandidate(rem);\n                    if ((seedOffset + week) % 17 == 0) {\n                        // diversify: sometimes pick a random among top 10 by rem\n                        vector<pair<long long,int>> v;\n                        v.reserve(N);\n                        for (int i = 0; i < N; i++) v.push_back({rem[i], i});\n                        sort(v.begin(), v.end(), [&](auto &p, auto &q){ return p.first > q.first; });\n                        int R = min(10, N);\n                        uniform_int_distribution<int> d(0, R-1);\n                        y = v[d(rng)].second;\n                    }\n                    a[x] = y;\n                }\n                x = a[x];\n            } else {\n                if (b[x] == -1) {\n                    int y = chooseCandidate(rem);\n                    if ((seedOffset + week) % 23 == 0) {\n                        vector<pair<long long,int>> v;\n                        v.reserve(N);\n                        for (int i = 0; i < N; i++) v.push_back({rem[i], i});\n                        sort(v.begin(), v.end(), [&](auto &p, auto &q){ return p.first > q.first; });\n                        int R = min(10, N);\n                        uniform_int_distribution<int> d(0, R-1);\n                        y = v[d(rng)].second;\n                    }\n                    b[x] = y;\n                }\n                x = b[x];\n            }\n            cnt[x]++;\n            rem[x]--;\n        }\n\n        for (int i = 0; i < N; i++) {\n            if (a[i] == -1) a[i] = 0;\n            if (b[i] == -1) b[i] = 0;\n        }\n\n        State st;\n        long long err = simulate(a, b, T, N, L, st);\n        return {err, {std::move(a), std::move(b)}};\n    };\n\n    // Time control\n    using Clock = chrono::steady_clock;\n    auto start = Clock::now();\n    auto elapsed = [&]() -> double {\n        return chrono::duration<double>(Clock::now() - start).count();\n    };\n    const double TL = 1.95; // leave a bit of margin\n\n    long long bestErr = (1LL<<62);\n    vector<int> bestA(N, 0), bestB(N, 0);\n\n    // Initial restarts\n    for (int it = 0; it < 40 && elapsed() < TL * 0.35; it++) {\n        auto [err, ab] = buildMapping(it * 100 + 7);\n        if (err < bestErr) {\n            bestErr = err;\n            bestA = std::move(ab.first);\n            bestB = std::move(ab.second);\n        }\n    }\n\n    // Simulated annealing\n    vector<int> curA = bestA, curB = bestB;\n\n    State curSt, newSt;\n    long long curErr = simulate(curA, curB, T, N, L, curSt);\n    bestErr = min(bestErr, curErr);\n\n    // residual arrays (computed from curSt.cnt)\n    auto computeResidualOrder = [&](const State& st) {\n        vector<pair<int,int>> under; under.reserve(N);\n        vector<pair<int,int>> all; all.reserve(N);\n        for (int i = 0; i < N; i++) {\n            int r = T[i] - st.cnt[i];\n            all.push_back({abs(r), i});\n            if (r > 0) under.push_back({r, i});\n        }\n        sort(under.begin(), under.end(), [&](auto &p, auto &q){ return p.first > q.first; });\n        sort(all.begin(), all.end(), [&](auto &p, auto &q){ return p.first > q.first; });\n        return pair<vector<pair<int,int>>, vector<pair<int,int>>>(under, all);\n    };\n\n    vector<pair<int,int>> underList, allAbsList;\n\n    size_t iter = 0;\n    while (elapsed() < TL) {\n        iter++;\n\n        // compute residual lists occasionally\n        if ((iter & 3) == 1) {\n            auto lists = computeResidualOrder(curSt);\n            underList = std::move(lists.first);\n            allAbsList = std::move(lists.second);\n        }\n\n        // choose i with roulette on abs residual (approx)\n        int i = 0;\n        {\n            long long sumAbs = 0;\n            array<long long, MAXN> absw{};\n            for (int k = 0; k < N; k++) {\n                long long r = (long long)T[k] - (long long)curSt.cnt[k];\n                long long w = llabs(r);\n                absw[k] = w;\n                sumAbs += w;\n            }\n            if (sumAbs == 0) {\n                i = uniform_int_distribution<int>(0, N-1)(rng);\n            } else {\n                uniform_int_distribution<long long> dist(1, sumAbs);\n                long long r = dist(rng);\n                for (int k = 0; k < N; k++) {\n                    if (r <= absw[k]) { i = k; break; }\n                    r -= absw[k];\n                }\n            }\n        }\n\n        // choose which edge to modify (a[i] if oddUse dominates)\n        bool changeAedge = true;\n        int ou = curSt.oddUse[i];\n        int eu = curSt.evenUse[i];\n        if (ou + eu == 0) {\n            changeAedge = (uniform_int_distribution<int>(0,1)(rng) == 0);\n        } else {\n            long long r = (long long)uniform_int_distribution<int>(0, 1000000)(rng);\n            changeAedge = (r % (ou + eu) < ou);\n        }\n\n        // choose destination j among underrepresented (prefer positive residual)\n        int curDest = changeAedge ? curA[i] : curB[i];\n\n        int j = curDest;\n        if (!underList.empty()) {\n            int K = min(20, (int)underList.size());\n            // pick among top K with weights proportional to (need+1)\n            long long sumw = 0;\n            for (int t = 0; t < K; t++) sumw += (long long)underList[t].first + 1;\n            uniform_int_distribution<long long> dist(1, sumw);\n            long long r = dist(rng);\n            for (int t = 0; t < K; t++) {\n                long long w = (long long)underList[t].first + 1;\n                if (r <= w) { j = underList[t].second; break; }\n                r -= w;\n            }\n        } else {\n            // fallback: pick from top abs residual indices\n            int K = min(20, (int)allAbsList.size());\n            j = allAbsList[uniform_int_distribution<int>(0, K-1)(rng)].second;\n        }\n\n        // make sure it's actually a change if possible\n        if (N > 1 && j == curDest) {\n            j = (j + 1) % N;\n        }\n\n        // propose change\n        vector<int> aTry = curA;\n        vector<int> bTry = curB;\n\n        if (changeAedge) aTry[i] = j;\n        else bTry[i] = j;\n\n        // occasional double-edge move to escape\n        if (uniform_int_distribution<int>(0, 9)(rng) == 0) {\n            int i2 = allAbsList.empty() ? uniform_int_distribution<int>(0, N-1)(rng)\n                                        : allAbsList[uniform_int_distribution<int>(0, min(30, N)-1)(rng)].second;\n            bool changeA2 = (uniform_int_distribution<int>(0,1)(rng) == 0);\n\n            int dest2 = changeA2 ? aTry[i2] : bTry[i2];\n            int needJ = dest2;\n            if (!underList.empty()) {\n                int K = min(20, (int)underList.size());\n                needJ = underList[uniform_int_distribution<int>(0, K-1)(rng)].second;\n            } else {\n                needJ = allAbsList[uniform_int_distribution<int>(0, min(30, N)-1)(rng)].second;\n            }\n            if (N > 1 && needJ == dest2) needJ = (needJ + 2) % N;\n\n            if (changeA2) aTry[i2] = needJ;\n            else bTry[i2] = needJ;\n        }\n\n        long long newErr = simulate(aTry, bTry, T, N, L, newSt);\n\n        // temperature schedule\n        double frac = elapsed() / TL;\n        double temp = 50000.0 * (1.0 - frac) + 2000.0; // decreases over time\n\n        bool accept = false;\n        if (newErr <= curErr) accept = true;\n        else {\n            double diff = (double)(curErr - newErr); // negative\n            double prob = exp(diff / temp); // exp(-delta/temp)\n            double u = uniform_real_distribution<double>(0.0, 1.0)(rng);\n            if (u < prob) accept = true;\n        }\n\n        if (accept) {\n            curA.swap(aTry);\n            curB.swap(bTry);\n            curErr = newErr;\n            curSt = std::move(newSt);\n            if (curErr < bestErr) {\n                bestErr = curErr;\n                bestA = curA;\n                bestB = curB;\n            }\n        }\n    }\n\n    // Output\n    for (int i = 0; i < N; i++) {\n        cout << bestA[i] << ' ' << bestB[i] << '\\n';\n    }\n    return 0;\n}","ahc045":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\n\nstruct DSU {\n    vector<int> p, r;\n    DSU(int n=0){ init(n); }\n    void init(int n){\n        p.resize(n);\n        r.assign(n,0);\n        iota(p.begin(), p.end(), 0);\n    }\n    int find(int x){ return p[x]==x? x : p[x]=find(p[x]); }\n    bool unite(int a,int b){\n        a=find(a); b=find(b);\n        if(a==b) return false;\n        if(r[a]<r[b]) swap(a,b);\n        p[b]=a;\n        if(r[a]==r[b]) r[a]++;\n        return true;\n    }\n};\n\nstatic inline uint64_t morton2d(uint32_t x, uint32_t y) {\n    // x,y in [0,2^14)\n    uint64_t z = 0;\n    for (uint32_t i = 0; i < 14; i++) {\n        z |= (uint64_t)((x >> i) & 1u) << (2 * i + 1);\n        z |= (uint64_t)((y >> i) & 1u) << (2 * i);\n    }\n    return z;\n}\n\n// rectangle lower bound squared distance between city a and b\nstatic inline ll rectLowerBoundSq(\n    int a, int b,\n    const vector<int>& lx, const vector<int>& rx,\n    const vector<int>& ly, const vector<int>& ry\n) {\n    ll dx = 0;\n    if (rx[a] < lx[b]) dx = (ll)lx[b] - rx[a];\n    else if (rx[b] < lx[a]) dx = (ll)lx[a] - rx[b];\n\n    ll dy = 0;\n    if (ry[a] < ly[b]) dy = (ll)ly[b] - ry[a];\n    else if (ry[b] < ly[a]) dy = (ll)ly[a] - ry[b];\n\n    return dx * dx + dy * dy;\n}\n\nstatic vector<int> reorderNNProxy(\n    const vector<int>& ids,\n    const vector<int>& lx, const vector<int>& rx,\n    const vector<int>& ly, const vector<int>& ry,\n    const vector<uint64_t>& mortonKey\n) {\n    int sz = (int)ids.size();\n    if (sz <= 2) return ids;\n\n    // choose a couple of starts: min/max morton\n    int smin = 0, smax = 0;\n    for (int i = 1; i < sz; i++) {\n        if (mortonKey[ids[i]] < mortonKey[ids[smin]]) smin = i;\n        if (mortonKey[ids[i]] > mortonKey[ids[smax]]) smax = i;\n    }\n\n    auto build = [&](int startPos) {\n        vector<char> used(sz, 0);\n        vector<int> path;\n        path.reserve(sz);\n        int cur = startPos;\n        used[cur] = 1;\n        ll total = 0;\n\n        for (int step = 0; step < sz; step++) {\n            path.push_back(ids[cur]);\n            if (step == sz - 1) break;\n            int best = -1;\n            ll bestW = (1LL<<62);\n            for (int j = 0; j < sz; j++) if (!used[j]) {\n                ll w = rectLowerBoundSq(ids[cur], ids[j], lx, rx, ly, ry);\n                if (w < bestW) bestW = w, best = j;\n            }\n            total += bestW;\n            cur = best;\n            used[cur] = 1;\n        }\n        return pair<ll, vector<int>>(total, path);\n    };\n\n    auto [t1, p1] = build(smin);\n    auto [t2, p2] = build(smax);\n    return (t2 < t1 ? p2 : p1);\n}\n\nstruct CandEdge {\n    int u, v;          // city indices\n    bool oracle;       // primary preference\n    ll w;              // proxy weight\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, Q, L, W;\n    cin >> N >> M >> Q >> L >> W;\n\n    vector<int> G(M);\n    for (int i = 0; i < M; i++) cin >> G[i];\n\n    vector<int> lx(N), rx(N), ly(N), ry(N);\n    for (int i = 0; i < N; i++) cin >> lx[i] >> rx[i] >> ly[i] >> ry[i];\n\n    vector<int> cx_i(N), cy_i(N);\n    vector<uint64_t> mortonKey(N);\n    for (int i = 0; i < N; i++) {\n        cx_i[i] = (lx[i] + rx[i]) / 2;\n        cy_i[i] = (ly[i] + ry[i]) / 2;\n        mortonKey[i] = morton2d((uint32_t)cx_i[i], (uint32_t)cy_i[i]);\n    }\n\n    // Morton sort\n    vector<int> cities(N);\n    iota(cities.begin(), cities.end(), 0);\n    sort(cities.begin(), cities.end(), [&](int a, int b){\n        if (mortonKey[a] != mortonKey[b]) return mortonKey[a] < mortonKey[b];\n        return a < b;\n    });\n\n    // Precompute adjacency proxy along Morton order\n    vector<ll> adjProxy(N-1, 0);\n    for (int i = 0; i < N-1; i++) {\n        adjProxy[i] = rectLowerBoundSq(cities[i], cities[i+1], lx, rx, ly, ry);\n    }\n    vector<ll> pref(N, 0);\n    for (int i = 0; i < N-1; i++) pref[i+1] = pref[i] + adjProxy[i];\n\n    // Greedy segment assignment of group sizes to minimize average adjProxy\n    vector<vector<int>> groupCities(M);\n    int ptr = 0;\n\n    // list of remaining group indices\n    vector<int> rem;\n    rem.reserve(M);\n    for (int i = 0; i < M; i++) rem.push_back(i);\n\n    while (!rem.empty()) {\n        int bestIdx = -1;\n        double bestAvg = 1e300;\n\n        for (int gi : rem) {\n            int sz = G[gi];\n            if (ptr + sz > N) continue;\n            // sum of adjProxy over edges inside segment [ptr..ptr+sz-1]\n            ll sum = pref[ptr + sz - 1] - pref[ptr]; // length sz-1\n            double avg = (sz <= 1 ? 0.0 : (double)sum / (double)(sz-1));\n            if (avg < bestAvg) {\n                bestAvg = avg;\n                bestIdx = gi;\n            }\n        }\n\n        int gi = bestIdx;\n        int sz = G[gi];\n        groupCities[gi].assign(cities.begin() + ptr, cities.begin() + ptr + sz);\n        ptr += sz;\n\n        rem.erase(find(rem.begin(), rem.end(), gi));\n    }\n\n    vector<vector<pair<int,int>>> roads(M);\n    int queriesUsed = 0;\n\n    for (int gi = 0; gi < M; gi++) {\n        auto base = groupCities[gi];\n        int sz = (int)base.size();\n\n        if (sz <= 1) {\n            roads[gi].clear();\n            continue;\n        }\n\n        // Reorder inside group using NN proxy\n        vector<int> ord = reorderNNProxy(base, lx, rx, ly, ry, mortonKey);\n\n        // local index mapping\n        vector<int> local(N, -1);\n        for (int i = 0; i < sz; i++) local[ord[i]] = i;\n\n        // Candidate edges\n        vector<CandEdge> cand;\n        cand.reserve((sz-1) + 6000);\n\n        auto addEdge = [&](int u, int v, bool oracle){\n            if (u == v) return;\n            if (u > v) swap(u, v);\n            ll w = rectLowerBoundSq(u, v, lx, rx, ly, ry);\n            cand.push_back({u, v, oracle, w});\n        };\n\n        // Always add chain edges\n        for (int i = 0; i + 1 < sz; i++) {\n            addEdge(ord[i], ord[i+1], false);\n        }\n\n        // Oracle queries\n        if (sz >= 3 && queriesUsed < Q) {\n            int s = min(L, sz);\n            int step = max(2, s - 1); // s>=3 => step>=2\n            for (int start = 0; start + s <= sz && queriesUsed < Q; start += step) {\n                // query subset ord[start..start+s-1]\n                cout << \"? \" << s;\n                for (int t = 0; t < s; t++) cout << ' ' << ord[start+t];\n                cout << '\\n' << flush;\n\n                // read s-1 edges\n                for (int k = 0; k < s - 1; k++) {\n                    int a, b;\n                    cin >> a >> b;\n                    addEdge(a, b, true);\n                }\n                queriesUsed++;\n            }\n        }\n\n        // Kruskal: prefer oracle edges first, then proxy weight\n        sort(cand.begin(), cand.end(), [&](const CandEdge& e1, const CandEdge& e2){\n            if (e1.oracle != e2.oracle) return e1.oracle > e2.oracle; // oracle first\n            if (e1.w != e2.w) return e1.w < e2.w;\n            if (e1.u != e2.u) return e1.u < e2.u;\n            return e1.v < e2.v;\n        });\n\n        DSU dsu(sz);\n        vector<pair<int,int>> chosen;\n        chosen.reserve(sz-1);\n\n        for (auto &e : cand) {\n            int lu = local[e.u], lv = local[e.v];\n            if (lu < 0 || lv < 0) continue;\n            if (dsu.unite(lu, lv)) {\n                int a = e.u, b = e.v;\n                if (a > b) swap(a, b);\n                chosen.push_back({a, b});\n                if ((int)chosen.size() == sz - 1) break;\n            }\n        }\n\n        // Safety fallback: if somehow not connected, use pure chain\n        if ((int)chosen.size() != sz - 1) {\n            chosen.clear();\n            for (int i = 1; i < sz; i++) {\n                int a = ord[i-1], b = ord[i];\n                if (a > b) swap(a, b);\n                chosen.push_back({a, b});\n            }\n        }\n\n        roads[gi] = std::move(chosen);\n\n        // Output order can be ord (doesn't matter)\n        groupCities[gi] = std::move(ord);\n    }\n\n    cout << \"!\" << '\\n' << flush;\n\n    for (int gi = 0; gi < M; gi++) {\n        auto &vec = groupCities[gi];\n        for (int i = 0; i < (int)vec.size(); i++) {\n            if (i) cout << ' ';\n            cout << vec[i];\n        }\n        cout << '\\n';\n        for (auto [u,v] : roads[gi]) {\n            cout << u << ' ' << v << '\\n';\n        }\n    }\n    cout << flush;\n    return 0;\n}","ahc046":"#include <bits/stdc++.h>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M;\n    cin >> N >> M;\n    vector<pair<int,int>> t(M);\n    for (int k = 0; k < M; k++) cin >> t[k].first >> t[k].second;\n\n    const int Vpos = N * N;      // 400\n    const int Vblock = Vpos + 1; // 401: 0=none, 1..Vpos = block at (idx-1)\n    const int K = M + 1;         // stage k: next target index to visit (k==M => finished)\n\n    auto posIdx = [&](int x, int y) { return x * N + y; };\n\n    vector<int> targetPosIdx(M);\n    for (int k = 0; k < M; k++) targetPosIdx[k] = posIdx(t[k].first, t[k].second);\n\n    int startPos = targetPosIdx[0];\n    // next target to visit is index 1 (since t0 is the start position)\n    int startK = (M >= 2 ? 1 : M);\n    if (startK == M) {\n        // M=1 trivial, not possible here due to constraints (M=40), but safe.\n        return 0;\n    }\n\n    // neighbors for Move/Alter\n    int dx[4] = {-1, 1, 0, 0};\n    int dy[4] = {0, 0, -1, 1};\n    vector<array<int,4>> neigh(Vpos);\n    auto inside = [&](int x, int y){ return 0 <= x && x < N && 0 <= y && y < N; };\n    for (int p = 0; p < Vpos; p++) {\n        int x = p / N, y = p % N;\n        for (int dir = 0; dir < 4; dir++) {\n            int nx = x + dx[dir], ny = y + dy[dir];\n            neigh[p][dir] = inside(nx, ny) ? posIdx(nx, ny) : -1;\n        }\n    }\n\n    // slideStop[bIdx][pIdx][dir] precomputation:\n    // where you stop when sliding from pIdx in dir with a single block at bIdx (or none if bIdx==0).\n    vector<uint16_t> slideStop((size_t)Vblock * Vpos * 4);\n    auto slideId = [&](int bIdx, int pIdx, int dir) -> size_t {\n        return ((size_t)bIdx * Vpos + pIdx) * 4 + dir;\n    };\n\n    // block cell index for each bIdx (or -1 for none)\n    vector<int> blockCell(Vblock, -1);\n    for (int b = 1; b < Vblock; b++) blockCell[b] = b - 1;\n\n    for (int p = 0; p < Vpos; p++) {\n        int x = p / N, y = p % N;\n        for (int bIdx = 0; bIdx < Vblock; bIdx++) {\n            int bx = -1, by = -1;\n            if (bIdx != 0) {\n                int bc = blockCell[bIdx];\n                bx = bc / N; by = bc % N;\n            }\n            for (int dir = 0; dir < 4; dir++) {\n                int stopX = x, stopY = y;\n                if (dir == 0) { // U\n                    if (bIdx != 0 && y == by && bx < x) stopX = bx + 1;\n                    else stopX = 0;\n                    stopY = y;\n                } else if (dir == 1) { // D\n                    if (bIdx != 0 && y == by && bx > x) stopX = bx - 1;\n                    else stopX = N - 1;\n                    stopY = y;\n                } else if (dir == 2) { // L\n                    if (bIdx != 0 && x == bx && by < y) stopY = by + 1;\n                    else stopY = 0;\n                    stopX = x;\n                } else { // R\n                    if (bIdx != 0 && x == bx && by > y) stopY = by - 1;\n                    else stopY = N - 1;\n                    stopX = x;\n                }\n                slideStop[slideId(bIdx, p, dir)] = (uint16_t)posIdx(stopX, stopY);\n            }\n        }\n    }\n\n    auto sid = [&](int k, int pIdx, int bIdx) -> int {\n        return ((k * Vpos + pIdx) * Vblock + bIdx);\n    };\n    const int S = K * Vpos * Vblock; // ~6.57 million\n\n    vector<int16_t> dist(S, (int16_t)-1);\n    vector<int> parent(S, -1);\n    vector<uint8_t> parentCode(S, 0);\n\n    int startId = sid(startK, startPos, 0);\n    dist[startId] = 0;\n\n    vector<int> q;\n    q.reserve(1'000'000);\n    q.push_back(startId);\n    size_t head = 0;\n\n    int goalId = -1;\n\n    // mapping for output\n    const char actChar[3] = {'M', 'S', 'A'};\n    const char dirChar[4] = {'U', 'D', 'L', 'R'};\n\n    while (head < q.size()) {\n        int v = q[head++];\n        int dv = dist[v];\n\n        int bIdx = v % Vblock;\n        int tmp = v / Vblock;\n        int pIdx = tmp % Vpos;\n        int k = tmp / Vpos;\n\n        if (k == M) { // finished\n            goalId = v;\n            break;\n        }\n\n        int bc = blockCell[bIdx];\n\n        for (int dir = 0; dir < 4; dir++) {\n            // 1) Move (cost 1)\n            {\n                int np = neigh[pIdx][dir];\n                if (np != -1 && (bIdx == 0 || np != bc)) {\n                    int nk = k;\n                    if (nk < M && np == targetPosIdx[nk]) nk++;\n                    int to = sid(nk, np, bIdx);\n                    if (dist[to] == -1) {\n                        dist[to] = (int16_t)(dv + 1);\n                        parent[to] = v;\n                        parentCode[to] = (uint8_t)(0 * 4 + dir); // M\n                        q.push_back(to);\n                    }\n                }\n            }\n\n            // 2) Slide (cost 1)\n            {\n                int np = (int)slideStop[slideId(bIdx, pIdx, dir)];\n                int nk = k;\n                if (nk < M && np == targetPosIdx[nk]) nk++;\n                int to = sid(nk, np, bIdx);\n                if (dist[to] == -1) {\n                    dist[to] = (int16_t)(dv + 1);\n                    parent[to] = v;\n                    parentCode[to] = (uint8_t)(1 * 4 + dir); // S\n                    q.push_back(to);\n                }\n            }\n\n            // 3) Alter (toggle adjacent block) (cost 1)\n            {\n                int ap = neigh[pIdx][dir];\n                if (ap != -1) {\n                    int nbIdx = -1;\n                    if (bIdx == 0) {\n                        nbIdx = 1 + ap; // place\n                    } else {\n                        // can only remove if adjacent cell is exactly the existing block\n                        if (ap == bc) nbIdx = 0;\n                    }\n                    if (nbIdx != -1) {\n                        int nk = k; // position unchanged\n                        int to = sid(nk, pIdx, nbIdx);\n                        if (dist[to] == -1) {\n                            dist[to] = (int16_t)(dv + 1);\n                            parent[to] = v;\n                            parentCode[to] = (uint8_t)(2 * 4 + dir); // A\n                            q.push_back(to);\n                        }\n                    }\n                }\n            }\n        }\n    }\n\n    if (goalId == -1) {\n        // Should not happen because Move-only always works within limit.\n        return 0;\n    }\n\n    // reconstruct actions\n    vector<pair<char,char>> actions;\n    int cur = goalId;\n    while (cur != startId) {\n        uint8_t code = parentCode[cur];\n        int prev = parent[cur];\n        int act = code / 4;\n        int dir = code % 4;\n        actions.push_back({actChar[act], dirChar[dir]});\n        cur = prev;\n    }\n    reverse(actions.begin(), actions.end());\n\n    // safety check for output length\n    int limit = 2 * N * M;\n    if ((int)actions.size() > limit) {\n        // Should not happen; if it does, just truncate would be illegal.\n        return 0;\n    }\n\n    for (auto [a, d] : actions) {\n        cout << a << ' ' << d << \"\\n\";\n    }\n    return 0;\n}"},"8":{"ahc001":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\n\nstruct Company { int x, y; ll r; };\nstruct Rect { int a, b, c, d; }; // [a,c) x [b,d)\nstruct Cand { int k; long double cost; };\n\nstatic inline long double cutCostLogRatio(\n    ll areaParent, ll sumRParent,\n    ll areaL, ll sumRL\n) {\n    (void)areaParent;\n    ll areaR = areaParent - areaL;\n    ll sumRR = sumRParent - sumRL;\n\n    long double dL = logl((long double)(areaL + 1)) - logl((long double)(sumRL + 1));\n    long double dR = logl((long double)(areaR + 1)) - logl((long double)(sumRR + 1));\n    return dL * dL + dR * dR;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int n;\n    cin >> n;\n    vector<Company> comp(n);\n    for (int i = 0; i < n; i++) cin >> comp[i].x >> comp[i].y >> comp[i].r;\n\n    constexpr int N = 10000;\n\n    auto scoreOf = [&](const vector<Rect>& rects) -> long double {\n        long double total = 0;\n        for (int i = 0; i < n; i++) {\n            ll w = rects[i].c - rects[i].a;\n            ll h = rects[i].d - rects[i].b;\n            ll s = w * h;\n            ll ri = comp[i].r;\n            ll mn = min(ri, s), mx = max(ri, s);\n            long double t = (long double)mn / (long double)mx; // in (0,1]\n            total += 1.0L - (1.0L - t) * (1.0L - t); // 2t - t^2\n        }\n        return total;\n    };\n\n    uint64_t baseSeed = chrono::steady_clock::now().time_since_epoch().count();\n    long double bestScore = -1e100L;\n    vector<Rect> bestRects(n);\n\n    auto start = chrono::steady_clock::now();\n    const int TIME_LIMIT_MS = 4980;\n\n    // Parameters\n    const int TOPSPLIT = 32;\n    const int TOPK_CUT = 12;\n    const int DEDUP_CAP = 110;\n    const long double ORI_BETA = 2.2L;\n    const long double CUT_BETA = 2.8L;\n\n    int iter = 0;\n    while (true) {\n        int elapsed = (int)chrono::duration_cast<chrono::milliseconds>(chrono::steady_clock::now() - start).count();\n        if (elapsed >= TIME_LIMIT_MS) break;\n        iter++;\n\n        uint64_t seed = baseSeed ^ (uint64_t)iter * 0x9e3779b97f4a7c15ULL;\n        mt19937_64 rng(seed);\n\n        vector<Rect> rects(n);\n\n        auto getCandidates = [&](const vector<int>& ids,\n                                  int lx, int rx, int ly, int ry,\n                                  ll areaParent, ll sumRParent,\n                                  bool vertical) -> vector<Cand> {\n            int m = (int)ids.size();\n            if (m <= 1) return {};\n            if (areaParent <= 0) return {};\n\n            if (vertical) {\n                if (rx - lx <= 1) return {};\n                ll height = (ll)(ry - ly);\n\n                vector<int> v = ids;\n                sort(v.begin(), v.end(), [&](int a, int b){ return comp[a].x < comp[b].x; });\n\n                vector<int> xs;\n                vector<ll> sumR;\n                xs.reserve(m); sumR.reserve(m);\n                for (int i = 0; i < m; ) {\n                    int j = i;\n                    int xval = comp[v[i]].x;\n                    ll s = 0;\n                    while (j < m && comp[v[j]].x == xval) {\n                        s += comp[v[j]].r;\n                        j++;\n                    }\n                    xs.push_back(xval);\n                    sumR.push_back(s);\n                    i = j;\n                }\n                int G = (int)xs.size();\n                if (G <= 1) return {};\n\n                vector<ll> pref(G + 1, 0);\n                for (int i = 0; i < G; i++) pref[i+1] = pref[i] + sumR[i];\n\n                struct IntervalBest { int g; long double bestCost; int bestK; };\n                vector<IntervalBest> intervals;\n                intervals.reserve(G);\n\n                for (int g = 0; g < G - 1; g++) {\n                    ll sumRL = pref[g + 1];\n                    int uL = xs[g];\n                    int uR = xs[g + 1];\n\n                    int k_low = max(lx + 1, uL + 1);\n                    int k_high = min(rx - 1, uR);\n                    if (k_low > k_high) continue;\n\n                    long double k_exact = (long double)lx + (long double)sumRL / (long double)height;\n                    int k0 = (int)floor(k_exact);\n\n                    long double bestCost = numeric_limits<long double>::infinity();\n                    int bestK = k_low;\n\n                    auto tryK = [&](int k) {\n                        if (k < k_low || k > k_high) return;\n                        ll areaL = 1LL * (k - lx) * height;\n                        long double c = cutCostLogRatio(areaParent, sumRParent, areaL, sumRL);\n                        if (c < bestCost) { bestCost = c; bestK = k; }\n                    };\n\n                    tryK(k0);\n                    tryK(k0 + 1);\n                    tryK(k_low);\n                    tryK(k_high);\n\n                    intervals.push_back({g, bestCost, bestK});\n                }\n\n                if (intervals.empty()) return {};\n                sort(intervals.begin(), intervals.end(), [&](const auto& A, const auto& B){\n                    if (A.bestCost != B.bestCost) return A.bestCost < B.bestCost;\n                    return A.g < B.g;\n                });\n                if ((int)intervals.size() > TOPSPLIT) intervals.resize(TOPSPLIT);\n\n                vector<Cand> cand;\n                cand.reserve(TOPSPLIT * 14);\n\n                for (auto ib : intervals) {\n                    int g = ib.g;\n                    ll sumRL = pref[g + 1];\n                    int uL = xs[g];\n                    int uR = xs[g + 1];\n\n                    int k_low = max(lx + 1, uL + 1);\n                    int k_high = min(rx - 1, uR);\n                    if (k_low > k_high) continue;\n\n                    long double k_exact = (long double)lx + (long double)sumRL / (long double)height;\n                    int kf = (int)floor(k_exact);\n\n                    auto pushK = [&](int k) {\n                        if (k < k_low || k > k_high) return;\n                        ll areaL = 1LL * (k - lx) * height;\n                        long double c = cutCostLogRatio(areaParent, sumRParent, areaL, sumRL);\n                        cand.push_back({k, c});\n                    };\n\n                    pushK(k_low);\n                    pushK(k_high);\n                    pushK(kf);\n                    pushK(kf + 1);\n                    pushK(ib.bestK);\n                    pushK(ib.bestK - 1);\n                    pushK(ib.bestK + 1);\n\n                    // small biased random probes\n                    for (int t = 0; t < 2; t++) {\n                        long double u = (long double)(rng() % 1000000) / 1000000.0L;\n                        long double kk = k_exact + (u - 0.5L) * (long double)(k_high - k_low) / 5.0L;\n                        int k = (int)llround(kk);\n                        pushK(k);\n                    }\n                }\n\n                if (cand.empty()) return {};\n                sort(cand.begin(), cand.end(), [&](const Cand& A, const Cand& B){\n                    if (A.k != B.k) return A.k < B.k;\n                    return A.cost < B.cost;\n                });\n\n                vector<Cand> ded;\n                ded.reserve(cand.size());\n                for (auto &c : cand) {\n                    if (ded.empty() || ded.back().k != c.k) ded.push_back(c);\n                }\n                sort(ded.begin(), ded.end(), [&](const Cand& A, const Cand& B){\n                    return A.cost < B.cost;\n                });\n                if ((int)ded.size() > DEDUP_CAP) ded.resize(DEDUP_CAP);\n                // final keep unique k already; ok\n                return ded;\n\n            } else {\n                if (ry - ly <= 1) return {};\n                ll width = (ll)(rx - lx);\n\n                vector<int> v = ids;\n                sort(v.begin(), v.end(), [&](int a, int b){ return comp[a].y < comp[b].y; });\n\n                vector<int> ys;\n                vector<ll> sumR;\n                ys.reserve(m); sumR.reserve(m);\n                for (int i = 0; i < m; ) {\n                    int j = i;\n                    int yval = comp[v[i]].y;\n                    ll s = 0;\n                    while (j < m && comp[v[j]].y == yval) {\n                        s += comp[v[j]].r;\n                        j++;\n                    }\n                    ys.push_back(yval);\n                    sumR.push_back(s);\n                    i = j;\n                }\n                int G = (int)ys.size();\n                if (G <= 1) return {};\n\n                vector<ll> pref(G + 1, 0);\n                for (int i = 0; i < G; i++) pref[i+1] = pref[i] + sumR[i];\n\n                struct IntervalBest { int g; long double bestCost; int bestK; };\n                vector<IntervalBest> intervals;\n                intervals.reserve(G);\n\n                for (int g = 0; g < G - 1; g++) {\n                    ll sumRB = pref[g + 1];\n                    int uB = ys[g];\n                    int uT = ys[g + 1];\n\n                    int k_low = max(ly + 1, uB + 1);\n                    int k_high = min(ry - 1, uT);\n                    if (k_low > k_high) continue;\n\n                    long double k_exact = (long double)ly + (long double)sumRB / (long double)width;\n                    int k0 = (int)floor(k_exact);\n\n                    long double bestCost = numeric_limits<long double>::infinity();\n                    int bestK = k_low;\n\n                    auto tryK = [&](int k) {\n                        if (k < k_low || k > k_high) return;\n                        ll areaB = 1LL * (k - ly) * width;\n                        long double c = cutCostLogRatio(areaParent, sumRParent, areaB, sumRB);\n                        if (c < bestCost) { bestCost = c; bestK = k; }\n                    };\n\n                    tryK(k0);\n                    tryK(k0 + 1);\n                    tryK(k_low);\n                    tryK(k_high);\n\n                    intervals.push_back({g, bestCost, bestK});\n                }\n\n                if (intervals.empty()) return {};\n                sort(intervals.begin(), intervals.end(), [&](const auto& A, const auto& B){\n                    if (A.bestCost != B.bestCost) return A.bestCost < B.bestCost;\n                    return A.g < B.g;\n                });\n                if ((int)intervals.size() > TOPSPLIT) intervals.resize(TOPSPLIT);\n\n                vector<Cand> cand;\n                cand.reserve(TOPSPLIT * 14);\n\n                for (auto ib : intervals) {\n                    int g = ib.g;\n                    ll sumRB = pref[g + 1];\n                    int uB = ys[g];\n                    int uT = ys[g + 1];\n\n                    int k_low = max(ly + 1, uB + 1);\n                    int k_high = min(ry - 1, uT);\n                    if (k_low > k_high) continue;\n\n                    long double k_exact = (long double)ly + (long double)sumRB / (long double)width;\n                    int kf = (int)floor(k_exact);\n\n                    auto pushK = [&](int k) {\n                        if (k < k_low || k > k_high) return;\n                        ll areaB = 1LL * (k - ly) * width;\n                        long double c = cutCostLogRatio(areaParent, sumRParent, areaB, sumRB);\n                        cand.push_back({k, c});\n                    };\n\n                    pushK(k_low);\n                    pushK(k_high);\n                    pushK(kf);\n                    pushK(kf + 1);\n                    pushK(ib.bestK);\n                    pushK(ib.bestK - 1);\n                    pushK(ib.bestK + 1);\n\n                    for (int t = 0; t < 2; t++) {\n                        long double u = (long double)(rng() % 1000000) / 1000000.0L;\n                        long double kk = k_exact + (u - 0.5L) * (long double)(k_high - k_low) / 5.0L;\n                        int k = (int)llround(kk);\n                        pushK(k);\n                    }\n                }\n\n                if (cand.empty()) return {};\n                sort(cand.begin(), cand.end(), [&](const Cand& A, const Cand& B){\n                    if (A.k != B.k) return A.k < B.k;\n                    return A.cost < B.cost;\n                });\n\n                vector<Cand> ded;\n                ded.reserve(cand.size());\n                for (auto &c : cand) {\n                    if (ded.empty() || ded.back().k != c.k) ded.push_back(c);\n                }\n                sort(ded.begin(), ded.end(), [&](const Cand& A, const Cand& B){\n                    return A.cost < B.cost;\n                });\n                if ((int)ded.size() > DEDUP_CAP) ded.resize(DEDUP_CAP);\n                return ded;\n            }\n        };\n\n        function<void(int,int,int,int,const vector<int>&, ll)> build =\n            [&](int lx, int rx, int ly, int ry, const vector<int>& ids, ll sumRNode) {\n                if ((int)ids.size() == 1) {\n                    int id = ids[0];\n                    rects[id] = Rect{lx, ly, rx, ry};\n                    return;\n                }\n\n                ll areaParent = 1LL * (rx - lx) * (ry - ly);\n                if (areaParent <= 0) {\n                    // should not happen\n                    int id = ids[0];\n                    rects[id] = Rect{lx, ly, rx, ry};\n                    return;\n                }\n\n                bool canV = (rx - lx > 1);\n                bool canH = (ry - ly > 1);\n\n                vector<Cand> candV, candH;\n                if (canV) candV = getCandidates(ids, lx, rx, ly, ry, areaParent, sumRNode, true);\n                if (canH) candH = getCandidates(ids, lx, rx, ly, ry, areaParent, sumRNode, false);\n\n                bool chooseV;\n                if (candV.empty()) chooseV = false;\n                else if (candH.empty()) chooseV = true;\n                else {\n                    // softmax direction by best candidates\n                    int takeV = min(TOPK_CUT, (int)candV.size());\n                    int takeH = min(TOPK_CUT, (int)candH.size());\n                    long double Zv = 0, Zh = 0;\n                    for (int i = 0; i < takeV; i++) Zv += expl(-candV[i].cost * ORI_BETA);\n                    for (int i = 0; i < takeH; i++) Zh += expl(-candH[i].cost * ORI_BETA);\n                    if (Zv <= 0 || Zh <= 0) chooseV = (candV[0].cost <= candH[0].cost);\n                    else {\n                        long double u = (long double)(rng() % 1000000) / 1000000.0L;\n                        chooseV = (u < Zv / (Zv + Zh));\n                    }\n                }\n\n                auto splitV = [&](int k) -> bool {\n                    if (k <= lx || k >= rx) return false;\n                    vector<int> L, R;\n                    L.reserve(ids.size()); R.reserve(ids.size());\n                    ll sumL = 0, sumR = 0;\n                    for (int id : ids) {\n                        if (comp[id].x < k) { L.push_back(id); sumL += comp[id].r; }\n                        else { R.push_back(id); sumR += comp[id].r; }\n                    }\n                    if (L.empty() || R.empty()) return false;\n                    build(lx, k, ly, ry, L, sumL);\n                    build(k, rx, ly, ry, R, sumR);\n                    return true;\n                };\n\n                auto splitH = [&](int k) -> bool {\n                    if (k <= ly || k >= ry) return false;\n                    vector<int> B, T;\n                    B.reserve(ids.size()); T.reserve(ids.size());\n                    ll sumB = 0, sumT = 0;\n                    for (int id : ids) {\n                        if (comp[id].y < k) { B.push_back(id); sumB += comp[id].r; }\n                        else { T.push_back(id); sumT += comp[id].r; }\n                    }\n                    if (B.empty() || T.empty()) return false;\n                    build(lx, rx, ly, k, B, sumB);\n                    build(lx, rx, k, ry, T, sumT);\n                    return true;\n                };\n\n                if (chooseV) {\n                    int take = min(TOPK_CUT, (int)candV.size());\n                    long double sumW = 0;\n                    vector<long double> w(take);\n                    for (int i = 0; i < take; i++) {\n                        w[i] = expl(-candV[i].cost * CUT_BETA);\n                        sumW += w[i];\n                    }\n                    int pick = 0;\n                    if (sumW > 0) {\n                        long double u = (long double)(rng() % 1000000) / 1000000.0L * sumW;\n                        long double acc = 0;\n                        for (int i = 0; i < take; i++) {\n                            acc += w[i];\n                            if (u <= acc) { pick = i; break; }\n                        }\n                    }\n                    int k = candV[pick].k;\n                    if (!splitV(k)) {\n                        // last resort: deterministic feasible split by median x+1\n                        vector<int> v = ids;\n                        sort(v.begin(), v.end(), [&](int a, int b){ return comp[a].x < comp[b].x; });\n                        int k2 = min(max(comp[v[0]].x + 1, lx + 1), rx - 1);\n                        splitV(k2);\n                    }\n                } else {\n                    int take = min(TOPK_CUT, (int)candH.size());\n                    long double sumW = 0;\n                    vector<long double> w(take);\n                    for (int i = 0; i < take; i++) {\n                        w[i] = expl(-candH[i].cost * CUT_BETA);\n                        sumW += w[i];\n                    }\n                    int pick = 0;\n                    if (sumW > 0) {\n                        long double u = (long double)(rng() % 1000000) / 1000000.0L * sumW;\n                        long double acc = 0;\n                        for (int i = 0; i < take; i++) {\n                            acc += w[i];\n                            if (u <= acc) { pick = i; break; }\n                        }\n                    }\n                    int k = candH[pick].k;\n                    if (!splitH(k)) {\n                        vector<int> v = ids;\n                        sort(v.begin(), v.end(), [&](int a, int b){ return comp[a].y < comp[b].y; });\n                        int k2 = min(max(comp[v[0]].y + 1, ly + 1), ry - 1);\n                        splitH(k2);\n                    }\n                }\n            };\n\n        vector<int> ids(n);\n        iota(ids.begin(), ids.end(), 0);\n        ll sumR = 0;\n        for (auto &c : comp) sumR += c.r;\n\n        build(0, N, 0, N, ids, sumR);\n\n        long double sc = scoreOf(rects);\n        if (sc > bestScore) {\n            bestScore = sc;\n            bestRects = rects;\n        }\n    }\n\n    for (int i = 0; i < n; i++) {\n        cout << bestRects[i].a << ' ' << bestRects[i].b << ' '\n             << bestRects[i].c << ' ' << bestRects[i].d << '\\n';\n    }\n    return 0;\n}","ahc002":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const int H = 50, W = 50;\nstatic const int N = H * W;\n\nstatic inline int id(int i, int j) { return i * W + j; }\n\nstatic char dirBetween(int a, int b) {\n    int ai = a / W, aj = a % W;\n    int bi = b / W, bj = b % W;\n    if (bi == ai - 1 && bj == aj) return 'U';\n    if (bi == ai + 1 && bj == aj) return 'D';\n    if (bi == ai && bj == aj - 1) return 'L';\n    if (bi == ai && bj == aj + 1) return 'R';\n    return '?';\n}\n\nstruct RNG {\n    mt19937_64 mt;\n    RNG() : mt((uint64_t)chrono::steady_clock::now().time_since_epoch().count()) {}\n    int nextInt(int l, int r) { return uniform_int_distribution<int>(l, r)(mt); } // inclusive\n    double nextDouble() { return uniform_real_distribution<double>(0.0, 1.0)(mt); }\n};\n\nstruct Param {\n    double beta;       // weight for best future p\n    double gammaAvail;// weight for mobility (avail moves from candidate)\n    double gammaDistinct; // weight for precomputed distinct neighbors\n    double temp;      // softmax temp for suffix repair\n    double noise;     // noise magnitude for ordering/backtracking\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int si, sj;\n    cin >> si >> sj;\n\n    vector<int> tile(N);\n    for (int i = 0; i < H; i++) for (int j = 0; j < W; j++) cin >> tile[id(i, j)];\n\n    vector<int> p(N);\n    for (int i = 0; i < H; i++) for (int j = 0; j < W; j++) cin >> p[id(i, j)];\n\n    int M = 0;\n    for (int x : tile) M = max(M, x + 1);\n    int start = id(si, sj);\n\n    // neighbors on squares\n    vector<array<int,4>> neigh(N);\n    for (int i = 0; i < H; i++) for (int j = 0; j < W; j++) {\n        int v = id(i, j);\n        array<int,4> a; a.fill(-1);\n        if (i > 0) a[0] = id(i-1, j);\n        if (i+1 < H) a[1] = id(i+1, j);\n        if (j > 0) a[2] = id(i, j-1);\n        if (j+1 < W) a[3] = id(i, j+1);\n        neigh[v] = a;\n    }\n\n    // cntAdjDistinct[v] = distinct tile IDs among neighbors of v excluding same tile\n    vector<int> cntAdjDistinct(N, 0);\n    for (int v = 0; v < N; v++) {\n        int tv = tile[v];\n        int seen[4]; int sc = 0;\n        for (int k = 0; k < 4; k++) {\n            int u = neigh[v][k];\n            if (u < 0) continue;\n            int tu = tile[u];\n            if (tu == tv) continue;\n            bool ok = true;\n            for (int q = 0; q < sc; q++) if (seen[q] == tu) ok = false;\n            if (!ok) continue;\n            seen[sc++] = tu;\n        }\n        cntAdjDistinct[v] = sc;\n    }\n\n    RNG rng;\n\n    vector<int> usedStamp(M, 0);\n    int curStamp = 1;\n    auto stampReset = [&]() {\n        curStamp++;\n        if (curStamp == INT_MAX) {\n            fill(usedStamp.begin(), usedStamp.end(), 0);\n            curStamp = 1;\n        }\n    };\n    auto isUsed = [&](int tid) -> bool { return usedStamp[tid] == curStamp; };\n    auto markUsed = [&](int tid) { usedStamp[tid] = curStamp; };\n    auto unmarkUsed = [&](int tid) { usedStamp[tid] = 0; /* not necessary with stamps */ };\n\n    // compute evaluation value for moving to candidate square nb from current state\n    auto evalMove = [&](int nb, int tnb, const Param &par, const int curTile) -> double {\n        // lookahead one step from nb (after moving to nb, tile tnb becomes used, so exclude tnn==tnb)\n        int bestExit = -1;\n        int avail = 0;\n        for (int dd = 0; dd < 4; dd++) {\n            int nn = neigh[nb][dd];\n            if (nn < 0) continue;\n            int tnn = tile[nn];\n            if (tnn == tnb) continue;          // would step on same tile again\n            if (isUsed(tnn)) continue;        // forbidden because already used\n            avail++;\n            bestExit = max(bestExit, p[nn]);\n        }\n        if (bestExit < 0) bestExit = 0;\n\n        double val = (double)p[nb]\n            + par.beta * (double)bestExit\n            + par.gammaAvail * (double)avail\n            + par.gammaDistinct * (double)cntAdjDistinct[nb];\n        val += (rng.nextDouble() - 0.5) * par.noise; // tie-breaking / ordering noise\n        return val;\n    };\n\n    // DFS with backtracking and stochastic ordering (no softmax inside DFS; backtracking explores alternatives)\n    struct Frame {\n        int cand[4];\n        int sz = 0;\n        int idx = 0;\n    };\n\n    auto runDFSBacktrack = [&](const Param &par, long long timeBudgetNs,\n                               chrono::steady_clock::time_point t0,\n                               vector<int> &outPath, long long &outScore) {\n        outPath.clear();\n        outScore = -1;\n\n        stampReset();\n        markUsed(tile[start]);\n\n        vector<int> path;\n        path.reserve(M);\n        path.push_back(start);\n\n        vector<Frame> st;\n        st.reserve(M);\n\n        long long score = p[start];\n\n        auto computeCandidates = [&](int cur, Frame &fr) {\n            fr.sz = 0;\n            fr.idx = 0;\n            int tcur = tile[cur];\n            (void)tcur;\n            int tcurDummy = tcur;\n\n            for (int d = 0; d < 4; d++) {\n                int nb = neigh[cur][d];\n                if (nb < 0) continue;\n                int tnb = tile[nb];\n                if (isUsed(tnb)) continue; // cannot step on used tile again\n                fr.cand[fr.sz++] = nb;\n            }\n            // sort candidates by eval value descending (insertion sort, sz <= 4)\n            double vals[4];\n            for (int i = 0; i < fr.sz; i++) {\n                int nb = fr.cand[i];\n                vals[i] = evalMove(nb, tile[nb], par, tcurDummy);\n            }\n            for (int i = 1; i < fr.sz; i++) {\n                int x = fr.cand[i];\n                double vx = vals[i];\n                int j = i - 1;\n                while (j >= 0 && vals[j] < vx) {\n                    fr.cand[j+1] = fr.cand[j];\n                    vals[j+1] = vals[j];\n                    j--;\n                }\n                fr.cand[j+1] = x;\n                vals[j+1] = vx;\n            }\n        };\n\n        // Main DFS loop (iterative)\n        while (true) {\n            auto now = chrono::steady_clock::now();\n            long long elapsedNs = chrono::duration_cast<chrono::nanoseconds>(now - t0).count();\n            if (elapsedNs > timeBudgetNs) break;\n\n            int d = (int)path.size() - 1; // current depth, currently at path[d]\n\n            if ((int)st.size() <= d) {\n                st.emplace_back();\n                computeCandidates(path[d], st.back());\n            }\n\n            Frame &fr = st[d];\n\n            if (fr.idx >= fr.sz) {\n                // Exhausted all moves from this node; backtrack\n                st.pop_back();\n                if (d == 0) break; // finished this restart\n                int last = path.back();\n                path.pop_back();\n                score -= p[last];\n\n                // unmarking with stamps: easiest is to just increment stamp on restart;\n                // but for backtracking we need accurate state.\n                // With stamps, we can't \"unmark\" by setting to 0 without losing other marks.\n                // We'll implement unmark by keeping a stack of visited tile ids and clearing them.\n                // (Because candidate branching is tiny, overhead is fine.)\n                // We'll do it by tracking visited tiles in another stack below.\n            } else {\n                int nb = fr.cand[fr.idx++];\n\n                // mark tile nb as used, push nb\n                int tnb = tile[nb];\n                // We need proper unmark on backtrack: implement by setting usedStamp[tnb]=0\n                // (safe because stamps ensure only current stamp matters; setting to 0 clears it).\n                // Note: marking uses current stamp.\n                usedStamp[tnb] = curStamp;\n\n                path.push_back(nb);\n                score += p[nb];\n                // update best\n                if (score > outScore) {\n                    outScore = score;\n                    outPath = path;\n                }\n                // continue deeper; next loop will compute st[d+1]\n                continue;\n            }\n\n            // If we backtracked above, we must unmark the tile of the removed last node.\n            // But because we didn't track which tile to unmark at the time we popped,\n            // we do it here using tile[last] from the current path pop.\n            // However the code popped already above; adjust:\n            // We'll implement correct behavior by restructuring to always know 'last' on pop.\n            // To keep code correct, we redo DFS properly below.\n        }\n    };\n\n    // The DFS above had an unmark issue with stamps. Let's implement a correct DFS:\n    auto runDFSBacktrack2 = [&](const Param &par, long long timeBudgetNs,\n                                chrono::steady_clock::time_point t0,\n                                vector<int> &outPath, long long &outScore) {\n        outPath.clear();\n        outScore = -1;\n\n        stampReset();\n        // visited tiles stack for unmark\n        vector<int> tileStack;\n        tileStack.reserve(M);\n\n        usedStamp[tile[start]] = curStamp;\n        tileStack.push_back(tile[start]);\n\n        long long score = p[start];\n\n        vector<int> path;\n        path.reserve(M);\n        path.push_back(start);\n\n        vector<Frame> st;\n        st.reserve(M);\n\n        auto computeCandidates = [&](int cur, Frame &fr) {\n            fr.sz = 0;\n            fr.idx = 0;\n            for (int d = 0; d < 4; d++) {\n                int nb = neigh[cur][d];\n                if (nb < 0) continue;\n                int tnb = tile[nb];\n                if (usedStamp[tnb] == curStamp) continue;\n                fr.cand[fr.sz++] = nb;\n            }\n            double vals[4];\n            for (int i = 0; i < fr.sz; i++) vals[i] = 0.0;\n            int tcurDummy = tile[cur];\n            for (int i = 0; i < fr.sz; i++) {\n                int nb = fr.cand[i];\n                int tnb = tile[nb];\n                int bestExit = -1;\n                int avail = 0;\n                for (int dd = 0; dd < 4; dd++) {\n                    int nn = neigh[nb][dd];\n                    if (nn < 0) continue;\n                    int tnn = tile[nn];\n                    if (tnn == tnb) continue; // same tile, forbidden next\n                    if (usedStamp[tnn] == curStamp) continue;\n                    avail++;\n                    bestExit = max(bestExit, p[nn]);\n                }\n                if (bestExit < 0) bestExit = 0;\n                vals[i] = (double)p[nb]\n                        + par.beta * (double)bestExit\n                        + par.gammaAvail * (double)avail\n                        + par.gammaDistinct * (double)cntAdjDistinct[nb]\n                        + (rng.nextDouble() - 0.5) * par.noise;\n            }\n            // insertion sort by vals desc\n            for (int i = 1; i < fr.sz; i++) {\n                int x = fr.cand[i];\n                double vx = vals[i];\n                int j = i - 1;\n                while (j >= 0 && vals[j] < vx) {\n                    fr.cand[j+1] = fr.cand[j];\n                    vals[j+1] = vals[j];\n                    j--;\n                }\n                fr.cand[j+1] = x;\n                vals[j+1] = vx;\n            }\n        };\n\n        if (p[start] > outScore) {\n            outScore = p[start];\n            outPath = path;\n        }\n\n        while (true) {\n            auto now = chrono::steady_clock::now();\n            long long elapsedNs = chrono::duration_cast<chrono::nanoseconds>(now - t0).count();\n            if (elapsedNs > timeBudgetNs) break;\n\n            int d = (int)path.size() - 1;\n            if ((int)st.size() <= d) {\n                st.emplace_back();\n                computeCandidates(path[d], st.back());\n            }\n            Frame &fr = st[d];\n\n            if (fr.idx >= fr.sz) {\n                // backtrack one step\n                st.pop_back();\n                if (d == 0) break;\n                int lastSq = path.back();\n                path.pop_back();\n                score -= p[lastSq];\n\n                // unmark tile of lastSq\n                int tlast = tile[lastSq];\n                usedStamp[tlast] = 0;\n                tileStack.pop_back();\n                continue;\n            }\n\n            int nb = fr.cand[fr.idx++];\n            int tnb = tile[nb];\n            // mark + move\n            usedStamp[tnb] = curStamp;\n            tileStack.push_back(tnb);\n\n            path.push_back(nb);\n            score += p[nb];\n\n            if (score > outScore) {\n                outScore = score;\n                outPath = path;\n            }\n            // next depth frame will be computed in next loop iteration\n        }\n    };\n\n    auto runSuffixWalk = [&](const Param &par, long long timeBudgetNs,\n                              chrono::steady_clock::time_point t0,\n                              const vector<int> &prefixPath, int cutIdx,\n                              vector<int> &outMerged, long long baseScore) {\n        // used tiles from prefix\n        stampReset();\n\n        for (int i = 0; i <= cutIdx; i++) {\n            int sq = prefixPath[i];\n            usedStamp[tile[sq]] = curStamp;\n        }\n\n        int cur = prefixPath[cutIdx];\n        long long score = baseScore;\n\n        vector<int> suffix;\n        suffix.reserve(N);\n        suffix.push_back(cur);\n\n        int candSq[4];\n        double candVal[4];\n\n        auto computeCandList = [&](int v, int &k) {\n            k = 0;\n            int tv = tile[v];\n            (void)tv;\n            for (int d = 0; d < 4; d++) {\n                int nb = neigh[v][d];\n                if (nb < 0) continue;\n                int tnb = tile[nb];\n                if (usedStamp[tnb] == curStamp) continue; // tile must be unvisited\n                // lookahead from nb after stepping onto nb:\n                int bestExit = -1;\n                int avail = 0;\n                for (int dd = 0; dd < 4; dd++) {\n                    int nn = neigh[nb][dd];\n                    if (nn < 0) continue;\n                    int tnn = tile[nn];\n                    if (tnn == tnb) continue;\n                    if (usedStamp[tnn] == curStamp) continue;\n                    avail++;\n                    bestExit = max(bestExit, p[nn]);\n                }\n                if (bestExit < 0) bestExit = 0;\n\n                double val = (double)p[nb]\n                           + par.beta * (double)bestExit\n                           + par.gammaAvail * (double)avail\n                           + par.gammaDistinct * (double)cntAdjDistinct[nb]\n                           + (rng.nextDouble() - 0.5) * par.noise * 0.2;\n                candSq[k] = nb;\n                candVal[k] = val;\n                k++;\n            }\n            // sort descending by candVal (small k<=4)\n            for (int i = 1; i < k; i++) {\n                int xs = candSq[i];\n                double xv = candVal[i];\n                int j = i - 1;\n                while (j >= 0 && candVal[j] < xv) {\n                    candSq[j+1] = candSq[j];\n                    candVal[j+1] = candVal[j];\n                    j--;\n                }\n                candSq[j+1] = xs;\n                candVal[j+1] = xv;\n            }\n        };\n\n        while (true) {\n            auto now = chrono::steady_clock::now();\n            long long elapsedNs = chrono::duration_cast<chrono::nanoseconds>(now - t0).count();\n            if (elapsedNs > timeBudgetNs) break;\n\n            int k = 0;\n            computeCandList(cur, k);\n            if (k == 0) break;\n\n            int K = min(k, 4);\n            double mx = -1e100;\n            for (int i = 0; i < K; i++) mx = max(mx, candVal[i]);\n            double sumW = 0.0;\n            double w[4];\n            for (int i = 0; i < K; i++) {\n                w[i] = exp((candVal[i] - mx) / max(1e-6, par.temp));\n                sumW += w[i];\n            }\n            double r = rng.nextDouble() * sumW;\n            int pick = 0;\n            for (int i = 0; i < K; i++) {\n                if (r <= w[i]) { pick = i; break; }\n                r -= w[i];\n            }\n\n            int nxt = candSq[pick];\n            usedStamp[tile[nxt]] = curStamp;\n            cur = nxt;\n            suffix.push_back(cur);\n            score += p[cur];\n        }\n\n        outMerged.clear();\n        outMerged.reserve(prefixPath.size() + suffix.size());\n        for (int i = 0; i <= cutIdx; i++) outMerged.push_back(prefixPath[i]);\n        for (int i = 1; i < (int)suffix.size(); i++) outMerged.push_back(suffix[i]);\n\n        return score;\n    };\n\n    auto t0 = chrono::steady_clock::now();\n    double TIME_LIMIT = 1.98;\n    long long totalBudgetNs = (long long)(TIME_LIMIT * 1e9);\n\n    vector<Param> params = {\n        {0.95, 1.00, 0.85, 1.25, 0.20},\n        {1.10, 0.80, 1.10, 1.15, 0.18},\n        {0.80, 1.35, 0.70, 1.35, 0.22},\n        {1.20, 0.65, 0.95, 1.05, 0.16}\n    };\n\n    vector<int> bestPath, tmpPath, merged;\n    long long bestScore = -1;\n\n    // Phase 1: multiple restarts with DFS backtracking\n    while (true) {\n        auto now = chrono::steady_clock::now();\n        long long elapsed = chrono::duration_cast<chrono::nanoseconds>(now - t0).count();\n        if (elapsed > totalBudgetNs) break;\n\n        const Param &par = params[rng.nextInt(0, (int)params.size() - 1)];\n\n        vector<int> path;\n        long long sc = -1;\n\n        // give each DFS restart a small slice\n        long long slice = (long long)(0.07 * 1e9); // 70ms\n        auto now2 = chrono::steady_clock::now();\n        long long startElapsed = chrono::duration_cast<chrono::nanoseconds>(now2 - t0).count();\n        if (startElapsed + slice > totalBudgetNs) slice = max(1LL, totalBudgetNs - startElapsed);\n\n        runDFSBacktrack2(par, slice, t0, path, sc);\n\n        if (sc > bestScore) {\n            bestScore = sc;\n            bestPath = std::move(path);\n        }\n    }\n\n    // Phase 2: suffix repair on best path\n    if (!bestPath.empty()) {\n        int L = (int)bestPath.size();\n        int regionL = max(0, L - 700);\n\n        // choose cut points near the end, biased by low p (often helps escape)\n        vector<pair<int,double>> cutW;\n        cutW.reserve(L);\n        for (int i = regionL; i < L; i++) {\n            double w = (100.0 - p[bestPath[i]] + 1.0);\n            w = max(0.1, w);\n            cutW.push_back({i, w});\n        }\n\n        long long remain = totalBudgetNs - chrono::duration_cast<chrono::nanoseconds>(chrono::steady_clock::now() - t0).count();\n        long long sliceTotal = min(remain, (long long)(0.45 * 1e9));\n\n        // sample ~70 cuts max\n        vector<int> cuts;\n        int attemptsCuts = 0;\n        while ((int)cuts.size() < 70 && attemptsCuts < 200) {\n            attemptsCuts++;\n            double sumW = 0;\n            for (auto &x : cutW) sumW += x.second;\n            double r = rng.nextDouble() * sumW;\n            int pick = cutW.back().first;\n            for (auto &x : cutW) {\n                r -= x.second;\n                if (r <= 0) { pick = x.first; break; }\n            }\n            cuts.push_back(pick);\n        }\n        sort(cuts.begin(), cuts.end());\n        cuts.erase(unique(cuts.begin(), cuts.end()), cuts.end());\n        if (cuts.empty()) cuts.push_back(L - 1);\n\n        for (int cutIdx : cuts) {\n            auto now = chrono::steady_clock::now();\n            long long elapsed = chrono::duration_cast<chrono::nanoseconds>(now - t0).count();\n            long long remaining = totalBudgetNs - elapsed;\n            if (remaining <= 0) break;\n\n            long long perCut = min(remaining, (long long)(0.01 * 1e9)); // 10ms each attempt\n            if (perCut <= 0) break;\n\n            // baseScore of prefix\n            long long base = 0;\n            for (int i = 0; i <= cutIdx; i++) base += p[bestPath[i]];\n\n            for (int rep = 0; rep < 3; rep++) {\n                const Param &par = params[(cutIdx + rep) % params.size()];\n                merged.clear();\n                long long sc2 = runSuffixWalk(par, perCut, t0, bestPath, cutIdx, merged, base);\n                if (sc2 > bestScore) {\n                    bestScore = sc2;\n                    bestPath = merged;\n                }\n            }\n        }\n    }\n\n    // Output directions\n    string ans;\n    if (!bestPath.empty()) {\n        ans.reserve(max(0, (int)bestPath.size() - 1));\n        for (int i = 1; i < (int)bestPath.size(); i++) {\n            ans.push_back(dirBetween(bestPath[i-1], bestPath[i]));\n        }\n    }\n    cout << ans << \"\\n\";\n    return 0;\n}","ahc003":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int H = 30;\nstatic constexpr int W = 30;\nstatic constexpr int N = H * W;\n\nstatic constexpr int HOR = H * (W - 1);      // 30*29=870\nstatic constexpr int VER = (H - 1) * W;      // 29*30=870\nstatic constexpr int ECOUNT = HOR + VER;     // 1740\n\nstatic inline int idx_node(int i, int j) { return i * W + j; }\nstatic inline int idx_horizontal_edge(int i, int j) { return i * (W - 1) + j; } // j in [0..28]\nstatic inline int idx_vertical_edge(int i, int j) { return HOR + i * W + j; }   // i in [0..28]\n\nstruct PathResult {\n    string moves;\n    vector<int> usedEdges;\n};\n\nstruct FitLine {\n    bool two = false;\n    int split = 0;          // split point x (0..n). left: [0..x-1], right: [x..n-1]\n    double mean1 = 0.0;\n    double meanL = 0.0;\n    double meanR = 0.0;\n    double cost1 = 0.0;\n    double bestCost = 0.0;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // adjacency\n    vector<vector<pair<int,int>>> adj(N);\n    for (int i = 0; i < H; i++) {\n        for (int j = 0; j < W; j++) {\n            int u = idx_node(i, j);\n            if (j + 1 < W) {\n                int v = idx_node(i, j + 1);\n                int e = idx_horizontal_edge(i, j);\n                adj[u].push_back({v, e});\n                adj[v].push_back({u, e});\n            }\n            if (i + 1 < H) {\n                int v = idx_node(i + 1, j);\n                int e = idx_vertical_edge(i, j);\n                adj[u].push_back({v, e});\n                adj[v].push_back({u, e});\n            }\n        }\n    }\n\n    const double LO_W = 500.0;\n    const double HI_W = 9500.0;\n\n    auto clampW = [&](double x) {\n        if (x < LO_W) return LO_W;\n        if (x > HI_W) return HI_W;\n        return x;\n    };\n\n    vector<double> w_hat(ECOUNT, 5000.0);\n    vector<double> w_noisy(ECOUNT, 5000.0);\n\n    // RNG\n    mt19937_64 rng(123456789ULL);\n    auto rand01 = [&]() -> double {\n        return (rng() >> 11) * (1.0 / 9007199254740992.0);\n    };\n    normal_distribution<double> gauss(0.0, 1.0);\n\n    // Dijkstra working arrays\n    const double INF = 1e100;\n    vector<double> dist(N);\n    vector<int> parent(N), parentEdge(N);\n\n    auto build_path = [&](int s, int t) -> PathResult {\n        PathResult res;\n        if (s == t) return res;\n        if (parent[t] < 0) return res;\n\n        vector<char> revMoves;\n        vector<int> revEdges;\n\n        int cur = t;\n        while (cur != s) {\n            int p = parent[cur];\n            int e = parentEdge[cur];\n            if (p < 0 || e < 0) return PathResult{};\n\n            int pi = p / W, pj = p % W;\n            int ci = cur / W, cj = cur % W;\n\n            char mv;\n            if (ci == pi - 1 && cj == pj) mv = 'U';\n            else if (ci == pi + 1 && cj == pj) mv = 'D';\n            else if (ci == pi && cj == pj - 1) mv = 'L';\n            else if (ci == pi && cj == pj + 1) mv = 'R';\n            else mv = '?';\n\n            revMoves.push_back(mv);\n            revEdges.push_back(e);\n            cur = p;\n        }\n\n        reverse(revMoves.begin(), revMoves.end());\n        reverse(revEdges.begin(), revEdges.end());\n        res.moves.assign(revMoves.begin(), revMoves.end());\n        res.usedEdges = std::move(revEdges);\n        return res;\n    };\n\n    auto dijkstra_path = [&](int s, int t, const double* w_use) -> PathResult {\n        for (int i = 0; i < N; i++) {\n            dist[i] = INF;\n            parent[i] = -1;\n            parentEdge[i] = -1;\n        }\n\n        struct State {\n            double d;\n            int v;\n            bool operator>(const State& o) const { return d > o.d; }\n        };\n\n        priority_queue<State, vector<State>, greater<State>> pq;\n        dist[s] = 0.0;\n        parent[s] = s;\n        pq.push({0.0, s});\n\n        const double EPS = 1e-12;\n\n        while (!pq.empty()) {\n            auto [dcur, u] = pq.top();\n            pq.pop();\n            if (dcur != dist[u]) continue;\n            if (u == t) break;\n\n            for (auto [to, e] : adj[u]) {\n                double nd = dcur + w_use[e];\n                if (nd + EPS < dist[to]) {\n                    dist[to] = nd;\n                    parent[to] = u;\n                    parentEdge[to] = e;\n                    pq.push({nd, to});\n                } else if (fabs(nd - dist[to]) <= EPS) {\n                    if (rand01() < 0.5) {\n                        parent[to] = u;\n                        parentEdge[to] = e;\n                        pq.push({nd, to});\n                    }\n                }\n            }\n        }\n\n        return build_path(s, t);\n    };\n\n    auto monotone_path = [&](int s, int t) -> PathResult {\n        int si = s / W, sj = s % W;\n        int ti = t / W, tj = t % W;\n        int i = si, j = sj;\n\n        PathResult res;\n        while (i != ti || j != tj) {\n            bool canV = (i != ti);\n            bool canH = (j != tj);\n            bool doV = (canV && canH) ? (rand01() < 0.5) : canV;\n\n            if (doV) {\n                if (ti > i) {\n                    int e = idx_vertical_edge(i, j);\n                    res.usedEdges.push_back(e);\n                    res.moves.push_back('D');\n                    i++;\n                } else {\n                    int e = idx_vertical_edge(i - 1, j);\n                    res.usedEdges.push_back(e);\n                    res.moves.push_back('U');\n                    i--;\n                }\n            } else {\n                if (tj > j) {\n                    int e = idx_horizontal_edge(i, j);\n                    res.usedEdges.push_back(e);\n                    res.moves.push_back('R');\n                    j++;\n                } else {\n                    int e = idx_horizontal_edge(i, j - 1);\n                    res.usedEdges.push_back(e);\n                    res.moves.push_back('L');\n                    j--;\n                }\n            }\n        }\n        return res;\n    };\n\n    // Fit functions for row/col (1 or 2 contiguous segments)\n    auto fit_row = [&](int row, double TH) -> FitLine {\n        // n = 29 edges j=0..28\n        const int n = W - 1;\n        array<double, W> a{}; // size 30, use [0..n-1]\n        for (int j = 0; j < n; j++) a[j] = w_hat[idx_horizontal_edge(row, j)];\n\n        double sum = 0.0, sumsq = 0.0;\n        for (int j = 0; j < n; j++) { sum += a[j]; sumsq += a[j] * a[j]; }\n        double mean1 = sum / n;\n        double cost1 = sumsq - (double)n * mean1 * mean1;\n\n        array<double, W> pref{}, pref2{};\n        pref[0] = 0.0; pref2[0] = 0.0;\n        for (int j = 0; j < n; j++) {\n            pref[j + 1] = pref[j] + a[j];\n            pref2[j + 1] = pref2[j] + a[j] * a[j];\n        }\n\n        FitLine f;\n        f.mean1 = mean1;\n        f.cost1 = cost1;\n        f.bestCost = cost1;\n        f.two = false;\n\n        double bestCost = cost1;\n        int bestX = 0;\n        double bestMeanL = mean1, bestMeanR = mean1;\n\n        for (int x = 1; x <= n - 1; x++) {\n            int nl = x;\n            int nr = n - x;\n            double sumL = pref[x];\n            double sumR = pref[n] - pref[x];\n            double sumsqL = pref2[x];\n            double sumsqR = pref2[n] - pref2[x];\n\n            double meanL = sumL / nl;\n            double meanR = sumR / nr;\n\n            double costL = sumsqL - (double)nl * meanL * meanL;\n            double costR = sumsqR - (double)nr * meanR * meanR;\n            double cost = costL + costR;\n\n            if (cost < bestCost) {\n                bestCost = cost;\n                bestX = x;\n                bestMeanL = meanL;\n                bestMeanR = meanR;\n            }\n        }\n\n        f.bestCost = bestCost;\n        if (cost1 > 1e-9 && bestCost < cost1 * TH) {\n            f.two = true;\n            f.split = bestX;\n            f.meanL = bestMeanL;\n            f.meanR = bestMeanR;\n        } else {\n            f.two = false;\n        }\n        return f;\n    };\n\n    auto fit_col = [&](int col, double TH) -> FitLine {\n        const int n = H - 1; // 29 edges i=0..28\n        array<double, H> a{}; // size 30 use [0..n-1]\n        for (int i = 0; i < n; i++) a[i] = w_hat[idx_vertical_edge(i, col)];\n\n        double sum = 0.0, sumsq = 0.0;\n        for (int i = 0; i < n; i++) { sum += a[i]; sumsq += a[i] * a[i]; }\n        double mean1 = sum / n;\n        double cost1 = sumsq - (double)n * mean1 * mean1;\n\n        array<double, H> pref{}, pref2{};\n        pref[0] = 0.0; pref2[0] = 0.0;\n        for (int i = 0; i < n; i++) {\n            pref[i + 1] = pref[i] + a[i];\n            pref2[i + 1] = pref2[i] + a[i] * a[i];\n        }\n\n        FitLine f;\n        f.mean1 = mean1;\n        f.cost1 = cost1;\n        f.bestCost = cost1;\n        f.two = false;\n\n        double bestCost = cost1;\n        int bestY = 0;\n        double bestMeanT = mean1, bestMeanB = mean1;\n\n        for (int y = 1; y <= n - 1; y++) {\n            int nt = y;\n            int nb = n - y;\n            double sumT = pref[y];\n            double sumB = pref[n] - pref[y];\n            double sumsqT = pref2[y];\n            double sumsqB = pref2[n] - pref2[y];\n\n            double meanT = sumT / nt;\n            double meanB = sumB / nb;\n\n            double costT = sumsqT - (double)nt * meanT * meanT;\n            double costB = sumsqB - (double)nb * meanB * meanB;\n            double cost = costT + costB;\n\n            if (cost < bestCost) {\n                bestCost = cost;\n                bestY = y;\n                bestMeanT = meanT;\n                bestMeanB = meanB;\n            }\n        }\n\n        f.bestCost = bestCost;\n        if (cost1 > 1e-9 && bestCost < cost1 * TH) {\n            f.two = true;\n            f.split = bestY;\n            f.meanL = bestMeanT; // for col: \"top\"\n            f.meanR = bestMeanB; // for col: \"bottom\"\n        } else {\n            f.two = false;\n        }\n        return f;\n    };\n\n    // Optional soft projection (kept small to stabilize split boundaries)\n    auto smooth_row = [&](int row, double alpha, double TH) {\n        FitLine f = fit_row(row, TH);\n        const int n = W - 1;\n        if (!f.two) {\n            double target = f.mean1;\n            for (int j = 0; j < n; j++) {\n                int e = idx_horizontal_edge(row, j);\n                w_hat[e] = clampW((1.0 - alpha) * w_hat[e] + alpha * target);\n            }\n        } else {\n            int x = f.split;\n            double L = f.meanL, R = f.meanR;\n            for (int j = 0; j < n; j++) {\n                int e = idx_horizontal_edge(row, j);\n                double target = (j < x ? L : R);\n                w_hat[e] = clampW((1.0 - alpha) * w_hat[e] + alpha * target);\n            }\n        }\n    };\n\n    auto smooth_col = [&](int col, double alpha, double TH) {\n        FitLine f = fit_col(col, TH);\n        const int n = H - 1;\n        if (!f.two) {\n            double target = f.mean1;\n            for (int i = 0; i < n; i++) {\n                int e = idx_vertical_edge(i, col);\n                w_hat[e] = clampW((1.0 - alpha) * w_hat[e] + alpha * target);\n            }\n        } else {\n            int y = f.split;\n            double T = f.meanL, B = f.meanR; // top/bottom\n            for (int i = 0; i < n; i++) {\n                int e = idx_vertical_edge(i, col);\n                double target = (i < y ? T : B);\n                w_hat[e] = clampW((1.0 - alpha) * w_hat[e] + alpha * target);\n            }\n        }\n    };\n\n    // main loop\n    for (int k = 0; k < 1000; k++) {\n        int si, sj, ti, tj;\n        if (!(cin >> si >> sj >> ti >> tj)) return 0;\n        int s = idx_node(si, sj);\n        int t = idx_node(ti, tj);\n\n        // Candidate det\n        PathResult cand_det = dijkstra_path(s, t, w_hat.data());\n        if (cand_det.moves.empty()) cand_det = monotone_path(s, t);\n\n        // Decide noisy exploration\n        double pNoisy = (k < 160 ? 0.55 : (k < 520 ? 0.26 : 0.12));\n        bool doNoisy = (rand01() < pNoisy);\n\n        PathResult chosen = cand_det;\n\n        // Soft pick between det/noisy based on predicted length under w_hat\n        if (doNoisy) {\n            double sigmaBase = 1400.0 + 900.0 * (1.0 - min(1.0, (double)k / 700.0));\n            double sigmaEdge = 160.0;\n\n            array<double, H> rowOff{};\n            array<double, W> colOff{};\n\n            for (int i = 0; i < H; i++) rowOff[i] = gauss(rng) * sigmaBase;\n            for (int j = 0; j < W; j++) colOff[j] = gauss(rng) * sigmaBase;\n\n            for (int e = 0; e < ECOUNT; e++) {\n                double w = w_hat[e];\n                if (e < HOR) {\n                    int row = e / (W - 1);\n                    w += rowOff[row] + gauss(rng) * sigmaEdge;\n                } else {\n                    int z = e - HOR;\n                    int col = z % W;\n                    w += colOff[col] + gauss(rng) * sigmaEdge;\n                }\n                w_noisy[e] = clampW(w);\n            }\n\n            PathResult cand_noi = dijkstra_path(s, t, w_noisy.data());\n            if (!cand_noi.moves.empty()) {\n                long double pred_det = 0, pred_noi = 0;\n                for (int e : cand_det.usedEdges) pred_det += (long double)w_hat[e];\n                for (int e : cand_noi.usedEdges) pred_noi += (long double)w_hat[e];\n\n                long double diff = pred_noi - pred_det;\n                long double T = 7000.0L;\n                long double prob_noi = 1.0L / (1.0L + expl(diff / T));\n                if (rand01() < (double)prob_noi) chosen = std::move(cand_noi);\n            }\n        }\n\n        cout << chosen.moves << '\\n' << flush;\n\n        long long y_int;\n        if (!(cin >> y_int)) return 0;\n        long double y = (long double)y_int;\n\n        int m = (int)chosen.usedEdges.size();\n        if (m == 0) continue;\n\n        // pred with current w_hat\n        long double predFull = 0;\n        for (int e : chosen.usedEdges) predFull += (long double)w_hat[e];\n        long double err = y - predFull;\n\n        long double bound = 0.45L * max(1.0L, predFull);\n        if (err > bound) err = bound;\n        if (err < -bound) err = -bound;\n\n        // touched rows/cols\n        array<char, H> usedRows{};\n        array<char, W> usedCols{};\n        for (int e : chosen.usedEdges) {\n            if (e < HOR) usedRows[e / (W - 1)] = 1;\n            else usedCols[(e - HOR) % W] = 1;\n        }\n\n        // schedule\n        double etaBase = 0.24 / sqrt((long double)(k + 1));\n        etaBase = max(0.0025L, (long double)etaBase);\n\n        double THfit = (k < 200 ? 0.80 : (k < 600 ? 0.78 : 0.76));\n        double betaShift = (k < 200 ? 0.95 : (k < 600 ? 0.88 : 0.82));\n        double gammaEdge = 0.10; // small residual update on used edges\n\n        // compute fits for touched lines\n        vector<FitLine> rowFit(H), colFit(W);\n        for (int i = 0; i < H; i++) if (usedRows[i]) rowFit[i] = fit_row(i, THfit);\n        for (int j = 0; j < W; j++) if (usedCols[j]) colFit[j] = fit_col(j, THfit);\n\n        // segment counts on chosen path\n        // for each row: countSeg0, countSeg1; for 1-seg countSeg1=0\n        array<int, H> cntRow0{}, cntRow1{};\n        array<int, W> cntCol0{}, cntCol1{};\n\n        for (int e : chosen.usedEdges) {\n            if (e < HOR) {\n                int row = e / (W - 1);\n                int pos = e % (W - 1); // 0..28\n                if (rowFit[row].two) {\n                    if (pos < rowFit[row].split) cntRow0[row]++;\n                    else cntRow1[row]++;\n                } else {\n                    cntRow0[row]++;\n                }\n            } else {\n                int col = (e - HOR) % W;\n                int pos = (e - HOR) / W; // i in 0..28\n                if (colFit[col].two) {\n                    if (pos < colFit[col].split) cntCol0[col]++;\n                    else cntCol1[col]++;\n                } else {\n                    cntCol0[col]++;\n                }\n            }\n        }\n\n        // apply segment shifts\n        long double eta = etaBase;\n        long double dmBase = eta * err / (long double)m; // base per-edge scale\n\n        // update w_hat for whole segment on touched lines\n        for (int i = 0; i < H; i++) if (usedRows[i]) {\n            if (rowFit[i].two) {\n                long double d0 = betaShift * dmBase * (long double)cntRow0[i];\n                long double d1 = betaShift * dmBase * (long double)cntRow1[i];\n                int x = rowFit[i].split;\n                for (int j = 0; j < W - 1; j++) {\n                    int e = idx_horizontal_edge(i, j);\n                    if (j < x) w_hat[e] = clampW((long double)w_hat[e] + d0);\n                    else w_hat[e] = clampW((long double)w_hat[e] + d1);\n                }\n            } else {\n                long double d0 = betaShift * dmBase * (long double)cntRow0[i];\n                for (int j = 0; j < W - 1; j++) {\n                    int e = idx_horizontal_edge(i, j);\n                    w_hat[e] = clampW((long double)w_hat[e] + d0);\n                }\n            }\n        }\n\n        for (int j = 0; j < W; j++) if (usedCols[j]) {\n            if (colFit[j].two) {\n                long double d0 = betaShift * dmBase * (long double)cntCol0[j];\n                long double d1 = betaShift * dmBase * (long double)cntCol1[j];\n                int ysplit = colFit[j].split;\n                for (int i = 0; i < H - 1; i++) {\n                    int e = idx_vertical_edge(i, j);\n                    if (i < ysplit) w_hat[e] = clampW((long double)w_hat[e] + d0);\n                    else w_hat[e] = clampW((long double)w_hat[e] + d1);\n                }\n            } else {\n                long double d0 = betaShift * dmBase * (long double)cntCol0[j];\n                for (int i = 0; i < H - 1; i++) {\n                    int e = idx_vertical_edge(i, j);\n                    w_hat[e] = clampW((long double)w_hat[e] + d0);\n                }\n            }\n        }\n\n        // small residual edge-level update (helps learn per-edge delta noise)\n        long double dEdge = (long double)gammaEdge * eta * err / (long double)m;\n        for (int e : chosen.usedEdges) {\n            w_hat[e] = clampW((long double)w_hat[e] + dEdge);\n        }\n\n        // small soft projection on touched lines (to let split boundaries adapt)\n        double alphaProj = (k < 200 ? 0.10 : (k < 600 ? 0.085 : 0.07));\n        double THproj = (k < 200 ? 0.80 : (k < 600 ? 0.78 : 0.76));\n\n        for (int i = 0; i < H; i++) if (usedRows[i]) smooth_row(i, alphaProj, THproj);\n        for (int j = 0; j < W; j++) if (usedCols[j]) smooth_col(j, alphaProj, THproj);\n    }\n\n    return 0;\n}","ahc004":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 20;\nstatic constexpr int ALPHA = 8; // A..H\n\n// SplitMix64 hash\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 uint64_t keyOfString(const vector<uint8_t>& v) {\n    int len = (int)v.size();\n    uint64_t enc = 0;\n    for (uint8_t x : v) enc = (enc << 3) | (uint64_t)x; // base 8 packing\n    return (uint64_t(len) << 48) | enc;\n}\n\nstruct Solver {\n    int M;\n    vector<string> S;\n    vector<vector<uint8_t>> scodes;\n    vector<int> slen;\n    vector<uint64_t> skey;\n\n    // distinct string keys (exact sequences by length+content)\n    int K;\n    vector<int> mult;     // multiplicity per key id\n    vector<int> occ;      // occurrence count per key in current grid\n    long long curC = 0;   // sum mult[id] where occ[id] > 0\n    int bestC = -1;\n    array<array<uint8_t, N>, N> g{};\n    array<array<uint8_t, N>, N> bestG{};\n\n    unordered_map<uint64_t, int, decltype(&splitmix64)> idByKey;\n\n    bool needLen[13]{};\n    vector<int> neededLens;\n    uint64_t maskLower[13]{};\n\n    // overlap maps for greedy construction\n    // prefixCand[ov][prefEnc] -> list of indices whose prefix of length ov equals prefEnc\n    // suffixCand[ov][sufEnc] -> list of indices whose suffix of length ov equals sufEnc\n    vector<unordered_map<uint64_t, vector<int>, decltype(&splitmix64)>> prefixCand, suffixCand;\n\n    mt19937_64 rng;\n\n    Solver() : rng((uint64_t)chrono::steady_clock::now().time_since_epoch().count()),\n               idByKey(1024, splitmix64) {}\n\n    uint8_t charToCode(char c) { return (uint8_t)(c - 'A'); }\n\n    uint64_t encFromSeq(const vector<uint8_t>& v, int l, int r) {\n        uint64_t enc = 0;\n        for (int i = l; i < r; i++) enc = (enc << 3) | v[i];\n        return enc;\n    }\n\n    void buildObjectiveStructures() {\n        idByKey.clear();\n        mult.clear();\n\n        for (int k = 0; k <= 12; k++) needLen[k] = false;\n\n        K = 0;\n        for (int i = 0; i < M; i++) {\n            uint64_t key = skey[i];\n            auto it = idByKey.find(key);\n            if (it == idByKey.end()) {\n                int id = K++;\n                idByKey.emplace(key, id);\n                mult.push_back(1);\n            } else {\n                mult[it->second]++;\n            }\n            needLen[slen[i]] = true;\n        }\n        neededLens.clear();\n        for (int k = 2; k <= 12; k++) if (needLen[k]) neededLens.push_back(k);\n\n        // Precompute masks for sliding\n        for (int k = 2; k <= 12; k++) {\n            int bits = 3 * (k - 1);\n            maskLower[k] = (bits >= 64) ? ~0ULL : ((1ULL << bits) - 1ULL);\n        }\n        occ.assign(K, 0);\n    }\n\n    void buildOverlapMaps() {\n        prefixCand.assign(13, unordered_map<uint64_t, vector<int>, decltype(&splitmix64)>(0, splitmix64));\n        suffixCand.assign(13, unordered_map<uint64_t, vector<int>, decltype(&splitmix64)>(0, splitmix64));\n\n        for (int i = 0; i < M; i++) {\n            int L = slen[i];\n            for (int ov = 2; ov <= L - 1; ov++) {\n                uint64_t pref = encFromSeq(scodes[i], 0, ov);\n                uint64_t suf  = encFromSeq(scodes[i], L - ov, L);\n                prefixCand[ov][pref].push_back(i);\n                suffixCand[ov][suf].push_back(i);\n            }\n        }\n    }\n\n    inline void updateLine(bool isRow, int idx, int delta) {\n        // delta: +1 (add contributions) or -1 (remove contributions) for that line only\n        uint8_t ext[2 * N];\n        if (isRow) {\n            for (int t = 0; t < 2 * N; t++) ext[t] = g[idx][t % N];\n        } else {\n            for (int t = 0; t < 2 * N; t++) ext[t] = g[t % N][idx];\n        }\n\n        for (int k : neededLens) {\n            uint64_t enc = 0;\n            for (int t = 0; t < k; t++) enc = (enc << 3) | (uint64_t)ext[t];\n\n            for (int start = 0; start < N; start++) {\n                uint64_t key = (uint64_t(k) << 48) | enc;\n                auto it = idByKey.find(key);\n                if (it != idByKey.end()) {\n                    int id = it->second;\n                    int before = occ[id];\n                    if (delta == +1) {\n                        occ[id] = before + 1;\n                        if (before == 0) curC += mult[id];\n                    } else {\n                        occ[id] = before - 1;\n                        if (before == 1) curC -= mult[id];\n                    }\n                }\n                if (start == N - 1) break;\n                enc = ((enc & maskLower[k]) << 3) | (uint64_t)ext[start + k];\n            }\n        }\n    }\n\n    void computeInitialCounts() {\n        fill(occ.begin(), occ.end(), 0);\n        curC = 0;\n\n        // rows\n        for (int i = 0; i < N; i++) updateLine(true, i, +1);\n        // columns\n        for (int j = 0; j < N; j++) updateLine(false, j, +1);\n\n        // IMPORTANT FIX:\n        // do NOT overwrite global bestC/bestG here.\n    }\n\n    inline void setCell(int i, int j, uint8_t nv) {\n        uint8_t old = g[i][j];\n        if (old == nv) return;\n\n        updateLine(true, i, -1);\n        updateLine(false, j, -1);\n\n        g[i][j] = nv;\n\n        updateLine(true, i, +1);\n        updateLine(false, j, +1);\n    }\n\n    void randomFillRow(array<uint8_t, N>& row) {\n        for (int j = 0; j < N; j++) row[j] = (uint8_t)(rng() % ALPHA);\n    }\n\n    void buildInitialGridGreedy() {\n        // Build a decent starting point by row assembly.\n        // coveredKeys[k] stores cyclic horizontal substrings of length k already present.\n        vector<unordered_set<uint64_t, decltype(&splitmix64)>> coveredKeys(13, unordered_set<uint64_t, decltype(&splitmix64)>(0, splitmix64));\n        vector<char> coveredInput(M, 0);\n\n        for (int k = 2; k <= 12; k++) if (needLen[k]) {\n            coveredKeys[k] = unordered_set<uint64_t, decltype(&splitmix64)>(0, splitmix64);\n            coveredKeys[k].reserve(1 << 12);\n        }\n\n        auto addRowToCovered = [&](int rowIdx, const array<uint8_t, N>& row) {\n            for (int k : neededLens) {\n                uint64_t enc = 0;\n                for (int t = 0; t < k; t++) enc = (enc << 3) | row[t];\n                for (int start = 0; start < N; start++) {\n                    uint64_t key = (uint64_t(k) << 48) | enc;\n                    coveredKeys[k].insert(key);\n                    if (start == N - 1) break;\n                    enc = ((enc & maskLower[k]) << 3) | row[(start + k) % N];\n                }\n            }\n        };\n\n        auto updateCoveredInputFromRowSets = [&]() {\n            for (int i = 0; i < M; i++) {\n                if (coveredInput[i]) continue;\n                int k = slen[i];\n                uint64_t key = skey[i];\n                if (coveredKeys[k].find(key) != coveredKeys[k].end()) coveredInput[i] = 1;\n            }\n        };\n\n        int minOverlap = 2;\n\n        for (int i = 0; i < N; i++) {\n            // choose seed string not yet horizontally covered, prefer longer\n            int bestL = -1;\n            vector<int> bestIdx;\n            for (int idx = 0; idx < M; idx++) {\n                if (coveredInput[idx]) continue;\n                if (slen[idx] > bestL) {\n                    bestL = slen[idx];\n                    bestIdx.clear();\n                    bestIdx.push_back(idx);\n                } else if (slen[idx] == bestL) {\n                    bestIdx.push_back(idx);\n                }\n            }\n\n            array<uint8_t, N> row{};\n            if (bestL < 0) {\n                randomFillRow(row);\n                for (int j = 0; j < N; j++) g[i][j] = row[j];\n                addRowToCovered(i, row);\n                updateCoveredInputFromRowSets();\n                continue;\n            }\n\n            int seed = bestIdx[rng() % (int)bestIdx.size()];\n            vector<uint8_t> seq = scodes[seed];\n\n            // Expand to length N by overlapping with input strings\n            while ((int)seq.size() < N) {\n                int curLen = (int)seq.size();\n                int maxOv = min(curLen - 1, 11);\n\n                int bestRightLen = curLen, bestRightIdx = -1, bestRightOv = -1;\n                for (int ov = maxOv; ov >= minOverlap; ov--) {\n                    uint64_t sufEnc = 0;\n                    for (int t = curLen - ov; t < curLen; t++) sufEnc = (sufEnc << 3) | seq[t];\n                    auto it = prefixCand[ov].find(sufEnc);\n                    if (it == prefixCand[ov].end()) continue;\n                    for (int candIdx : it->second) {\n                        if (slen[candIdx] <= ov) continue;\n                        int newLen = curLen + slen[candIdx] - ov;\n                        if (newLen <= N && newLen > bestRightLen) {\n                            bestRightLen = newLen;\n                            bestRightIdx = candIdx;\n                            bestRightOv = ov;\n                        }\n                    }\n                }\n\n                int bestLeftLen = curLen, bestLeftIdx = -1, bestLeftOv = -1;\n                for (int ov = maxOv; ov >= minOverlap; ov--) {\n                    uint64_t prefEnc = 0;\n                    for (int t = 0; t < ov; t++) prefEnc = (prefEnc << 3) | seq[t];\n                    auto it = suffixCand[ov].find(prefEnc);\n                    if (it == suffixCand[ov].end()) continue;\n                    for (int candIdx : it->second) {\n                        if (slen[candIdx] <= ov) continue;\n                        int newLen = curLen + slen[candIdx] - ov;\n                        if (newLen <= N && newLen > bestLeftLen) {\n                            bestLeftLen = newLen;\n                            bestLeftIdx = candIdx;\n                            bestLeftOv = ov;\n                        }\n                    }\n                }\n\n                int finalLen = max(bestRightLen, bestLeftLen);\n                if (finalLen == curLen) break;\n\n                bool takeRight;\n                if (bestRightLen > bestLeftLen) takeRight = true;\n                else if (bestLeftLen > bestRightLen) takeRight = false;\n                else takeRight = (rng() & 1);\n\n                if (takeRight) {\n                    auto& cv = scodes[bestRightIdx];\n                    int ov = bestRightOv;\n                    for (int t = ov; t < (int)cv.size() && (int)seq.size() < N; t++) seq.push_back(cv[t]);\n                } else {\n                    auto& cv = scodes[bestLeftIdx];\n                    int ov = bestLeftOv;\n                    vector<uint8_t> nseq;\n                    nseq.reserve(N);\n                    for (int t = 0; t < (int)cv.size() - ov && (int)nseq.size() < N; t++) nseq.push_back(cv[t]);\n                    for (uint8_t x : seq) {\n                        if ((int)nseq.size() >= N) break;\n                        nseq.push_back(x);\n                    }\n                    seq.swap(nseq);\n                }\n            }\n\n            while ((int)seq.size() < N) seq.push_back((uint8_t)(rng() % ALPHA));\n            for (int j = 0; j < N; j++) {\n                row[j] = seq[j];\n                g[i][j] = row[j];\n            }\n\n            addRowToCovered(i, row);\n            updateCoveredInputFromRowSets();\n        }\n    }\n\n    void solveOneRun(int steps, long double Tstart, long double Tmin, chrono::steady_clock::time_point deadline) {\n        long double T = Tstart;\n        long double alpha = pow((double)(Tmin / Tstart), 1.0L / (long double)steps);\n\n        for (int it = 0; it < steps; it++) {\n            if (chrono::steady_clock::now() >= deadline) break;\n\n            int i = (int)(rng() % N);\n            int j = (int)(rng() % N);\n\n            uint8_t old = g[i][j];\n            uint8_t nv = old;\n            while (nv == old) nv = (uint8_t)(rng() % ALPHA);\n\n            long long beforeC = curC;\n            setCell(i, j, nv);\n            long long afterC = curC;\n\n            bool accept = false;\n            if (afterC >= beforeC) {\n                accept = true;\n            } else {\n                long double prob = expl((long double)(afterC - beforeC) / T);\n                long double r = (long double)(rng() % 1000000) / 1000000.0L;\n                if (r < prob) accept = true;\n            }\n\n            if (accept) {\n                if (afterC > bestC) {\n                    bestC = (int)afterC;\n                    bestG = g;\n                }\n            } else {\n                // revert\n                setCell(i, j, old);\n            }\n\n            T *= alpha;\n            if (T < 1e-7L) T = 1e-7L;\n        }\n    }\n\n    void run() {\n        ios::sync_with_stdio(false);\n        cin.tie(nullptr);\n\n        int Nread;\n        cin >> Nread >> M; // N fixed to 20 but read anyway\n\n        S.resize(M);\n        for (int i = 0; i < M; i++) cin >> S[i];\n\n        scodes.assign(M, {});\n        slen.assign(M, 0);\n        skey.assign(M, 0);\n\n        for (int i = 0; i < M; i++) {\n            const string& s = S[i];\n            slen[i] = (int)s.size();\n            vector<uint8_t> v(s.size());\n            for (int t = 0; t < (int)s.size(); t++) v[t] = charToCode(s[t]);\n            scodes[i] = std::move(v);\n            skey[i] = keyOfString(scodes[i]);\n        }\n\n        buildObjectiveStructures();\n        buildOverlapMaps();\n\n        // Initialize grid\n        buildInitialGridGreedy();\n        auto baseG = g;\n\n        // improve expected performance: reserve more buckets\n        idByKey.reserve((size_t)K * 2);\n\n        bestC = -1;\n        bestG = g;\n\n        const auto globalStart = chrono::steady_clock::now();\n        const auto deadline = globalStart + chrono::milliseconds(2850); // keep margin\n\n        int restarts = 6;\n        for (int r = 0; r < restarts; r++) {\n            if (chrono::steady_clock::now() >= deadline) break;\n\n            g = baseG;\n\n            int perturb = (r == 0 ? 0 : 30 + 15 * r);\n            for (int t = 0; t < perturb; t++) {\n                int i = (int)(rng() % N);\n                int j = (int)(rng() % N);\n                uint8_t nv = (uint8_t)(rng() % ALPHA);\n                if (nv == g[i][j]) nv = (nv + 1) % ALPHA;\n                g[i][j] = nv;\n            }\n\n            computeInitialCounts();\n            if (curC > bestC) {\n                bestC = (int)curC;\n                bestG = g;\n            }\n\n            // Remaining steps adapt to time\n            int steps = 120000 + 20000 * r;\n            solveOneRun(steps, 4.0L, 0.10L, deadline);\n        }\n\n        for (int i = 0; i < N; i++) {\n            string row;\n            row.reserve(N);\n            for (int j = 0; j < N; j++) row.push_back(char('A' + bestG[i][j]));\n            cout << row << '\\n';\n        }\n    }\n};\n\nint main() {\n    Solver s;\n    s.run();\n    return 0;\n}","ahc005":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct DSU {\n    int n;\n    vector<int> p, r;\n    DSU(int n=0): n(n), p(n), r(n,0) { iota(p.begin(), p.end(), 0); }\n    int find(int x){ return p[x]==x? x : p[x]=find(p[x]); }\n    bool unite(int a,int b){\n        a=find(a); b=find(b);\n        if(a==b) return false;\n        if(r[a]<r[b]) swap(a,b);\n        p[b]=a;\n        if(r[a]==r[b]) r[a]++;\n        return true;\n    }\n};\n\nstatic inline char dirChar(const pair<int,int>& a, const pair<int,int>& b){\n    int ar=a.first, ac=a.second, br=b.first, bc=b.second;\n    if(br==ar-1 && bc==ac) return 'U';\n    if(br==ar+1 && bc==ac) return 'D';\n    if(br==ar && bc==ac-1) return 'L';\n    return 'R'; // br==ar && bc==ac+1\n}\n\nstruct TourResult{\n    bool ok=false;\n    long long t = (1LL<<62);\n    vector<int> seq; // vertices, seq[0]==seq.back()==start\n};\n\nint main(){\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, si, sj;\n    cin >> N >> si >> sj;\n    vector<string> g(N);\n    for(int i=0;i<N;i++) cin >> g[i];\n\n    auto inside = [&](int r,int c){ return 0<=r && r<N && 0<=c && c<N; };\n\n    // Extract connected component from (si,sj)\n    vector<vector<int>> idx(N, vector<int>(N, -1));\n    vector<pair<int,int>> cells;\n    vector<int> wts;\n\n    queue<pair<int,int>> q;\n    vector<vector<char>> vis(N, vector<char>(N,0));\n    q.push({si,sj});\n    vis[si][sj]=1;\n\n    int dr[4]={-1,1,0,0};\n    int dc[4]={0,0,-1,1};\n\n    while(!q.empty()){\n        auto [r,c]=q.front(); q.pop();\n        int id=(int)cells.size();\n        idx[r][c]=id;\n        cells.push_back({r,c});\n        wts.push_back(g[r][c]-'0');\n        for(int k=0;k<4;k++){\n            int nr=r+dr[k], nc=c+dc[k];\n            if(!inside(nr,nc)) continue;\n            if(vis[nr][nc]) continue;\n            if(g[nr][nc]=='#') continue;\n            vis[nr][nc]=1;\n            q.push({nr,nc});\n        }\n    }\n\n    int m=(int)cells.size();\n    if(m<=1){\n        cout << \"\\n\";\n        return 0;\n    }\n    int sidx = idx[si][sj];\n\n    // Build component adjacency with edge ids.\n    // Use right/down scans to add each undirected adjacency exactly once.\n    vector<vector<pair<int,int>>> adj(m); // (to, eid)\n    vector<int> eu, ev;\n    eu.reserve(2*m); ev.reserve(2*m);\n\n    auto addAdjEdge = [&](int a,int b){\n        int eid=(int)eu.size();\n        eu.push_back(a);\n        ev.push_back(b);\n        adj[a].push_back({b,eid});\n        adj[b].push_back({a,eid});\n    };\n\n    for(int u=0;u<m;u++){\n        auto [r,c]=cells[u];\n        if(c+1<N && idx[r][c+1]!=-1) addAdjEdge(u, idx[r][c+1]); // right\n        if(r+1<N && idx[r+1][c]!=-1) addAdjEdge(u, idx[r+1][c]); // down\n    }\n\n    int E=(int)eu.size();\n    vector<int> edgeCost(E);\n    for(int eid=0;eid<E;eid++){\n        int a=eu[eid], b=ev[eid];\n        edgeCost[eid]=wts[a]+wts[b];\n    }\n\n    // Unique costs for Kruskal\n    vector<int> uniq=edgeCost;\n    sort(uniq.begin(), uniq.end());\n    uniq.erase(unique(uniq.begin(), uniq.end()), uniq.end());\n\n    unordered_map<int, vector<int>> byCost;\n    byCost.reserve(uniq.size()*2+5);\n    for(int eid=0;eid<E;eid++) byCost[edgeCost[eid]].push_back(eid);\n\n    mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());\n\n    auto buildMST = [&](bool randomTies)->pair<vector<int>, vector<int>>{\n        DSU dsu(m);\n        vector<int> mstDeg(m,0), mstEdgeIds;\n        mstEdgeIds.reserve(m-1);\n\n        for(int cst: uniq){\n            auto vec = byCost[cst];\n            if(randomTies) shuffle(vec.begin(), vec.end(), rng);\n            for(int eid: vec){\n                int a=eu[eid], b=ev[eid];\n                if(dsu.unite(a,b)){\n                    mstEdgeIds.push_back(eid);\n                    mstDeg[a]++; mstDeg[b]++;\n                    if((int)mstEdgeIds.size()==m-1) break;\n                }\n            }\n            if((int)mstEdgeIds.size()==m-1) break;\n        }\n        if((int)mstEdgeIds.size()!=m-1) return {{},{}}; // should not happen\n        return {mstEdgeIds, mstDeg};\n    };\n\n    // Doubled-tree tour (baseline)\n    auto doubledTreeTour = [&](const vector<int>& mstEdgeIds)->TourResult{\n        vector<vector<int>> treeAdj(m);\n        for(int eid: mstEdgeIds){\n            int a=eu[eid], b=ev[eid];\n            treeAdj[a].push_back(b);\n            treeAdj[b].push_back(a);\n        }\n\n        long long t=0;\n        for(int u=0;u<m;u++) t += 1LL*wts[u]*(long long)treeAdj[u].size();\n\n        vector<int> seq;\n        seq.reserve(2*(m-1)+1);\n\n        struct Frame{int u,p,it;};\n        vector<Frame> st;\n        st.reserve(m);\n        st.push_back({sidx,-1,0});\n\n        // We will build vertex sequence by DFS stack transitions\n        seq.push_back(sidx);\n        while(!st.empty()){\n            auto &top=st.back();\n            int u=top.u;\n            if(top.it < (int)treeAdj[u].size()){\n                int v=treeAdj[u][top.it++];\n                if(v==top.p) continue;\n                seq.push_back(v);\n                st.push_back({v,u,0});\n            }else{\n                int p=top.p;\n                st.pop_back();\n                if(!st.empty()){\n                    int pu=st.back().u;\n                    seq.push_back(pu); // move back to parent vertex\n                }\n            }\n        }\n\n        TourResult res;\n        res.ok = (seq.size()>=1 && seq.front()==sidx && seq.back()==sidx);\n        res.t = t;\n        res.seq = std::move(seq);\n        return res;\n    };\n\n    auto buildEulerFromCnt = [&](vector<int> cnt)->TourResult{\n        // parity check\n        vector<int> parity(m,0);\n        for(int eid=0;eid<E;eid++){\n            if(cnt[eid]&1){\n                parity[eu[eid]]^=1;\n                parity[ev[eid]]^=1;\n            }\n        }\n        for(int u=0;u<m;u++) if(parity[u]) return {};\n\n        vector<vector<int>> inc(m);\n        for(int eid=0;eid<E;eid++){\n            if(cnt[eid]==0) continue;\n            inc[eu[eid]].push_back(eid);\n            inc[ev[eid]].push_back(eid);\n        }\n\n        // Hierholzer\n        vector<int> ptr(m,0);\n        vector<int> stV;\n        vector<int> circuit;\n        stV.reserve(1);\n        circuit.reserve(1);\n        stV.push_back(sidx);\n\n        auto otherEnd = [&](int eid, int u)->int{\n            return (u==eu[eid]? ev[eid] : eu[eid]);\n        };\n\n        while(!stV.empty()){\n            int u=stV.back();\n            auto &vec = inc[u];\n            while(ptr[u]<(int)vec.size() && cnt[vec[ptr[u]]]==0) ptr[u]++;\n            if(ptr[u]==(int)vec.size()){\n                circuit.push_back(u);\n                stV.pop_back();\n            }else{\n                int eid=vec[ptr[u]];\n                cnt[eid]--;\n                int v=otherEnd(eid,u);\n                stV.push_back(v);\n            }\n        }\n\n        reverse(circuit.begin(), circuit.end());\n        if(circuit.size()<=1) return {};\n        if(circuit.front()!=sidx || circuit.back()!=sidx) return {};\n\n        // ensure all vertices visited => v=r (important for score)\n        vector<char> seen(m,0);\n        for(int v: circuit) seen[v]=1;\n        for(int u=0;u<m;u++) if(!seen[u]) return {};\n\n        long long t=0;\n        for(int i=1;i<(int)circuit.size();i++) t += wts[circuit[i]];\n\n        TourResult res;\n        res.ok=true;\n        res.t=t;\n        res.seq=std::move(circuit);\n        return res;\n    };\n\n    // Augmented Euler tour (kept from previous good approach)\n    auto multiSourceDijkstra = [&](const vector<int>& sources,\n                                     vector<long long>& dist,\n                                     vector<int>& srcLabel,\n                                     vector<int>& parent,\n                                     vector<int>& parentEid){\n        const long long INF = (1LL<<60);\n        dist.assign(m, INF);\n        srcLabel.assign(m, -1);\n        parent.assign(m, -1);\n        parentEid.assign(m, -1);\n\n        using P = pair<long long,int>;\n        priority_queue<P, vector<P>, greater<P>> pq;\n\n        for(int s: sources){\n            dist[s]=0;\n            srcLabel[s]=s;\n            parent[s]=-1;\n            parentEid[s]=-1;\n            pq.push({0,s});\n        }\n\n        while(!pq.empty()){\n            auto [d,u]=pq.top(); pq.pop();\n            if(d!=dist[u]) continue;\n            for(auto [v,eid]: adj[u]){\n                long long nd = d + (long long)wts[u] + (long long)wts[v]; // metric\n                if(nd < dist[v]){\n                    dist[v]=nd;\n                    srcLabel[v]=srcLabel[u];\n                    parent[v]=u;\n                    parentEid[v]=eid;\n                    pq.push({nd,v});\n                }\n            }\n        }\n    };\n\n    auto augmentedEulerTour = [&](const vector<int>& mstEdgeIds, const vector<int>& mstDeg)->TourResult{\n        vector<int> cnt(E,0);\n        for(int eid: mstEdgeIds) cnt[eid]=1;\n\n        vector<int> odd;\n        for(int u=0;u<m;u++) if(mstDeg[u]&1) odd.push_back(u);\n        if(odd.empty()) return {};\n\n        // Phase 1\n        vector<long long> dist;\n        vector<int> srcLabel, parent, parentEid;\n        multiSourceDijkstra(odd, dist, srcLabel, parent, parentEid);\n\n        struct Cand{\n            long long cost;\n            int sa, sb;\n            int x, y;\n            int eid;\n            uint64_t key;\n        };\n        vector<Cand> cands;\n        cands.reserve(E);\n        for(int eid=0;eid<E;eid++){\n            int a0=eu[eid], b0=ev[eid];\n            int sa=srcLabel[a0], sb=srcLabel[b0];\n            if(sa==-1 || sb==-1 || sa==sb) continue;\n            long long cost = dist[a0] + dist[b0] + (long long)wts[a0] + (long long)wts[b0];\n            cands.push_back({cost, sa, sb, a0, b0, eid, rng()});\n        }\n        sort(cands.begin(), cands.end(), [&](const Cand& A, const Cand& B){\n            if(A.cost!=B.cost) return A.cost<B.cost;\n            if(A.key!=B.key) return A.key<B.key;\n            if(A.sa!=B.sa) return A.sa<B.sa;\n            return A.sb<B.sb;\n        });\n\n        vector<char> used(m,0);\n        auto pushPathAddEdges = [&](int node, int targetSource){\n            int cur=node;\n            while(cur!=targetSource){\n                int pe=parentEid[cur];\n                int pr=parent[cur];\n                if(pe<0 || pr<0) break;\n                cnt[pe]++; // add this edge once\n                cur=pr;\n            }\n        };\n\n        for(auto &cd: cands){\n            if(used[cd.sa] || used[cd.sb]) continue;\n            pushPathAddEdges(cd.x, cd.sa);\n            cnt[cd.eid]++; // meeting edge\n            pushPathAddEdges(cd.y, cd.sb);\n            used[cd.sa]=used[cd.sb]=1;\n        }\n\n        // Remaining odd vertices\n        vector<int> rem;\n        rem.reserve(odd.size());\n        for(int u: odd) if(!used[u]) rem.push_back(u);\n\n        // Phase 2: greedy nearest-odd pairing by directed shortest paths with early stop\n        vector<char> inRem(m,0);\n        for(int u: rem) inRem[u]=1;\n\n        auto dijkstraEarlyNearestOdd = [&](int start)->int{\n            const long long INF = (1LL<<60);\n            vector<long long> d(m, INF);\n            vector<int> par(m,-1), parE(m,-1);\n            using P = pair<long long,int>;\n            priority_queue<P, vector<P>, greater<P>> pq;\n            d[start]=0;\n            pq.push({0,start});\n\n            while(!pq.empty()){\n                auto [du,u]=pq.top(); pq.pop();\n                if(du!=d[u]) continue;\n\n                if(u!=start && inRem[u]){\n                    // add path start -> u\n                    int cur=u;\n                    while(cur!=start){\n                        int eid = parE[cur];\n                        if(eid<0) return u;\n                        cnt[eid]++; // traverse edge once\n                        cur = par[cur];\n                    }\n                    inRem[u]=0;\n                    return u;\n                }\n                for(auto [v,eid]: adj[u]){\n                    long long nd = du + (long long)wts[v]; // true move cost: enter v\n                    if(nd < d[v]){\n                        d[v]=nd;\n                        par[v]=u;\n                        parE[v]=eid;\n                        pq.push({nd,v});\n                    }\n                }\n            }\n            return -1;\n        };\n\n        while(true){\n            int a=-1;\n            for(int u: rem) if(inRem[u]) { a=u; break; }\n            if(a==-1) break;\n            inRem[a]=0;\n            (void)dijkstraEarlyNearestOdd(a);\n        }\n\n        return buildEulerFromCnt(cnt);\n    };\n\n    // Solve by trying multiple MSTs\n    TourResult best;\n    bool hasBest=false;\n\n    int attempts=16;\n    for(int it=0; it<attempts; it++){\n        bool randomTies = (it>0);\n        auto [mstE, mstDeg] = buildMST(randomTies);\n        if(mstE.empty()) continue;\n\n        TourResult aug = augmentedEulerTour(mstE, mstDeg);\n        if(aug.ok && (!hasBest || aug.t < best.t)){\n            best = std::move(aug);\n            hasBest=true;\n        }\n        TourResult base = doubledTreeTour(mstE);\n        if(base.ok && (!hasBest || base.t < best.t)){\n            best = std::move(base);\n            hasBest=true;\n        }\n    }\n\n    if(!best.ok){\n        auto [mstE, mstDeg] = buildMST(false);\n        best = doubledTreeTour(mstE);\n    }\n\n    // -------- Safe shortcutting post-process (reduces t, keeps v=r) --------\n    // Neighbors list for Dijkstra\n    vector<vector<int>> neigh(m);\n    for(int u=0;u<m;u++){\n        for(auto [v,eid]: adj[u]) neigh[u].push_back(v);\n    }\n\n    auto dijkstraPathDirected = [&](int A, int B)->vector<int>{\n        if(A==B) return {A};\n        const long long INF = (1LL<<60);\n        vector<long long> dist(m, INF);\n        vector<int> par(m,-1);\n        using P = pair<long long,int>;\n        priority_queue<P, vector<P>, greater<P>> pq;\n        dist[A]=0;\n        pq.push({0,A});\n        while(!pq.empty()){\n            auto [d,u]=pq.top(); pq.pop();\n            if(d!=dist[u]) continue;\n            if(u==B) break;\n            for(auto [v,eid]: adj[u]){\n                (void)eid;\n                long long nd = d + (long long)wts[v]; // enter v\n                if(nd < dist[v]){\n                    dist[v]=nd;\n                    par[v]=u;\n                    pq.push({nd,v});\n                }\n            }\n        }\n        if(par[B]==-1) return {};\n        vector<int> path;\n        int cur=B;\n        path.push_back(cur);\n        while(cur!=A){\n            cur=par[cur];\n            if(cur==-1) return {};\n            path.push_back(cur);\n        }\n        reverse(path.begin(), path.end());\n        return path;\n    };\n\n    auto computeTFromSeq = [&](const vector<int>& seq)->long long{\n        long long tt=0;\n        for(int i=1;i<(int)seq.size();i++) tt += wts[seq[i]];\n        return tt;\n    };\n\n    auto shortcut = [&](vector<int>& seq, long long& curT){\n        int L=(int)seq.size();\n        vector<int> cntOcc(m,0);\n        for(int v: seq) cntOcc[v]++;\n\n        // temp arrays for frequencies\n        vector<int> freqOld(m,0), freqNew(m,0), mark(m,0);\n        int stamp=1;\n\n        auto getOldSum = [&](int l,int r)->long long{\n            long long s=0;\n            for(int k=l+1;k<=r;k++) s += wts[seq[k]];\n            return s;\n        };\n        auto getNewSum = [&](const vector<int>& path)->long long{\n            long long s=0;\n            for(int i=1;i<(int)path.size();i++) s += wts[path[i]];\n            return s;\n        };\n\n        int maxGap = min(35, L-2);\n        int tries = 220;\n\n        for(int it=0; it<tries; it++){\n            if((int)seq.size() < 3) break;\n            int Lcur = (int)seq.size();\n            if(Lcur < 3) break;\n\n            int l = (int)(rng() % (Lcur-2));\n            int gap = 2 + (int)(rng() % max(1, maxGap-1));\n            int r = min(Lcur-1, l+gap);\n            if(r<=l+1) continue;\n\n            int A=seq[l], B=seq[r];\n            if(A==B) continue;\n\n            // Shortest directed path A->B\n            vector<int> path = dijkstraPathDirected(A,B);\n            if(path.size() < 2) continue; // must actually move\n            // Avoid exploding insert size\n            if((int)path.size() > 120) continue;\n\n            // Collect freqOld for seq[l+1..r] (removed), freqNew for path[1..end] (added)\n            vector<int> touchedOld, touchedNew;\n            touchedOld.reserve(r-l);\n            touchedNew.reserve(path.size());\n\n            // reset touched lists by tracking zeros -> but we zero after\n            for(int k=l+1;k<=r;k++){\n                int u=seq[k];\n                if(freqOld[u]==0) touchedOld.push_back(u);\n                freqOld[u]++;\n            }\n            for(int i=1;i<(int)path.size();i++){\n                int u=path[i];\n                if(freqNew[u]==0) touchedNew.push_back(u);\n                freqNew[u]++;\n            }\n\n            // After counts must stay > 0 for all vertices whose counts change\n            stamp++;\n            if(stamp==INT_MAX){\n                fill(mark.begin(), mark.end(), 0);\n                stamp=1;\n            }\n            vector<int> touchedUnion;\n            touchedUnion.reserve(touchedOld.size()+touchedNew.size());\n\n            auto touchUnion = [&](int u){\n                if(mark[u]==stamp) return;\n                mark[u]=stamp;\n                touchedUnion.push_back(u);\n            };\n            for(int u: touchedOld) touchUnion(u);\n            for(int u: touchedNew) touchUnion(u);\n\n            bool ok=true;\n            for(int u: touchedUnion){\n                int after = cntOcc[u] - freqOld[u] + freqNew[u];\n                if(after<=0){ ok=false; break; }\n            }\n            if(ok){\n                long long oldSum = getOldSum(l,r);\n                long long newSum = getNewSum(path);\n                long long delta = newSum - oldSum;\n                if(delta < 0){ // improve t\n                    // apply counts update\n                    for(int u: touchedOld) cntOcc[u] -= freqOld[u];\n                    for(int u: touchedNew) cntOcc[u] += freqNew[u];\n                    // apply sequence update: replace (l+1..r) by path[1..]\n                    seq.erase(seq.begin()+l+1, seq.begin()+r+1);\n                    seq.insert(seq.begin()+l+1, path.begin()+1, path.end());\n                    curT += delta;\n                }\n            }\n\n            // clear freq arrays\n            for(int u: touchedOld) freqOld[u]=0;\n            for(int u: touchedNew) freqNew[u]=0;\n        }\n    };\n\n    if(best.ok){\n        long long curT = best.t;\n        vector<int> seq = best.seq;\n        shortcut(seq, curT);\n        best.t = curT;\n        best.seq = std::move(seq);\n    }\n\n    // Build move string\n    string route;\n    if(!best.seq.empty()){\n        route.reserve(best.seq.size());\n        for(int i=0;i+1<(int)best.seq.size();i++){\n            int u=best.seq[i], v=best.seq[i+1];\n            route.push_back(dirChar(cells[u], cells[v]));\n        }\n    }\n\n    cout << route << \"\\n\";\n    return 0;\n}","future-contest-2022-qual":"#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, K, R;\n    cin >> N >> M >> K >> R;\n\n    vector<double> p(N, 0.0);      // sqrt(sum d^2)\n    vector<long long> p2(N, 0LL); // sum d^2 (for tie-break)\n\n    for (int i = 0; i < N; i++) {\n        long long sum = 0;\n        for (int k = 0; k < K; k++) {\n            long long x;\n            cin >> x;\n            sum += x * x;\n        }\n        p2[i] = sum;\n        p[i] = sqrt((double)sum);\n    }\n\n    vector<vector<int>> out(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        out[u].push_back(v);\n        indeg[v]++;\n    }\n\n    // ---- Static time-based criticality (integer scaled) ----\n    // Use a global ability guess A0 to build a rough proxy duration.\n    const double A0 = 35.0;\n    const long long SCALE = 1000LL;\n\n    vector<long long> timeProxyInt(N);\n    for (int i = 0; i < N; i++) {\n        double diff = p[i] - A0;\n        double wprime = max(0.0, diff);\n        double tproxy = 1.0 + wprime; // consistent with proxy used for scoring\n        timeProxyInt[i] = (long long)llround(tproxy * (double)SCALE);\n    }\n\n    vector<long long> critInt(N, 0);\n    for (int i = N - 1; i >= 0; i--) {\n        long long bestChild = 0;\n        for (int v : out[i]) bestChild = max(bestChild, critInt[v]);\n        critInt[i] = timeProxyInt[i] + bestChild;\n    }\n    long long maxCritInt = 0;\n    for (int i = 0; i < N; i++) maxCritInt = max(maxCritInt, critInt[i]);\n\n    // Ready set ordered by: higher criticality, then smaller difficulty norm, then id.\n    struct Comp {\n        const vector<long long>* crit;\n        const vector<long long>* p2;\n        bool operator()(int a, int b) const {\n            if ((*crit)[a] != (*crit)[b]) return (*crit)[a] > (*crit)[b];\n            if ((*p2)[a] != (*p2)[b]) return (*p2)[a] < (*p2)[b];\n            return a < b;\n        }\n    };\n    Comp comp{&critInt, &p2};\n    set<int, Comp> ready(comp);\n\n    vector<char> state(N, 0); // 0 unstarted, 1 running, 2 done\n    for (int i = 0; i < N; i++) if (indeg[i] == 0) ready.insert(i);\n\n    vector<int> curTask(M, -1);\n    vector<int> startDay(M, -1);\n\n    // ---- Learning parameters per member ----\n    // param[j] ~ threshold on p such that deficit ~ max(0, p_i - param[j])\n    // Bounds LB/UB maintained by observations.\n    const double NEG_INF = -1e100, POS_INF = 1e100;\n    vector<double> LB(M, NEG_INF), UB(M, POS_INF);\n    vector<double> param(M, A0);\n\n    auto recomputeParam = [&](int j) {\n        double lb = LB[j], ub = UB[j];\n        double x;\n        bool lbOk = (lb > NEG_INF/2);\n        bool ubOk = (ub < POS_INF/2);\n        if (!lbOk && !ubOk) x = A0;\n        else if (!lbOk) x = ub - 2.5;\n        else if (!ubOk) x = lb + 2.5;\n        else x = 0.5 * (lb + ub);\n\n        x = min(100.0, max(0.0, x));\n        param[j] = x;\n    };\n\n    // Estimate expected duration under proxy: E[t] ~ 1 + max(0, p_i - param[j])\n    auto estimateExpected = [&](int j, int task) -> double {\n        double diff = p[task] - param[j];\n        double wprime = max(0.0, diff);\n        return 1.0 + wprime;\n    };\n\n    // Score: shorter expected time is better; also favor critical tasks.\n    auto estimateScore = [&](int j, int task) -> double {\n        double expT = estimateExpected(j, task);\n        double critNorm = (maxCritInt ? (double)critInt[task] / (double)maxCritInt : 0.0);\n        const double beta = 2.0;\n        double denom = 1.0 + beta * critNorm;\n        return expT / denom;\n    };\n\n    mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());\n\n    int day = 1;\n    const int LCAND = 200; // improved from ~60\n\n    while (day <= 2000) {\n        vector<int> idle;\n        idle.reserve(M);\n        for (int j = 0; j < M; j++) if (curTask[j] == -1) idle.push_back(j);\n\n        // Stronger first (larger param => easier tasks => smaller deficit)\n        sort(idle.begin(), idle.end(), [&](int a, int b) {\n            if (param[a] != param[b]) return param[a] > param[b];\n            return a < b;\n        });\n\n        vector<pair<int,int>> assign; // (member, task)\n        assign.reserve(M);\n\n        // For each idle member choose best task from top LCAND of ready-set.\n        for (int j : idle) {\n            if (ready.empty()) break;\n\n            int bestTask = -1;\n            double bestScore = 1e100;\n            auto itBest = ready.end();\n\n            int cnt = 0;\n            for (auto it = ready.begin(); it != ready.end() && cnt < LCAND; ++it, ++cnt) {\n                int t = *it;\n                // (state[t] should be 0 here, but safe)\n                if (state[t] != 0) continue;\n\n                double sc = estimateScore(j, t);\n\n                // tiny random tie-breaker\n                sc += uniform_real_distribution<double>(0.0, 1e-7)(rng);\n\n                if (sc < bestScore) {\n                    bestScore = sc;\n                    bestTask = t;\n                    itBest = it;\n                }\n            }\n\n            if (bestTask == -1) break;\n\n            // commit\n            state[bestTask] = 1;\n            curTask[j] = bestTask;\n            startDay[j] = day;\n            ready.erase(itBest);\n            assign.emplace_back(j, bestTask);\n        }\n\n        // Output\n        cout << assign.size();\n        for (auto [j, t] : assign) {\n            cout << ' ' << (j + 1) << ' ' << (t + 1);\n        }\n        cout << \"\\n\" << flush;\n\n        // Read completion status\n        int ncomp;\n        cin >> ncomp;\n        if (ncomp == -1) return 0;\n\n        for (int i = 0; i < ncomp; i++) {\n            int f;\n            cin >> f;\n            --f; // member index\n            int task = curTask[f];\n            if (task < 0) continue; // should not happen\n\n            curTask[f] = -1;\n            state[task] = 2;\n\n            int dur = day - startDay[f] + 1;\n\n            // ---- Update bounds for param[f] using duration ----\n            // Proxy deficit: w' = max(0, p[task] - param[f])\n            // Actual model: t = max(1, w + r), r in [-3,3]\n            //\n            // We use: if dur >= 2 then w' must be > 0 => p - param = w' roughly in [dur-3, dur+3].\n            // Convert to param interval:\n            //   param in [p - (dur+3), p - (dur-3)]\n            // Clamp and update LB/UB accordingly.\n            double pi = p[task];\n\n            if (dur <= 1) {\n                // If observed 1 day, it's likely w' is very small; allow param close to pi.\n                // Conservative: param >= pi - 1 (not too strict)\n                LB[f] = max(LB[f], pi - 1.0);\n            } else {\n                double lowW = max(1.0, (double)dur - 3.0);\n                double highW = (double)dur + 3.0;\n\n                // w' in [lowW, highW] => param in [pi-highW, pi-lowW]\n                LB[f] = max(LB[f], pi - highW);\n                UB[f] = min(UB[f], pi - lowW);\n            }\n\n            // If bounds inverted due to noise, slightly relax by merging towards midpoint.\n            if (LB[f] > UB[f]) {\n                double mid = 0.5 * (LB[f] + UB[f]);\n                LB[f] = mid;\n                UB[f] = mid;\n            }\n\n            // recompute param\n            recomputeParam(f);\n\n            // Update dependencies\n            for (int v : out[task]) {\n                indeg[v]--;\n                if (indeg[v] == 0 && state[v] == 0) {\n                    ready.insert(v);\n                }\n            }\n        }\n\n        day++;\n    }\n\n    return 0;\n}","ahc006":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic inline int manhattan(int x1, int y1, int x2, int y2) {\n    return abs(x1 - x2) + abs(y1 - y2);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    const int N = 1000;\n    const int M = 50;\n    const int XOFF = 400, YOFF = 400;\n\n    vector<int> px(N), py(N), dx(N), dy(N);\n    for (int i = 0; i < N; i++) {\n        cin >> px[i] >> py[i] >> dx[i] >> dy[i];\n    }\n\n    auto idx = [&](int i, int j) { return i * N + j; };\n\n    vector<int> internal(N), startDist(N), endDist(N);\n    vector<int> trans(N * N), pickDist(N * N), dropDist(N * N);\n\n    for (int i = 0; i < N; i++) {\n        internal[i] = manhattan(px[i], py[i], dx[i], dy[i]);              // pick_i -> drop_i\n        startDist[i] = manhattan(XOFF, YOFF, px[i], py[i]);              // office -> pick_i\n        endDist[i] = manhattan(dx[i], dy[i], XOFF, YOFF);                // drop_i -> office\n    }\n    for (int i = 0; i < N; i++) {\n        int dix = dx[i], diy = dy[i];\n        int pix = px[i], piy = py[i];\n        for (int j = 0; j < N; j++) {\n            // trans: drop_i -> pick_j\n            trans[idx(i, j)] = manhattan(dix, diy, px[j], py[j]);\n            // pickDist: pick_i -> pick_j\n            pickDist[idx(i, j)] = manhattan(pix, piy, px[j], py[j]);\n            // dropDist: drop_i -> drop_j\n            dropDist[idx(i, j)] = manhattan(dix, diy, dx[j], dy[j]);\n        }\n    }\n\n    auto getTrans = [&](int i, int j) -> int { return trans[idx(i, j)]; };\n    auto getPick  = [&](int i, int j) -> int { return pickDist[idx(i, j)]; };\n    auto getDrop  = [&](int i, int j) -> int { return dropDist[idx(i, j)]; };\n\n    auto macroCost = [&](const vector<int>& seq, long long internalSum) -> long long {\n        // office -> pick(seq0) -> drop(seq0) .. -> office\n        long long cost = internalSum;\n        cost += startDist[seq[0]];\n        cost += endDist[seq[M - 1]];\n        for (int i = 0; i + 1 < M; i++) cost += getTrans(seq[i], seq[i + 1]); // drop_i -> pick_next\n        return cost;\n    };\n\n    auto twoStageCostExact = [&](const vector<int>& P, const vector<int>& D) -> long long {\n        // office -> pick P... -> drop D... -> office\n        long long cost = 0;\n        cost += startDist[P[0]];\n        for (int i = 0; i + 1 < M; i++) cost += getPick(P[i], P[i + 1]);\n        // cross: pick_last -> drop_D[0] == trans[D[0]][P_last] (symmetry)\n        cost += getTrans(D[0], P[M - 1]);\n        for (int i = 0; i + 1 < M; i++) cost += getDrop(D[i], D[i + 1]);\n        cost += endDist[D[M - 1]];\n        return cost;\n    };\n\n    auto buildMacroRoute = [&](const vector<int>& seq) -> vector<pair<int,int>> {\n        vector<pair<int,int>> route;\n        route.reserve(2 * M + 2);\n        route.push_back({XOFF, YOFF});\n        for (int ord : seq) {\n            route.push_back({px[ord], py[ord]});\n            route.push_back({dx[ord], dy[ord]});\n        }\n        route.push_back({XOFF, YOFF});\n        return route;\n    };\n\n    auto buildTwoStageRoute = [&](const vector<int>& P, const vector<int>& D) -> vector<pair<int,int>> {\n        vector<pair<int,int>> route;\n        route.reserve(2 * M + 2);\n        route.push_back({XOFF, YOFF});\n        for (int ord : P) route.push_back({px[ord], py[ord]});\n        for (int ord : D) route.push_back({dx[ord], dy[ord]});\n        route.push_back({XOFF, YOFF});\n        return route;\n    };\n\n    // ---------- Weighted subset sampling ----------\n    vector<long long> weight(N);\n    for (int i = 0; i < N; i++) weight[i] = (long long)internal[i] + startDist[i] + endDist[i];\n\n    vector<int> ids(N);\n    iota(ids.begin(), ids.end(), 0);\n    sort(ids.begin(), ids.end(), [&](int a, int b) {\n        if (weight[a] != weight[b]) return weight[a] < weight[b];\n        return a < b;\n    });\n\n    vector<int> pool;\n    int TOP = 350;\n    for (int i = 0; i < TOP; i++) pool.push_back(ids[i]);\n\n    mt19937 rng((uint32_t)chrono::steady_clock::now().time_since_epoch().count());\n    uniform_int_distribution<int> uniAll(0, N - 1);\n    while ((int)pool.size() < 560) {\n        int v = uniAll(rng);\n        if (!binary_search(pool.begin(), pool.end(), v)) pool.push_back(v);\n    }\n    sort(pool.begin(), pool.end());\n    pool.erase(unique(pool.begin(), pool.end()), pool.end());\n\n    auto sampleSubset = [&](int k) -> vector<int> {\n        // Exponential race sampling without replacement from pool\n        // key = -log(u) * (weight[v]+1)  -> smaller weight tends to smaller key\n        vector<pair<long double,int>> keys;\n        keys.reserve(pool.size());\n        uniform_real_distribution<long double> ur(1e-12L, 1.0L);\n\n        for (int v : pool) {\n            long double u = ur(rng);\n            long double key = -log(u) * ((long double)weight[v] + 1.0L);\n            keys.push_back({key, v});\n        }\n        nth_element(keys.begin(), keys.begin() + k, keys.end(),\n                    [](auto &a, auto &b){ return a.first < b.first; });\n        keys.resize(k);\n        vector<int> subset;\n        subset.reserve(k);\n        for (auto &p : keys) subset.push_back(p.second);\n        return subset;\n    };\n\n    // ---------- Greedy macro order for a fixed subset ----------\n    auto greedyMacroForward = [&](const vector<int>& subset) -> vector<int> {\n        vector<char> used(N, 0);\n        vector<int> seq; seq.reserve(M);\n\n        // choose first: smallest startDist (optionally randomize among ties)\n        int first = subset[0];\n        for (int v : subset) if (startDist[v] < startDist[first]) first = v;\n        seq.push_back(first);\n        used[first] = 1;\n\n        while ((int)seq.size() < M) {\n            int cur = seq.back();\n            bool isLast = ((int)seq.size() == M - 1);\n            int best = -1;\n            long long bestVal = (1LL<<62);\n\n            for (int cand : subset) if (!used[cand]) {\n                long long val = getTrans(cur, cand);\n                if (isLast) val += endDist[cand];\n                if (val < bestVal) {\n                    bestVal = val;\n                    best = cand;\n                }\n            }\n            // should always find\n            used[best] = 1;\n            seq.push_back(best);\n        }\n        return seq;\n    };\n\n    auto greedyMacroBackward = [&](const vector<int>& subset) -> vector<int> {\n        vector<char> used(N, 0);\n        vector<int> seq(M, -1);\n\n        // choose last: smallest endDist\n        int last = subset[0];\n        for (int v : subset) if (endDist[v] < endDist[last]) last = v;\n        seq[M-1] = last;\n        used[last] = 1;\n\n        for (int pos = M - 2; pos >= 0; pos--) {\n            int nxt = seq[pos + 1];\n            bool isFirst = (pos == 0);\n\n            int best = -1;\n            long long bestVal = (1LL<<62);\n\n            for (int cand : subset) if (!used[cand]) {\n                long long val = getTrans(cand, nxt); // drop_cand -> pick_nxt\n                if (isFirst) val += startDist[cand];\n                if (val < bestVal) {\n                    bestVal = val;\n                    best = cand;\n                }\n            }\n            used[best] = 1;\n            seq[pos] = best;\n        }\n        return seq;\n    };\n\n    auto improveMacroSwapOnly = [&](vector<int>& seq, long long internalSum, int rounds, const chrono::steady_clock::time_point& stopTime) {\n        auto timeUp = [&](){ return chrono::steady_clock::now() >= stopTime; };\n\n        long long cur = macroCost(seq, internalSum);\n\n        for (int r = 0; r < rounds; r++) {\n            if (timeUp()) break;\n\n            bool improved = false;\n            long long bestCost = cur;\n            int bi = -1, bj = -1;\n\n            for (int i = 0; i < M && !timeUp(); i++) {\n                for (int j = i + 1; j < M && !timeUp(); j++) {\n                    swap(seq[i], seq[j]);\n                    long long nc = macroCost(seq, internalSum);\n                    swap(seq[i], seq[j]);\n                    if (nc < bestCost) {\n                        bestCost = nc;\n                        bi = i; bj = j;\n                    }\n                }\n            }\n            if (bi != -1 && bj != -1 && bestCost < cur) {\n                swap(seq[bi], seq[bj]);\n                cur = bestCost;\n                improved = true;\n            }\n            if (!improved) break;\n        }\n    };\n\n    // ---------- Two-stage build & local search from a fixed chosen set (subsetSeq) ----------\n    auto buildTwoStageFromSet = [&](const vector<int>& subsetSeq, vector<int>& P, vector<int>& D) {\n        // Use subsetSeq as a set (permutation), but we build P & D permutations.\n        const vector<int>& set = subsetSeq;\n\n        // Build pickup order P: start with min startDist, then nearest by pickDist\n        int startPick = set[0];\n        for (int v : set) if (startDist[v] < startDist[startPick]) startPick = v;\n\n        P.clear(); P.reserve(M);\n        vector<char> usedP(N, 0);\n        P.push_back(startPick);\n        usedP[startPick] = 1;\n\n        while ((int)P.size() < M) {\n            int cur = P.back();\n            int best = -1;\n            int bestVal = INT_MAX;\n            for (int cand : set) if (!usedP[cand]) {\n                int val = getPick(cur, cand);\n                if (val < bestVal) {\n                    bestVal = val;\n                    best = cand;\n                }\n            }\n            usedP[best] = 1;\n            P.push_back(best);\n        }\n\n        // Build destination order D:\n        // first dest minimizes cross from last pickup: pick_last -> drop_dest == trans[dest][pick_last]\n        int lastPick = P.back();\n        int firstDest = set[0];\n        int bestCross = getTrans(firstDest, lastPick);\n        for (int v : set) {\n            int c = getTrans(v, lastPick);\n            if (c < bestCross) {\n                bestCross = c;\n                firstDest = v;\n            }\n        }\n\n        D.clear(); D.reserve(M);\n        vector<char> usedD(N, 0);\n        D.push_back(firstDest);\n        usedD[firstDest] = 1;\n\n        while ((int)D.size() < M) {\n            int curDrop = D.back();\n            int best = -1;\n            int bestVal = INT_MAX;\n            for (int cand : set) if (!usedD[cand]) {\n                int val = getDrop(curDrop, cand);\n                if (val < bestVal) {\n                    bestVal = val;\n                    best = cand;\n                }\n            }\n            usedD[best] = 1;\n            D.push_back(best);\n        }\n    };\n\n    auto improveTwoStageSwapOnly = [&](vector<int>& P, vector<int>& D, int rounds, const chrono::steady_clock::time_point& stopTime) {\n        auto timeUp = [&](){ return chrono::steady_clock::now() >= stopTime; };\n\n        for (int r = 0; r < rounds; r++) {\n            if (timeUp()) break;\n\n            long long cur = twoStageCostExact(P, D);\n            bool improved = false;\n\n            // swap in P\n            long long best = cur;\n            int bi=-1, bj=-1;\n            for (int i = 0; i < M && !timeUp(); i++) {\n                for (int j = i + 1; j < M && !timeUp(); j++) {\n                    swap(P[i], P[j]);\n                    long long nc = twoStageCostExact(P, D);\n                    swap(P[i], P[j]);\n                    if (nc < best) {\n                        best = nc; bi=i; bj=j;\n                    }\n                }\n            }\n            if (bi != -1) {\n                swap(P[bi], P[bj]);\n                cur = best;\n                improved = true;\n            }\n\n            if (timeUp()) break;\n\n            // swap in D\n            best = cur; bi=-1; bj=-1;\n            for (int i = 0; i < M && !timeUp(); i++) {\n                for (int j = i + 1; j < M && !timeUp(); j++) {\n                    swap(D[i], D[j]);\n                    long long nc = twoStageCostExact(P, D);\n                    swap(D[i], D[j]);\n                    if (nc < best) {\n                        best = nc; bi=i; bj=j;\n                    }\n                }\n            }\n            if (bi != -1) {\n                swap(D[bi], D[bj]);\n                improved = true;\n            }\n\n            if (!improved) break;\n        }\n    };\n\n    // ---------- Main search ----------\n    auto stopTime = chrono::steady_clock::now() + chrono::milliseconds(1850);\n    auto timeUp = [&](){ return chrono::steady_clock::now() >= stopTime; };\n\n    struct Cand {\n        long long macroCostVal;\n        vector<int> seq; // macro permutation (also chosen set)\n    };\n\n    vector<Cand> bestMacros;\n    bestMacros.reserve(18);\n\n    auto pushMacroCand = [&](long long costVal, const vector<int>& seq) {\n        if ((int)bestMacros.size() < 14) {\n            bestMacros.push_back({costVal, seq});\n            return;\n        }\n        // keep best 14\n        int worst = 0;\n        for (int i = 1; i < (int)bestMacros.size(); i++) {\n            if (bestMacros[i].macroCostVal > bestMacros[worst].macroCostVal) worst = i;\n        }\n        if (costVal < bestMacros[worst].macroCostVal) bestMacros[worst] = {costVal, seq};\n    };\n\n    // Seed with deterministic subsets\n    int reps = 6;\n    for (int rep = 0; rep < reps && !timeUp(); rep++) {\n        vector<int> subset;\n        if (rep == 0) {\n            subset.assign(ids.begin(), ids.begin() + M);\n        } else if (rep == 1) {\n            vector<int> v = ids;\n            sort(v.begin(), v.end(), [&](int a, int b){ return internal[a] < internal[b]; });\n            subset.assign(v.begin(), v.begin() + M);\n        } else if (rep == 2) {\n            vector<int> v = ids;\n            sort(v.begin(), v.end(), [&](int a, int b){ return startDist[a] < startDist[b]; });\n            subset.assign(v.begin(), v.begin() + M);\n        } else if (rep == 3) {\n            vector<int> v = ids;\n            sort(v.begin(), v.end(), [&](int a, int b){ return endDist[a] < endDist[b]; });\n            subset.assign(v.begin(), v.begin() + M);\n        } else {\n            subset = sampleSubset(M);\n        }\n\n        long long isum = 0;\n        for (int v : subset) isum += internal[v];\n\n        auto seqF = greedyMacroForward(subset);\n        improveMacroSwapOnly(seqF, isum, 2, stopTime);\n        pushMacroCand(macroCost(seqF, isum), seqF);\n\n        if (timeUp()) break;\n\n        auto seqB = greedyMacroBackward(subset);\n        improveMacroSwapOnly(seqB, isum, 2, stopTime);\n        pushMacroCand(macroCost(seqB, isum), seqB);\n    }\n\n    // Random sampling\n    int it = 0;\n    while (!timeUp() && it < 90) {\n        it++;\n        vector<int> subset = sampleSubset(M);\n\n        long long isum = 0;\n        for (int v : subset) isum += internal[v];\n\n        auto seqF = greedyMacroForward(subset);\n        improveMacroSwapOnly(seqF, isum, 1, stopTime);\n        long long cf = macroCost(seqF, isum);\n        pushMacroCand(cf, seqF);\n\n        if (timeUp()) break;\n\n        auto seqB = greedyMacroBackward(subset);\n        improveMacroSwapOnly(seqB, isum, 1, stopTime);\n        long long cb = macroCost(seqB, isum);\n        pushMacroCand(cb, seqB);\n    }\n\n    sort(bestMacros.begin(), bestMacros.end(), [&](const Cand& a, const Cand& b){\n        return a.macroCostVal < b.macroCostVal;\n    });\n\n    // Evaluate two-stage on top macro candidates\n    long long bestTotal = (1LL<<62);\n    vector<int> bestOrders; // size M\n    vector<pair<int,int>> bestRoute;\n\n    int K2 = min(8, (int)bestMacros.size());\n    for (int i = 0; i < K2 && !timeUp(); i++) {\n        const auto& mc = bestMacros[i];\n        vector<int> P, D;\n        buildTwoStageFromSet(mc.seq, P, D);\n        improveTwoStageSwapOnly(P, D, 1, stopTime);\n        long long tc = twoStageCostExact(P, D);\n        if (tc < bestTotal) {\n            bestTotal = tc;\n            bestOrders = P; // pickup order contains all chosen orders\n            bestRoute = buildTwoStageRoute(P, D);\n        }\n    }\n\n    // Fallback: macro best if two-stage didn't beat anything\n    if (bestOrders.empty()) {\n        const auto& mc = bestMacros[0];\n        long long isum = 0;\n        for (int v : mc.seq) isum += internal[v];\n        bestTotal = mc.macroCostVal;\n        bestOrders = mc.seq;\n        bestRoute = buildMacroRoute(mc.seq);\n    }\n\n    // Output\n    cout << M << \"\\n\";\n    for (int i = 0; i < M; i++) {\n        if (i) cout << ' ';\n        cout << (bestOrders[i] + 1);\n    }\n    cout << \"\\n\";\n\n    cout << bestRoute.size() << \"\\n\";\n    for (auto &pt : bestRoute) {\n        cout << pt.first << ' ' << pt.second << ' ';\n    }\n    cout << \"\\n\";\n    return 0;\n}","ahc007":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct DSU {\n    int n;\n    vector<int> p, sz;\n    int comps;\n    DSU() : n(0), comps(0) {}\n    explicit DSU(int n_) { init(n_); }\n\n    void init(int n_) {\n        n = n_;\n        p.resize(n);\n        sz.assign(n, 1);\n        iota(p.begin(), p.end(), 0);\n        comps = n;\n    }\n\n    inline int find(int x) {\n        while (p[x] != x) {\n            p[x] = p[p[x]];\n            x = p[x];\n        }\n        return x;\n    }\n\n    inline bool 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        comps--;\n        return true;\n    }\n};\n\nstatic inline int distRound(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    double d = sqrt((double)dx * dx + (double)dy * dy);\n    return (int)llround(d);\n}\n\n// Feasible iff (current accepted edges) + (all remaining edges remIdx..M-1) is connected.\nstatic bool feasibleSkip(int N, int remIdx, DSU &curDSU,\n                          const vector<vector<uint16_t>> &sufRoot) {\n    if (curDSU.comps == 1) return true;\n\n    vector<int> rootToId(N, -1), compId(N);\n    int k = 0;\n    for (int v = 0; v < N; v++) {\n        int r = curDSU.find(v);\n        int &id = rootToId[r];\n        if (id == -1) id = k++;\n        compId[v] = id;\n    }\n    if (k <= 1) return true;\n\n    DSU comb(k);\n    vector<int> firstA(N, -1); // suffix-root -> first component-id\n    for (int v = 0; v < N; v++) {\n        int a = compId[v];\n        int bRoot = (int)sufRoot[remIdx][v]; // [0..N-1]\n        int &f = firstA[bRoot];\n        if (f == -1) f = a;\n        else comb.unite(a, f);\n        if (comb.comps == 1) return true;\n    }\n    return comb.comps == 1;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int a, b;\n    if (!(cin >> a >> b)) return 0;\n\n    int N, M;\n    vector<int> x, y, U, V;\n\n    // Robust parsing:\n    // If format is \"N M\" then M is large (>800). Otherwise N=400, M=1995 as per task.\n    if (b > 800) {\n        N = a; M = b;\n        x.assign(N, 0); y.assign(N, 0);\n        for (int i = 0; i < N; i++) cin >> x[i] >> y[i];\n        U.assign(M, 0); V.assign(M, 0);\n        for (int i = 0; i < M; i++) cin >> U[i] >> V[i];\n    } else {\n        N = 400; M = 1995;\n        x.assign(N, 0); y.assign(N, 0);\n        x[0] = a; y[0] = b;\n        for (int i = 1; i < N; i++) cin >> x[i] >> y[i];\n        U.assign(M, 0); V.assign(M, 0);\n        for (int i = 0; i < M; i++) cin >> U[i] >> V[i];\n    }\n\n    vector<int> d(M);\n    for (int i = 0; i < M; i++) {\n        d[i] = distRound(x[U[i]], y[U[i]], x[V[i]], y[V[i]]);\n        if (d[i] == 0) d[i] = 1;\n    }\n\n    // Offline MST on proxy weights d[i]\n    vector<int> ord(M);\n    iota(ord.begin(), ord.end(), 0);\n    sort(ord.begin(), ord.end(), [&](int i, int j) {\n        if (d[i] != d[j]) return d[i] < d[j];\n        return i < j;\n    });\n\n    DSU dsuTmp(N);\n    vector<char> inMST(M, 0);\n    long long mst_d_sum = 0;\n\n    for (int idx : ord) {\n        if (dsuTmp.unite(U[idx], V[idx])) {\n            inMST[idx] = 1;\n            mst_d_sum += d[idx];\n        }\n    }\n\n    // Precompute suffix DSU roots for feasibility checking\n    vector<vector<uint16_t>> sufRoot(M + 1, vector<uint16_t>(N));\n    DSU sufDSU(N);\n    for (int v = 0; v < N; v++) sufRoot[M][v] = (uint16_t)v;\n\n    for (int i = M - 1; i >= 0; i--) {\n        sufDSU.unite(U[i], V[i]);\n        for (int v = 0; v < N; v++) sufRoot[i][v] = (uint16_t)sufDSU.find(v);\n    }\n\n    // Estimated average true MST edge length ~ E[l|d]=2d\n    double avgTarget = 2.0 * (double)mst_d_sum / (double)(N - 1);\n\n    DSU curDSU(N);\n\n    for (int i = 0; i < M; i++) {\n        long long li;\n        cin >> li;\n\n        int ru = curDSU.find(U[i]);\n        int rv = curDSU.find(V[i]);\n        if (ru == rv) {\n            cout << 0 << \"\\n\" << flush;\n            continue;\n        }\n\n        double progress = (M <= 1 ? 1.0 : (double)i / (double)(M - 1)); // [0,1]\n\n        // Ratio threshold\n        double rThreshold = 1.58 + 1.38 * progress; // ~[1.58,2.96]\n        if (inMST[i]) rThreshold += 0.18;\n        else rThreshold -= 0.06;\n        rThreshold = max(1.0, min(3.0, rThreshold));\n\n        bool acceptRatio = (long double)li <= (long double)rThreshold * (long double)d[i];\n\n        // Absolute threshold (slightly relaxed to avoid early over-rejection)\n        double absThreshold = avgTarget * (0.98 + 0.72 * progress); // ~[0.98,1.70] * avgTarget\n        if (inMST[i]) absThreshold *= 1.04;\n\n        bool acceptAbs = (long double)li <= (long double)absThreshold;\n\n        // Very cheap edges are almost always good\n        bool ultraGood = (long double)li <= (long double)1.25 * (long double)d[i];\n\n        // Final decision: allow MST edges to pass even if absThreshold fails a bit.\n        bool accept = ultraGood || (acceptRatio && (acceptAbs || inMST[i]));\n\n        if (!accept) {\n            bool ok = feasibleSkip(N, i + 1, curDSU, sufRoot);\n            if (!ok) accept = true; // forced to keep feasibility\n        }\n\n        if (accept) {\n            curDSU.unite(ru, rv);\n            cout << 1 << \"\\n\" << flush;\n        } else {\n            cout << 0 << \"\\n\" << flush;\n        }\n    }\n\n    return 0;\n}","ahc008":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const int H = 30, W = 30;\nstatic const int V = H * W;\nstatic inline int id(int x, int y) { return x * W + y; }\nstatic inline bool inb(int x, int y) { return 0 <= x && x < H && 0 <= y && y < W; }\n\nstatic const int dx4[4] = {-1, 1, 0, 0};\nstatic const int dy4[4] = {0, 0, -1, 1};\n\nstatic char moveChar(int from, int to) {\n    int fx = from / W, fy = from % W;\n    int tx = to / W, ty = to % W;\n    if (tx == fx - 1 && ty == fy) return 'U';\n    if (tx == fx + 1 && ty == fy) return 'D';\n    if (tx == fx && ty == fy - 1) return 'L';\n    if (tx == fx && ty == fy + 1) return 'R';\n    return '.';\n}\n\nstatic char blockChar(int from, int to) {\n    int fx = from / W, fy = from % W;\n    int tx = to / W, ty = to % W;\n    if (tx == fx - 1 && ty == fy) return 'u';\n    if (tx == fx + 1 && ty == fy) return 'd';\n    if (tx == fx && ty == fy - 1) return 'l';\n    if (tx == fx && ty == fy + 1) return 'r';\n    return '.';\n}\n\nstatic bool isAdj(int a, int b) {\n    int ax = a / W, ay = a % W;\n    int bx = b / W, by = b % W;\n    return abs(ax - bx) + abs(ay - by) == 1;\n}\n\n// NOTE: rng is NON-const now (compile fix)\nstatic vector<int> computeWallPathVerticalOrHorizontal(\n    bool vertical,\n    const vector<char>& humanInitAt,\n    const vector<char>& petInitAt,\n    mt19937& rng // <-- changed from const mt19937&\n) {\n    const int INF = 1e9;\n    vector<int> cellCost(V, 1);\n\n    for (int x = 0; x < H; x++) for (int y = 0; y < W; y++) {\n        int c = id(x, y);\n        if (humanInitAt[c]) { cellCost[c] = INF; continue; }\n\n        int cost = 1;\n        if (petInitAt[c]) cost += 300;\n\n        int petAdj = 0;\n        for (int k = 0; k < 4; k++) {\n            int nx = x + dx4[k], ny = y + dy4[k];\n            if (!inb(nx, ny)) continue;\n            if (petInitAt[id(nx, ny)]) petAdj++;\n        }\n        cost += petAdj * 90;\n\n        // tiny randomness\n        cost += (int)(rng() % 3); // <-- now valid\n        cellCost[c] = cost;\n    }\n\n    using P = pair<long long,int>;\n    vector<long long> dist(V, (long long)INF * INF);\n    vector<int> parent(V, -1);\n    priority_queue<P, vector<P>, greater<P>> pq;\n\n    if (vertical) {\n        for (int y = 0; y < W; y++) {\n            int s = id(0, y);\n            if (cellCost[s] >= INF) continue;\n            dist[s] = cellCost[s];\n            parent[s] = -2;\n            pq.push({dist[s], s});\n        }\n    } else {\n        for (int x = 0; x < H; x++) {\n            int s = id(x, 0);\n            if (cellCost[s] >= INF) continue;\n            dist[s] = cellCost[s];\n            parent[s] = -2;\n            pq.push({dist[s], s});\n        }\n    }\n\n    int bestGoal = -1;\n    long long bestDist = (long long)INF * INF;\n\n    while (!pq.empty()) {\n        auto [d, u] = pq.top(); pq.pop();\n        if (d != dist[u]) continue;\n\n        int ux = u / W, uy = u % W;\n        if (vertical) {\n            if (ux == H - 1) {\n                if (d < bestDist) { bestDist = d; bestGoal = u; }\n            }\n        } else {\n            if (uy == W - 1) {\n                if (d < bestDist) { bestDist = d; bestGoal = u; }\n            }\n        }\n\n        for (int k = 0; k < 4; k++) {\n            int vx = ux + dx4[k], vy = uy + dy4[k];\n            if (!inb(vx, vy)) continue;\n            int v = id(vx, vy);\n            if (cellCost[v] >= INF) continue;\n            long long nd = d + cellCost[v];\n            if (nd < dist[v]) {\n                dist[v] = nd;\n                parent[v] = u;\n                pq.push({nd, v});\n            }\n        }\n    }\n\n    if (bestGoal == -1) {\n        // fallback straight line\n        vector<int> path;\n        if (vertical) {\n            int ymid = W / 2;\n            for (int x = 0; x < H; x++) path.push_back(id(x, ymid));\n        } else {\n            int xmid = H / 2;\n            for (int y = 0; y < W; y++) path.push_back(id(xmid, y));\n        }\n        return path;\n    }\n\n    vector<int> path;\n    int cur = bestGoal;\n    while (true) {\n        path.push_back(cur);\n        int p = parent[cur];\n        if (p == -2) break;\n        cur = p;\n        if (cur < 0) break;\n    }\n    reverse(path.begin(), path.end());\n    return path;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    mt19937 rng((uint32_t)chrono::steady_clock::now().time_since_epoch().count());\n\n    int N;\n    cin >> N;\n    vector<int> petPos(N);\n    vector<char> petInitAt(V, 0);\n    for (int i = 0; i < N; i++) {\n        int px, py, pt;\n        cin >> px >> py >> pt;\n        --px; --py;\n        petPos[i] = id(px, py);\n        petInitAt[petPos[i]] = 1;\n    }\n\n    int M;\n    cin >> M;\n    vector<int> humanPos(M);\n    vector<char> humanInitAt(V, 0);\n    for (int i = 0; i < M; i++) {\n        int hx, hy;\n        cin >> hx >> hy;\n        --hx; --hy;\n        humanPos[i] = id(hx, hy);\n        humanInitAt[humanPos[i]] = 1;\n    }\n\n    // Choose wall orientation\n    auto evaluateWall = [&](const vector<int>& wall) -> double {\n        vector<char> wallSet(V, 0);\n        for (int c : wall) wallSet[c] = 1;\n\n        vector<int> compId(V, -1);\n        int compCnt = 0;\n        vector<int> compSize;\n        queue<int> q;\n\n        for (int s = 0; s < V; s++) {\n            if (wallSet[s]) continue;\n            if (compId[s] != -1) continue;\n            compId[s] = compCnt;\n            int sz = 0;\n            q.push(s);\n            while (!q.empty()) {\n                int u = q.front(); q.pop();\n                sz++;\n                int ux = u / W, uy = u % W;\n                for (int k = 0; k < 4; k++) {\n                    int vx = ux + dx4[k], vy = uy + dy4[k];\n                    if (!inb(vx, vy)) continue;\n                    int v = id(vx, vy);\n                    if (wallSet[v]) continue;\n                    if (compId[v] != -1) continue;\n                    compId[v] = compCnt;\n                    q.push(v);\n                }\n            }\n            compSize.push_back(sz);\n            compCnt++;\n        }\n\n        vector<int> petCnt(compCnt, 0);\n        for (int i = 0; i < N; i++) {\n            int p = petPos[i];\n            if (wallSet[p]) continue;\n            int c = compId[p];\n            if (c >= 0) petCnt[c]++;\n        }\n\n        const int PETCAP = 6;\n        vector<double> compScore(compCnt, 0.0);\n        for (int c = 0; c < compCnt; c++) {\n            int n = min(petCnt[c], PETCAP);\n            compScore[c] = (double)compSize[c] / 900.0 * pow(0.5, n);\n        }\n\n        vector<double> top = compScore;\n        sort(top.begin(), top.end(), greater<double>());\n\n        int use = min(M, (int)top.size());\n        double sum = 0;\n        for (int i = 0; i < use; i++) sum += top[i];\n        for (int i = use; i < M; i++) sum += (top.empty() ? 0 : top[0]);\n        return sum / M;\n    };\n\n    vector<int> wallV = computeWallPathVerticalOrHorizontal(true, humanInitAt, petInitAt, rng);\n    vector<int> wallH = computeWallPathVerticalOrHorizontal(false, humanInitAt, petInitAt, rng);\n    vector<int> wall = (evaluateWall(wallV) >= evaluateWall(wallH) ? wallV : wallH);\n\n    // final wall\n    vector<char> wallSet(V, 0);\n    vector<int> wallIndex(V, -1);\n    for (int i = 0; i < (int)wall.size(); i++) {\n        wallSet[wall[i]] = 1;\n        wallIndex[wall[i]] = i;\n    }\n    int L = (int)wall.size();\n\n    // components in final-wall obstacle world\n    vector<int> compId(V, -1);\n    vector<vector<int>> compCells;\n    queue<int> q;\n    for (int s = 0; s < V; s++) {\n        if (wallSet[s] || compId[s] != -1) continue;\n        int cid = (int)compCells.size();\n        compId[s] = cid;\n        compCells.push_back({});\n        q.push(s);\n        while (!q.empty()) {\n            int u = q.front(); q.pop();\n            compCells[cid].push_back(u);\n            int ux = u / W, uy = u % W;\n            for (int k = 0; k < 4; k++) {\n                int vx = ux + dx4[k], vy = uy + dy4[k];\n                if (!inb(vx, vy)) continue;\n                int v = id(vx, vy);\n                if (wallSet[v] || compId[v] != -1) continue;\n                compId[v] = cid;\n                q.push(v);\n            }\n        }\n    }\n    int compCnt = (int)compCells.size();\n\n    vector<int> compSize(compCnt, 0);\n    for (int c = 0; c < compCnt; c++) compSize[c] = (int)compCells[c].size();\n\n    // distInterior: distance to nearest wall cell\n    vector<int> distInterior(V, -1);\n    queue<int> q2;\n    for (int c = 0; c < V; c++) if (wallSet[c]) {\n        distInterior[c] = 0;\n        q2.push(c);\n    }\n    while (!q2.empty()) {\n        int u = q2.front(); q2.pop();\n        int ux = u / W, uy = u % W;\n        for (int k = 0; k < 4; k++) {\n            int vx = ux + dx4[k], vy = uy + dy4[k];\n            if (!inb(vx, vy)) continue;\n            int v = id(vx, vy);\n            if (wallSet[v]) continue;\n            if (distInterior[v] != -1) continue;\n            distInterior[v] = distInterior[u] + 1;\n            q2.push(v);\n        }\n    }\n\n    // distMat for non-builders: BFS from every start (900*900*edges is fine)\n    vector<int16_t> distMat((size_t)V * V, (int16_t)-1);\n    for (int s = 0; s < V; s++) {\n        if (wallSet[s]) continue;\n        vector<int16_t> dist(V, (int16_t)-1);\n        queue<int> qq;\n        dist[s] = 0;\n        qq.push(s);\n        while (!qq.empty()) {\n            int u = qq.front(); qq.pop();\n            int ux = u / W, uy = u % W;\n            for (int k = 0; k < 4; k++) {\n                int vx = ux + dx4[k], vy = uy + dy4[k];\n                if (!inb(vx, vy)) continue;\n                int v = id(vx, vy);\n                if (wallSet[v]) continue;\n                if (dist[v] != -1) continue;\n                dist[v] = dist[u] + 1;\n                qq.push(v);\n            }\n        }\n        for (int t = 0; t < V; t++) distMat[(size_t)s * V + t] = dist[t];\n    }\n\n    // top candidate cells for each component\n    int TOPCELLS = 8;\n    vector<vector<int>> topCells(compCnt);\n    for (int c = 0; c < compCnt; c++) {\n        auto cells = compCells[c];\n        sort(cells.begin(), cells.end(), [&](int a, int b){\n            return distInterior[a] > distInterior[b];\n        });\n        int take = min(TOPCELLS, (int)cells.size());\n        topCells[c].assign(cells.begin(), cells.begin() + take);\n        if (topCells[c].empty() && !cells.empty()) topCells[c].push_back(cells[0]);\n    }\n\n    int K = min(4, M);\n    if (K < 1) K = 1;\n\n    vector<int> segL(K), segR(K);\n    for (int k = 0; k < K; k++) {\n        segL[k] = (long long)k * L / K;\n        segR[k] = (long long)(k + 1) * L / K;\n        if (segR[k] < segL[k]) segR[k] = segL[k];\n    }\n\n    // choose builders greedily\n    vector<int> builderHuman(K, -1);\n    vector<char> usedHuman(M, 0);\n\n    vector<int> segKey(K, -1);\n    for (int k = 0; k < K; k++) {\n        int mid = (segL[k] + segR[k]) / 2;\n        mid = max(0, min(L - 1, mid));\n        segKey[k] = wall[mid];\n    }\n\n    vector<int> order(K);\n    iota(order.begin(), order.end(), 0);\n    sort(order.begin(), order.end(), [&](int a, int b){\n        return (segR[a] - segL[a]) > (segR[b] - segL[b]);\n    });\n\n    for (int idx = 0; idx < K; idx++) {\n        int k = order[idx];\n        int keyCell = segKey[k];\n        int best = -1, bestD = INT_MAX;\n        for (int h = 0; h < M; h++) if (!usedHuman[h]) {\n            int dh = abs(humanPos[h] / W - keyCell / W) + abs(humanPos[h] % W - keyCell % W);\n            if (dh < bestD) { bestD = dh; best = h; }\n        }\n        if (best == -1) best = 0;\n        builderHuman[k] = best;\n        usedHuman[best] = 1;\n    }\n\n    vector<char> isBuilder(M, 0);\n    for (int k = 0; k < K; k++) isBuilder[builderHuman[k]] = 1;\n\n    vector<int> ptr(K);\n    for (int k = 0; k < K; k++) ptr[k] = segL[k];\n\n    vector<char> blockedActual(V, 0);\n    vector<int> willBlockWallCell(K, -1);\n\n    auto canBlockNow = [&](int targetCell, const vector<char>& petAtNow, const vector<char>& humanAtNow) -> bool {\n        if (targetCell < 0 || targetCell >= V) return false;\n        if (blockedActual[targetCell]) return false;\n        if (petAtNow[targetCell]) return false;\n        if (humanAtNow[targetCell]) return false;\n\n        int x = targetCell / W, y = targetCell % W;\n        for (int d = 0; d < 4; d++) {\n            int nx = x + dx4[d], ny = y + dy4[d];\n            if (!inb(nx, ny)) continue;\n            if (petAtNow[id(nx, ny)]) return false;\n        }\n        return true;\n    };\n\n    auto builderMoveOneStepToAdj = [&](int k, int bpos, int wcell, const vector<char>& plannedBlocked) -> char {\n        auto forbiddenWall = [&](int cell)->bool{\n            if (!wallSet[cell]) return false;\n            int wi = wallIndex[cell];\n            if (wi < 0) return false;\n            return !(segL[k] <= wi && wi < segR[k]);\n        };\n\n        vector<char> obs(V, 0);\n        for (int c = 0; c < V; c++) {\n            if (blockedActual[c] || plannedBlocked[c] || forbiddenWall(c)) obs[c] = 1;\n        }\n        if (obs[bpos]) return '.';\n\n        vector<int> candidates;\n        int wx = wcell / W, wy = wcell % W;\n        for (int d = 0; d < 4; d++) {\n            int nx = wx + dx4[d], ny = wy + dy4[d];\n            if (!inb(nx, ny)) continue;\n            int c = id(nx, ny);\n            if (obs[c]) continue;\n            if (c == wcell) continue; // don't step onto wcell while searching\n            candidates.push_back(c);\n        }\n        if (candidates.empty()) return '.';\n\n        vector<int> dist(V, -1), parent(V, -1);\n        queue<int> qq;\n        dist[bpos] = 0;\n        qq.push(bpos);\n\n        int bestCand = -1;\n        int bestDist = INT_MAX;\n\n        vector<char> isCand(V, 0);\n        for (int c : candidates) isCand[c] = 1;\n\n        while (!qq.empty()) {\n            int u = qq.front(); qq.pop();\n            if (dist[u] >= bestDist) continue;\n\n            if (isCand[u]) {\n                bestCand = u;\n                bestDist = dist[u];\n            }\n\n            int ux = u / W, uy = u % W;\n            for (int d = 0; d < 4; d++) {\n                int vx = ux + dx4[d], vy = uy + dy4[d];\n                if (!inb(vx, vy)) continue;\n                int v = id(vx, vy);\n                if (obs[v]) continue;\n                if (dist[v] != -1) continue;\n                dist[v] = dist[u] + 1;\n                parent[v] = u;\n                qq.push(v);\n            }\n        }\n\n        if (bestCand == -1) return '.';\n        if (bestCand == bpos) return '.';\n\n        int cur = bestCand;\n        while (parent[cur] != -1 && parent[cur] != bpos) cur = parent[cur];\n        if (parent[cur] == -1) return '.';\n        return moveChar(bpos, cur);\n    };\n\n    vector<int> targetPos(M, -1);\n\n    vector<char> petAt(V, 0), humanAt(V, 0);\n\n    auto updateTargets = [&](int /*turn*/) {\n        vector<int> petCnt(compCnt, 0);\n        for (int i = 0; i < N; i++) {\n            int p = petPos[i];\n            if (wallSet[p]) continue;\n            int c = compId[p];\n            if (c >= 0) petCnt[c]++;\n        }\n\n        const int PETCAP = 6;\n        vector<double> compScore(compCnt, 0.0);\n        for (int c = 0; c < compCnt; c++) {\n            int n = min(petCnt[c], PETCAP);\n            compScore[c] = (double)compSize[c] / 900.0 * pow(0.5, n);\n        }\n\n        vector<int> comps(compCnt);\n        iota(comps.begin(), comps.end(), 0);\n        sort(comps.begin(), comps.end(), [&](int a, int b){\n            if (compScore[a] != compScore[b]) return compScore[a] > compScore[b];\n            return compSize[a] > compSize[b];\n        });\n\n        int TOPCOMP = min(4, compCnt);\n        vector<int> chosenComps(comps.begin(), comps.begin() + TOPCOMP);\n\n        vector<int> nbHumans;\n        for (int i = 0; i < M; i++) if (!isBuilder[i]) nbHumans.push_back(i);\n\n        vector<char> used(V, 0);\n        const double alpha = 0.0015;\n        const double beta  = 0.00035;\n\n        for (int h : nbHumans) {\n            int cur = humanPos[h];\n            double bestVal = -1e100;\n            int bestCell = cur;\n\n            for (int c : chosenComps) {\n                for (int cell : topCells[c]) {\n                    if (wallSet[cell]) continue;\n                    int d = distMat[(size_t)cur * V + cell];\n                    if (d < 0) continue;\n                    if (used[cell]) continue;\n\n                    int depth = distInterior[cell];\n                    double noise = (double)(rng() % 1000) * 1e-10;\n                    double val = compScore[c]\n                               + alpha * (double)depth\n                               - beta  * (double)d\n                               + noise;\n\n                    if (val > bestVal) {\n                        bestVal = val;\n                        bestCell = cell;\n                    }\n                }\n            }\n\n            // fallback if we couldn't find a new distinct cell\n            if (used[bestCell]) {\n                for (int c : chosenComps) {\n                    for (int cell : topCells[c]) {\n                        if (wallSet[cell]) continue;\n                        int d = distMat[(size_t)cur * V + cell];\n                        if (d < 0) continue;\n\n                        int depth = distInterior[cell];\n                        double noise = (double)(rng() % 1000) * 1e-10;\n                        double val = compScore[c]\n                                   + alpha * (double)depth\n                                   - beta  * (double)d\n                                   + noise;\n\n                        if (val > bestVal) {\n                            bestVal = val;\n                            bestCell = cell;\n                        }\n                    }\n                }\n            }\n\n            targetPos[h] = bestCell;\n            used[bestCell] = 1;\n        }\n    };\n\n    // init positions arrays\n    for (int i = 0; i < N; i++) petAt[petPos[i]] = 1;\n    for (int i = 0; i < M; i++) humanAt[humanPos[i]] = 1;\n\n    updateTargets(0);\n\n    const int UPDATE_INTERVAL = 4;\n\n    for (int turn = 0; turn < 300; turn++) {\n        // rebuild at start of turn\n        fill(petAt.begin(), petAt.end(), 0);\n        for (int i = 0; i < N; i++) petAt[petPos[i]] = 1;\n\n        fill(humanAt.begin(), humanAt.end(), 0);\n        for (int i = 0; i < M; i++) humanAt[humanPos[i]] = 1;\n\n        if (turn % UPDATE_INTERVAL == 0) updateTargets(turn);\n\n        vector<char> plannedBlocked(V, 0);\n        fill(willBlockWallCell.begin(), willBlockWallCell.end(), -1);\n\n        vector<char> action(M, '.');\n\n        // builders\n        for (int k = 0; k < K; k++) {\n            int h = builderHuman[k];\n            int bpos = humanPos[h];\n\n            if (ptr[k] >= segR[k]) continue;\n\n            int widx = ptr[k];\n            int wcell = wall[widx];\n\n            if (isAdj(bpos, wcell)) {\n                if (canBlockNow(wcell, petAt, humanAt)) {\n                    action[h] = blockChar(bpos, wcell);\n                    willBlockWallCell[k] = wcell;\n                    plannedBlocked[wcell] = 1;\n                } else {\n                    action[h] = '.';\n                }\n            } else {\n                action[h] = builderMoveOneStepToAdj(k, bpos, wcell, plannedBlocked);\n            }\n        }\n\n        // non-builders: move greedily along shortest path in final-wall world\n        for (int i = 0; i < M; i++) {\n            if (isBuilder[i]) continue;\n            int cur = humanPos[i];\n            int tgt = targetPos[i];\n            if (tgt < 0 || cur == tgt) continue;\n            int d0 = distMat[(size_t)cur * V + tgt];\n            if (d0 < 0) continue;\n\n            vector<int> options;\n            int ux = cur / W, uy = cur % W;\n            for (int k = 0; k < 4; k++) {\n                int vx = ux + dx4[k], vy = uy + dy4[k];\n                if (!inb(vx, vy)) continue;\n                int v = id(vx, vy);\n                if (wallSet[v]) continue;\n                if (plannedBlocked[v]) continue;\n                int dv = distMat[(size_t)v * V + tgt];\n                if (dv == d0 - 1) options.push_back(v);\n            }\n            if (options.empty()) continue;\n\n            int bestv = options[0];\n            for (int v : options) {\n                if (distInterior[v] > distInterior[bestv]) bestv = v;\n            }\n            action[i] = moveChar(cur, bestv);\n        }\n\n        // output\n        string out(M, '.');\n        for (int i = 0; i < M; i++) out[i] = action[i];\n        cout << out << \"\\n\" << flush;\n\n        // apply actions\n        for (int i = 0; i < M; i++) {\n            char c = action[i];\n            if (c == '.') continue;\n\n            int x = humanPos[i] / W, y = humanPos[i] % W;\n            if (c == 'U') { x--; humanPos[i] = id(x,y); }\n            else if (c == 'D') { x++; humanPos[i] = id(x,y); }\n            else if (c == 'L') { y--; humanPos[i] = id(x,y); }\n            else if (c == 'R') { y++; humanPos[i] = id(x,y); }\n            else {\n                int bx = x, by = y;\n                if (c == 'u') bx--;\n                else if (c == 'd') bx++;\n                else if (c == 'l') by--;\n                else if (c == 'r') by++;\n                int bcell = id(bx, by);\n                if (0 <= bcell && bcell < V) blockedActual[bcell] = 1;\n            }\n        }\n\n        // update builders pointers\n        for (int k = 0; k < K; k++) {\n            int h = builderHuman[k];\n            if (willBlockWallCell[k] == -1) continue;\n            if (ptr[k] >= segR[k]) continue;\n\n            if (action[h] >= 'a' && action[h] <= 'z') {\n                if (willBlockWallCell[k] == wall[ptr[k]]) ptr[k]++;\n            }\n        }\n\n        // read pets movement\n        for (int i = 0; i < N; i++) {\n            string mv;\n            cin >> mv;\n            int p = petPos[i];\n            int x = p / W, y = p % W;\n            if (mv != \".\") {\n                for (char ch : mv) {\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                petPos[i] = id(x, y);\n            }\n        }\n    }\n\n    return 0;\n}","ahc009":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int H = 20;\nstatic constexpr int W = 20;\nstatic constexpr int N = H * W;\nstatic constexpr int L = 200;\n\nusing ld = long double;\nusing db = double;\n\nstruct Node {\n    array<db, N> dp; // probability mass on non-target cells\n    db score;        // exact accumulated expected reward up to current step\n    int parent;\n    char act;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int si, sj, ti, tj;\n    double p_in;\n    cin >> si >> sj >> ti >> tj >> p_in;\n\n    vector<string> hwall(H);\n    for (int i = 0; i < H; i++) cin >> hwall[i]; // 19 chars\n\n    vector<string> vwall(H - 1);\n    for (int i = 0; i < H - 1; i++) cin >> vwall[i]; // 20 chars\n\n    auto id = [&](int r, int c) { return r * W + c; };\n    int start = id(si, sj);\n    int target = id(ti, tj);\n\n    const db Pforget = (db)p_in;\n    const db Qmove = (db)(1.0 - p_in);\n\n    // Precompute transition with remembered-action attempt (ignoring forgetting)\n    static int moveTo[N][4]; // 0=U,1=D,2=L,3=R\n    for (int r = 0; r < H; r++) {\n        for (int c = 0; c < W; c++) {\n            int v = id(r, c);\n            // U\n            if (r == 0) moveTo[v][0] = v;\n            else moveTo[v][0] = (vwall[r - 1][c] == '1') ? v : id(r - 1, c);\n            // D\n            if (r == H - 1) moveTo[v][1] = v;\n            else moveTo[v][1] = (vwall[r][c] == '1') ? v : id(r + 1, c);\n            // L\n            if (c == 0) moveTo[v][2] = v;\n            else moveTo[v][2] = (hwall[r][c - 1] == '1') ? v : id(r, c - 1);\n            // R\n            if (c == W - 1) moveTo[v][3] = v;\n            else moveTo[v][3] = (hwall[r][c] == '1') ? v : id(r, c + 1);\n        }\n    }\n\n    // BFS distances in static graph\n    const int INF = 1e9;\n    vector<int> dist(N, INF);\n    queue<int> q;\n    dist[target] = 0;\n    q.push(target);\n\n    while (!q.empty()) {\n        int v = q.front(); q.pop();\n        int dv = dist[v];\n        for (int a = 0; a < 4; a++) {\n            int u = moveTo[v][a];\n            if (u == v) continue; // blocked edge / no progress\n            if (dist[u] > dv + 1) {\n                dist[u] = dv + 1;\n                q.push(u);\n            }\n        }\n    }\n\n    int distMaxFin = 0;\n    for (int v = 0; v < N; v++) if (dist[v] < INF) distMaxFin = max(distMaxFin, dist[v]);\n\n    // clamp dist for unreachable (shouldn't happen by statement)\n    vector<int> distClamped(N);\n    for (int v = 0; v < N; v++) {\n        if (dist[v] >= INF) distClamped[v] = distMaxFin + 10;\n        else distClamped[v] = dist[v];\n    }\n\n    // rewardAt[t]: reach target at turn t+1 => 401-(t+1)\n    vector<db> rewardAt(L);\n    for (int t = 0; t < L; t++) rewardAt[t] = (db)(401 - (t + 1));\n\n    static const char dirChar[4] = {'U','D','L','R'};\n\n    // Build heuristic table using negative-binomial-ish approximation\n    auto buildHeuristic = [&](db qHeur) -> vector<db> {\n        qHeur = max<db>(1e-6, min<db>(0.9999, qHeur));\n        ld qFail = (ld)1.0 - (ld)qHeur;\n\n        vector<db> Hh((L + 1) * N, 0.0);\n\n        for (int t = 0; t < L; t++) {\n            int rem = L - t;\n            vector<ld> E(rem + 1, 0.0);\n\n            for (int k = 1; k <= rem; k++) {\n                ld pj = pow((ld)qHeur, k); // P(J=k) with simplistic model\n                ld expected = 0.0;\n\n                for (int j = k; j <= rem; j++) {\n                    // completion reward at absolute turn (t+j)\n                    ld r = (ld)(401 - (t + j));\n                    if (r > 0) expected += r * pj;\n\n                    if (j == rem) break;\n                    ld ratio = (ld)j / (ld)(j - k + 1);\n                    pj = pj * ratio * qFail;\n                    if (pj < 1e-18L) break;\n                }\n                E[k] = expected;\n            }\n\n            for (int v = 0; v < N; v++) {\n                if (v == target) continue;\n                int k = dist[v];\n                if (k <= 0 || k >= INF || k > rem) Hh[(size_t)t * N + v] = 0.0;\n                else Hh[(size_t)t * N + v] = (db)E[k];\n            }\n        }\n        return Hh;\n    };\n\n    auto runBeam = [&](db qHeur, int beamW, uint64_t seed) -> pair<string, db> {\n        vector<db> Hh = buildHeuristic(qHeur);\n        auto Hptr = [&](int tNext) -> const db* {\n            return &Hh[(size_t)tNext * N];\n        };\n\n        vector<Node> pool;\n        pool.reserve((L + 1) * beamW + 16);\n\n        Node root;\n        root.dp.fill(0.0);\n        root.dp[start] = 1.0;\n        root.score = 0.0;\n        root.parent = -1;\n        root.act = '?';\n        pool.push_back(root);\n\n        vector<int> beamIdx;\n        beamIdx.reserve(beamW);\n        beamIdx.push_back(0);\n\n        mt19937_64 rng(seed);\n        normal_distribution<db> gauss(0.0, 1.0);\n        uniform_real_distribution<db> uni(0.0, 1.0);\n\n        // diversity bins\n        int numBins = 10;\n        db binWidth = max<db>(1.0, (db)distMaxFin / (db)numBins);\n        if (binWidth < 1.0) binWidth = 1.0;\n\n        vector<db> bestEst(beamW, -1e300);\n        vector<db> bestScore(beamW, 0.0);\n        vector<int> bestParent(beamW, -1);\n        vector<char> bestAct(beamW, '?');\n        vector<int> bestBucket(beamW, -1);\n        vector<array<db, N>> bestDp(beamW);\n\n        // workspace dpNext\n        array<db, N> dpNext;\n\n        auto bucketOfDist = [&](double d) -> int {\n            int b = (int)(d / binWidth);\n            if (b < 0) b = 0;\n            if (b >= numBins) b = numBins - 1;\n            return b;\n        };\n\n        for (int t = 0; t < L; t++) {\n            int tNext = t + 1;\n            const db* Hnext = Hptr(tNext);\n            db rwd = rewardAt[t];\n\n            int curSize = 0;\n\n            auto insertCandidate = [&](db est, db exactScore, int parent, char act,\n                                        const array<db, N>& dpCand, int candBucket) {\n                if (curSize < beamW) {\n                    bestEst[curSize] = est;\n                    bestScore[curSize] = exactScore;\n                    bestParent[curSize] = parent;\n                    bestAct[curSize] = act;\n                    bestBucket[curSize] = candBucket;\n                    bestDp[curSize] = dpCand;\n                    curSize++;\n                    return;\n                }\n\n                // locate worst overall\n                int worstAll = 0;\n                for (int i = 1; i < beamW; i++) if (bestEst[i] < bestEst[worstAll]) worstAll = i;\n\n                // locate worst inside same bucket\n                int worstB = -1;\n                db worstBVal = 1e300;\n                for (int i = 0; i < beamW; i++) {\n                    if (bestBucket[i] == candBucket && bestEst[i] < worstBVal) {\n                        worstBVal = bestEst[i];\n                        worstB = i;\n                    }\n                }\n\n                int repl = (worstB == -1 ? worstAll : worstB);\n\n                if (est > bestEst[repl]) {\n                    bestEst[repl] = est;\n                    bestScore[repl] = exactScore;\n                    bestParent[repl] = parent;\n                    bestAct[repl] = act;\n                    bestBucket[repl] = candBucket;\n                    bestDp[repl] = dpCand;\n                } else {\n                    // stochastic keep if close (prevents deterministic collapse)\n                    db diff = bestEst[repl] - est; // positive if worse\n                    db scale = 1.0 + fabsl(bestEst[repl]);\n                    if (diff < 0.01 * scale) {\n                        // ~10% chance to replace among near ties\n                        if (uni(rng) < 0.10) {\n                            bestEst[repl] = est;\n                            bestScore[repl] = exactScore;\n                            bestParent[repl] = parent;\n                            bestAct[repl] = act;\n                            bestBucket[repl] = candBucket;\n                            bestDp[repl] = dpCand;\n                        }\n                    }\n                }\n            };\n\n            vector<int> nextBeamIdx;\n            nextBeamIdx.reserve(beamW);\n\n            for (int idx : beamIdx) {\n                const Node& nd = pool[idx];\n\n                for (int a = 0; a < 4; a++) {\n                    dpNext.fill(0.0);\n\n                    db probReach = 0.0; // mass reaching target at this turn (remembered)\n                    db future = 0.0;    // sum dpNext[v]*Hnext[v] excluding target\n                    db sumProb = 0.0;\n                    db sumWD = 0.0;\n\n                    // modal tracking: state with highest dpNext probability mass\n                    db maxVal = -1.0;\n                    int modalDist = distMaxFin + 10;\n\n                    for (int v = 0; v < N; v++) {\n                        if (v == target) continue;\n                        db dv = nd.dp[v];\n                        if (dv == 0.0) continue;\n\n                        int w = moveTo[v][a];\n\n                        if (w == target) {\n                            probReach += dv * Qmove;\n                            db addStay = dv * Pforget;\n                            dpNext[v] += addStay;\n                            db addDist = addStay;\n\n                            future += addStay * Hnext[v];\n                            sumProb += addDist;\n                            sumWD += (db)addDist * (db)distClamped[v];\n\n                            if (dpNext[v] > maxVal) {\n                                maxVal = dpNext[v];\n                                modalDist = distClamped[v];\n                            }\n                        } else {\n                            db addMove = dv * Qmove;\n                            dpNext[w] += addMove;\n                            future += addMove * Hnext[w];\n                            sumProb += addMove;\n                            sumWD += (db)addMove * (db)distClamped[w];\n\n                            if (dpNext[w] > maxVal) {\n                                maxVal = dpNext[w];\n                                modalDist = distClamped[w];\n                            }\n\n                            db addStay = dv * Pforget;\n                            dpNext[v] += addStay;\n                            future += addStay * Hnext[v];\n                            sumProb += addStay;\n                            sumWD += (db)addStay * (db)distClamped[v];\n\n                            if (dpNext[v] > maxVal) {\n                                maxVal = dpNext[v];\n                                modalDist = distClamped[v];\n                            }\n                        }\n                    }\n\n                    db gain = probReach * rwd;\n                    db newScore = nd.score + gain;\n                    db est = newScore + future + (db)1e-7 * gauss(rng);\n\n                    // decide bucket: prefer modal if distribution is not too spread\n                    double meanDist = (sumProb > 1e-18 ? (double)(sumWD / sumProb) : (double)(distMaxFin + 10));\n                    double modalRatio = (sumProb > 1e-18 ? (double)(maxVal / sumProb) : 0.0);\n\n                    double useDist = (modalRatio >= 0.15 ? (double)modalDist : meanDist);\n                    int candBucket = bucketOfDist(useDist);\n\n                    insertCandidate(est, newScore, idx, dirChar[a], dpNext, candBucket);\n                }\n            }\n\n            // collect kept candidates and form next beam sorted by est\n            vector<int> order(curSize);\n            iota(order.begin(), order.end(), 0);\n            sort(order.begin(), order.end(), [&](int i, int j) { return bestEst[i] > bestEst[j]; });\n\n            nextBeamIdx.clear();\n            for (int i = 0; i < curSize; i++) {\n                int k = order[i];\n                Node nn;\n                nn.dp = bestDp[k];\n                nn.score = bestScore[k];\n                nn.parent = bestParent[k];\n                nn.act = bestAct[k];\n                pool.push_back(std::move(nn));\n                nextBeamIdx.push_back((int)pool.size() - 1);\n            }\n\n            beamIdx.swap(nextBeamIdx);\n        }\n\n        // choose best by exact score\n        int bestNode = beamIdx[0];\n        for (int idx : beamIdx) if (pool[idx].score > pool[bestNode].score) bestNode = idx;\n\n        // reconstruct string\n        string ans;\n        ans.reserve(L);\n        int cur = bestNode;\n        while (pool[cur].parent != -1) {\n            ans.push_back(pool[cur].act);\n            cur = pool[cur].parent;\n        }\n        reverse(ans.begin(), ans.end());\n        if ((int)ans.size() != L) {\n            if ((int)ans.size() > L) ans.resize(L);\n            else while ((int)ans.size() < L) ans.push_back('U');\n        }\n        return {ans, pool[bestNode].score};\n    };\n\n    // multiple heuristic variants\n    vector<db> mult = {0.70, 0.82, 0.95, 1.05, 1.18, 1.32};\n    int beamW = 58;\n\n    // base seed from input\n    uint64_t baseSeed = 0x9e3779b97f4a7c15ULL;\n    baseSeed ^= (uint64_t)si * 10007ULL + (uint64_t)sj * 1009ULL;\n    baseSeed ^= (uint64_t)ti * 10037ULL + (uint64_t)tj * 997ULL;\n    baseSeed ^= (uint64_t)llround(p_in * 100000.0);\n\n    string bestS;\n    db bestVal = -1e300;\n\n    for (int i = 0; i < (int)mult.size(); i++) {\n        db qHeur = Qmove * mult[i];\n        uint64_t seed = baseSeed ^ (uint64_t)(i + 1) * 0x1000003ULL ^ (uint64_t)(beamW * 10007);\n        auto [s, sc] = runBeam(qHeur, beamW, seed);\n        if (sc > bestVal) {\n            bestVal = sc;\n            bestS = std::move(s);\n        }\n    }\n\n    cout << bestS << \"\\n\";\n    return 0;\n}","ahc010":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 30;\nstatic constexpr int CELLS = N * N;          // 900\nstatic constexpr int DIRS = 4;\nstatic constexpr int STATES = CELLS * DIRS; // 3600\n\nstatic constexpr int di[4] = {0, -1, 0, 1};\nstatic constexpr int dj[4] = {-1, 0, 1, 0};\n\n// toBase[t][d] in statement: exit direction (0..3) or -1 if cannot enter from direction d\nstatic const int8_t toBase[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\n// toRot[t][r][d] = exitDir or -1, where r is CCW rotation count (0..3)\nstatic int8_t toRot[8][4][4];\n\nstatic int16_t neighCell[CELLS][4]; // neighCell[cell][exitDir]\nstatic uint8_t tileType[CELLS];\nstatic uint8_t rotCurr[CELLS];\nstatic uint8_t rotBest[CELLS];\n\nstatic int nextState[STATES];\nstatic uint8_t vis[STATES];\nstatic int posInPath[STATES];\nstatic int pathArr[STATES];\n\nstruct EvalResult {\n    long long score;\n    int best1;\n    int best2;\n    int numCycles;\n};\n\nstatic inline EvalResult evaluateCurrent() {\n    // Build functional graph transitions on states: (cell, entryDir)\n    for (int c = 0; c < CELLS; c++) {\n        int t = tileType[c];\n        int r = rotCurr[c];\n        int base = c * 4;\n        for (int d = 0; d < 4; d++) {\n            int8_t exitDir = toRot[t][r][d];\n            int v = base + d;\n            if (exitDir < 0) {\n                nextState[v] = -1;\n            } else {\n                int nb = neighCell[c][exitDir];\n                if (nb < 0) nextState[v] = -1;\n                else {\n                    int entryNext = (exitDir + 2) & 3; // direction opposite exitDir\n                    nextState[v] = nb * 4 + entryNext;\n                }\n            }\n        }\n    }\n\n    memset(vis, 0, sizeof(vis));\n\n    int best1 = 0, best2 = 0;\n    int numCycles = 0;\n    int cntBest1 = 0;\n\n    for (int v0 = 0; v0 < STATES; v0++) {\n        if (vis[v0] != 0) continue;\n\n        int cur = v0;\n        int pathLen = 0;\n\n        while (cur != -1 && vis[cur] == 0) {\n            vis[cur] = 1;\n            posInPath[cur] = pathLen;\n            pathArr[pathLen++] = cur;\n            cur = nextState[cur];\n        }\n\n        if (cur != -1 && vis[cur] == 1) {\n            int len = pathLen - posInPath[cur]; // cycle length in state graph\n            numCycles++;\n\n            if (len > best1) {\n                best2 = best1;\n                best1 = len;\n                cntBest1 = 1;\n            } else if (len == best1) {\n                cntBest1++;\n                if (cntBest1 >= 2) best2 = best1;\n            } else if (len > best2) {\n                best2 = len;\n            }\n        }\n\n        // mark path nodes done\n        for (int i = 0; i < pathLen; i++) vis[pathArr[i]] = 2;\n    }\n\n    long long score = (numCycles >= 2) ? 1LL * best1 * best2 : 0LL;\n    return {score, best1, best2, numCycles};\n}\n\n// Local compatibility: count how many neighbor entries would continue (under current rotations)\nstatic inline int localCompatibilityCell(int c, uint8_t r, const uint8_t rotArr[]) {\n    int t = tileType[c];\n    int sum = 0;\n    for (int entry = 0; entry < 4; entry++) {\n        int8_t exitDir = toRot[t][r][entry];\n        if (exitDir < 0) continue;\n        int nb = neighCell[c][exitDir];\n        if (nb < 0) continue;\n        int entryNext = (exitDir + 2) & 3;\n        int nbT = tileType[nb];\n        uint8_t nbR = rotArr[nb];\n        if (toRot[nbT][nbR][entryNext] >= 0) sum++;\n    }\n    return sum;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // Build toRot using geometric rotation mapping:\n    // If rotated CCW by r, original entry direction becomes (d + r) mod 4.\n    // exit also rotates by -r.\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 d_orig = (d + r) & 3;\n                int exit_orig = toBase[t][d_orig];\n                if (exit_orig < 0) toRot[t][r][d] = -1;\n                else toRot[t][r][d] = (exit_orig - r + 4) & 3;\n            }\n        }\n    }\n\n    // Read input\n    for (int i = 0; i < N; i++) {\n        string s; cin >> s;\n        for (int j = 0; j < N; j++) {\n            tileType[i * N + j] = (uint8_t)(s[j] - '0');\n        }\n    }\n\n    // Neighbors\n    for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) {\n        int c = i * N + j;\n        for (int dir = 0; dir < 4; dir++) {\n            int ni = i + di[dir], nj = j + dj[dir];\n            neighCell[c][dir] = (0 <= ni && ni < N && 0 <= nj && nj < N) ? (ni * N + nj) : -1;\n        }\n    }\n\n    mt19937_64 rng((uint64_t)chrono::steady_clock::now().time_since_epoch().count());\n    auto randInt = [&](int L, int R) -> int {\n        uniform_int_distribution<int> dist(L, R);\n        return dist(rng);\n    };\n    auto rand01 = [&]() -> double {\n        return uniform_real_distribution<double>(0.0, 1.0)(rng);\n    };\n\n    const double TIME_LIMIT = 1.98;\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    long long bestScore = -1;\n\n    // Multiple restarts\n    int restarts = 14;\n    for (int R = 0; R < restarts; R++) {\n        if (elapsed() > TIME_LIMIT) break;\n\n        // Init\n        if (R == 0) {\n            // all 0 then a short greedy local improvement\n            for (int c = 0; c < CELLS; c++) rotCurr[c] = 0;\n        } else {\n            for (int c = 0; c < CELLS; c++) rotCurr[c] = (uint8_t)randInt(0, 3);\n        }\n\n        // Short greedy tightening\n        {\n            vector<int> order(CELLS);\n            iota(order.begin(), order.end(), 0);\n            shuffle(order.begin(), order.end(), rng);\n            int sweeps = 1 + (R % 3 == 0 ? 1 : 0);\n            for (int s = 0; s < sweeps; s++) {\n                for (int idx : order) {\n                    uint8_t oldR = rotCurr[idx];\n                    int bestR = oldR;\n                    int bestS = localCompatibilityCell(idx, oldR, rotCurr);\n                    for (int rr = 0; rr < 4; rr++) {\n                        if (rr == oldR) continue;\n                        int sc = localCompatibilityCell(idx, (uint8_t)rr, rotCurr);\n                        if (sc > bestS) {\n                            bestS = sc;\n                            bestR = rr;\n                        }\n                    }\n                    // keep mostly greedy, slight diversity\n                    if ((uint8_t)bestR != oldR && rand01() < 0.95) rotCurr[idx] = (uint8_t)bestR;\n                }\n            }\n        }\n\n        EvalResult curRes = evaluateCurrent();\n        long long curScore = curRes.score;\n        if (curScore > bestScore) {\n            bestScore = curScore;\n            memcpy(rotBest, rotCurr, CELLS);\n        }\n\n        // SA parameters\n        double T_start = 6e6;\n        double T_end = 200.0;\n\n        // Run as many iterations as possible until time limit\n        while (elapsed() < TIME_LIMIT - 1e-3) {\n            double prog = elapsed() / TIME_LIMIT;\n            double T = T_end + (T_start - T_end) * (1.0 - prog);\n            if (T < 1.0) T = 1.0;\n\n            // Choose candidate cell: sample K random cells, pick one with highest local score\n            int K = 15;\n            int bestCell = -1;\n            int bestLocal = -1;\n            for (int t = 0; t < K; t++) {\n                int c = randInt(0, CELLS - 1);\n                int rcur = rotCurr[c];\n                int lsc = localCompatibilityCell(c, (uint8_t)rcur, rotCurr);\n                if (lsc > bestLocal) {\n                    bestLocal = lsc;\n                    bestCell = c;\n                }\n            }\n            int c = (rand01() < 0.10) ? randInt(0, CELLS - 1) : bestCell;\n\n            uint8_t oldR = rotCurr[c];\n\n            // Candidate rotations: those within 1 of max local score\n            int local[4];\n            int mx = -1;\n            for (int rr = 0; rr < 4; rr++) {\n                local[rr] = localCompatibilityCell(c, (uint8_t)rr, rotCurr);\n                mx = max(mx, local[rr]);\n            }\n\n            int cand[4];\n            int candCnt = 0;\n            for (int rr = 0; rr < 4; rr++) {\n                if (rr == oldR) continue;\n                if (local[rr] >= mx - 1) cand[candCnt++] = rr;\n            }\n            if (candCnt == 0) {\n                for (int rr = 0; rr < 4; rr++) if (rr != oldR) cand[candCnt++] = rr;\n            }\n\n            uint8_t newR;\n            // Weighted random early, greedy later\n            if (rand01() < (prog < 0.5 ? 0.75 : 0.35)) {\n                long long sumw = 0;\n                for (int i = 0; i < candCnt; i++) sumw += max(1, local[cand[i]] + 1);\n                long long x = (long long)(rng() % (unsigned long long)sumw);\n                long long acc = 0;\n                newR = cand[0];\n                for (int i = 0; i < candCnt; i++) {\n                    acc += max(1, local[cand[i]] + 1);\n                    if (x < acc) { newR = (uint8_t)cand[i]; break; }\n                }\n            } else {\n                int bestRR = cand[0];\n                for (int i = 1; i < candCnt; i++) if (local[cand[i]] > local[bestRR]) bestRR = cand[i];\n                newR = (uint8_t)bestRR;\n            }\n\n            if (newR == oldR) continue;\n\n            rotCurr[c] = newR;\n            EvalResult nres = evaluateCurrent();\n            long long newScore = nres.score;\n            long long delta = newScore - curScore;\n\n            bool accept = false;\n            if (delta >= 0) accept = true;\n            else {\n                double prob = exp((double)delta / T);\n                if (rand01() < prob) accept = true;\n            }\n\n            if (accept) {\n                curScore = newScore;\n                curRes = nres;\n                if (curScore > bestScore) {\n                    bestScore = curScore;\n                    memcpy(rotBest, rotCurr, CELLS);\n                }\n            } else {\n                rotCurr[c] = oldR;\n            }\n        }\n    }\n\n    // Output\n    string out;\n    out.reserve(CELLS);\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            out.push_back(char('0' + (int)rotBest[i * N + j]));\n        }\n    }\n    cout << out << \"\\n\";\n    return 0;\n}","ahc011":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct DSUFixed {\n    int M;\n    int parent[100], sz[100];\n    void init(int m) { M = m; reset(); }\n    void reset() {\n        for (int i = 0; i < M; i++) parent[i] = i, sz[i] = 1;\n    }\n    int find(int a) {\n        while (parent[a] != a) {\n            parent[a] = parent[parent[a]];\n            a = parent[a];\n        }\n        return a;\n    }\n    void unite(int a, int b) {\n        a = find(a); b = find(b);\n        if (a == b) return;\n        if (sz[a] < sz[b]) swap(a, b);\n        parent[b] = a;\n        sz[a] += sz[b];\n    }\n};\n\nstruct Evaluator {\n    int N, M;\n    DSUFixed dsu;\n    // indices for fixed adjacency pairs\n    vector<int> vertTop, vertBot;\n    vector<int> horL, horR;\n\n    // compatibility for masks 0..15\n    bool vertOk[16][16];\n    bool horOk[16][16];\n\n    int compVerts[100], compEdges[100];\n\n    Evaluator(int N_) : N(N_), M(N_ * N_) {\n        dsu.init(M);\n\n        for (int a = 0; a < 16; a++) for (int b = 0; b < 16; b++) {\n            // vertical: top needs DOWN(8), bottom needs UP(2)\n            vertOk[a][b] = ((a & 8) && (b & 2));\n            // horizontal: left needs RIGHT(4), right needs LEFT(1)\n            horOk[a][b] = ((a & 4) && (b & 1));\n        }\n\n        for (int i = 0; i < N - 1; i++) for (int j = 0; j < N; j++) {\n            int top = i * N + j;\n            int bot = (i + 1) * N + j;\n            vertTop.push_back(top);\n            vertBot.push_back(bot);\n        }\n        for (int i = 0; i < N; i++) for (int j = 0; j < N - 1; j++) {\n            int L = i * N + j;\n            int R = i * N + (j + 1);\n            horL.push_back(L);\n            horR.push_back(R);\n        }\n    }\n\n    struct Res {\n        int bestTree;     // exact largest tree component size\n        int bestFitness;  // smoother metric\n    };\n\n    Res eval(const vector<uint8_t>& b) {\n        dsu.reset();\n\n        // Build components via existing edges\n        for (size_t k = 0; k < vertTop.size(); k++) {\n            int top = vertTop[k], bot = vertBot[k];\n            uint8_t mt = b[top], mb = b[bot];\n            if (vertOk[mt][mb]) dsu.unite(top, bot);\n        }\n        for (size_t k = 0; k < horL.size(); k++) {\n            int L = horL[k], R = horR[k];\n            uint8_t mL = b[L], mR = b[R];\n            if (horOk[mL][mR]) dsu.unite(L, R);\n        }\n\n        for (int i = 0; i < M; i++) compVerts[i] = 0;\n        for (int v = 0; v < M; v++) {\n            if (b[v] == 0) continue;\n            compVerts[dsu.find(v)]++;\n        }\n        for (int i = 0; i < M; i++) compEdges[i] = 0;\n\n        // Count edges per component root\n        for (size_t k = 0; k < vertTop.size(); k++) {\n            int top = vertTop[k], bot = vertBot[k];\n            uint8_t mt = b[top], mb = b[bot];\n            if (vertOk[mt][mb]) compEdges[dsu.find(top)]++;\n        }\n        for (size_t k = 0; k < horL.size(); k++) {\n            int L = horL[k], R = horR[k];\n            uint8_t mL = b[L], mR = b[R];\n            if (horOk[mL][mR]) compEdges[dsu.find(L)]++;\n        }\n\n        int bestTree = 0;\n        int bestFitness = 0;\n        // fitness = v - extraCycles, where extra = edges - (v-1)\n        for (int r = 0; r < M; r++) {\n            int vcnt = compVerts[r];\n            if (vcnt == 0) continue;\n            int ecnt = compEdges[r];\n            int extra = ecnt - (vcnt - 1); // >= 0\n            if (extra == 0) bestTree = max(bestTree, vcnt);\n            int fitness = vcnt - extra;\n            if (fitness < 0) fitness = 0;\n            bestFitness = max(bestFitness, fitness);\n        }\n        return {bestTree, bestFitness};\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    long long T;\n    cin >> N >> T;\n\n    vector<string> s(N);\n    for (int i = 0; i < N; i++) cin >> s[i];\n\n    int M = N * N;\n    vector<uint8_t> b(M);\n    int emptyIdx = -1;\n\n    auto hexToVal = [&](char c) -> int {\n        if ('0' <= c && c <= '9') return c - '0';\n        return 10 + (c - 'a');\n    };\n\n    for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) {\n        int v = hexToVal(s[i][j]);\n        b[i * N + j] = (uint8_t)v;\n        if (v == 0) emptyIdx = i * N + j;\n    }\n\n    Evaluator evaluator(N);\n    const int FULLTREE = N * N - 1;\n\n    auto valForSelect = [&](const Evaluator::Res& r) -> int {\n        // normalized numeric value (avoid huge scaling so selection remains explorative)\n        // bestTree dominates, bestFitness refines.\n        return r.bestTree * 200 + r.bestFitness; // range ~ 0..~2e4\n    };\n\n    int dr[4] = {-1, 1, 0, 0};\n    int dc[4] = {0, 0, -1, 1};\n    char dirChar[4] = {'U', 'D', 'L', 'R'};\n    int opp[4] = {1, 0, 3, 2};\n\n    auto inBounds = [&](int r, int c) {\n        return 0 <= r && r < N && 0 <= c && c < N;\n    };\n\n    uint64_t seed = (uint64_t)chrono::steady_clock::now().time_since_epoch().count();\n    seed ^= 0x9e3779b97f4a7c15ULL * (uint64_t)N;\n    for (int i = 0; i < M; i++) seed = seed * 1315423911u + b[i] + 7;\n    seed ^= (uint64_t)emptyIdx * 1234567ULL;\n    mt19937_64 rng(seed);\n\n    auto start = chrono::steady_clock::now();\n    auto elapsedSec = [&]() -> double {\n        return chrono::duration<double>(chrono::steady_clock::now() - start).count();\n    };\n\n    int bestTreeGlobal = evaluator.eval(b).bestTree;\n    vector<char> bestMovesGlobal;\n    int bestKGlobal = (int)bestMovesGlobal.size();\n\n    const double LIMIT = 2.92;\n    const int maxRestarts = 26;\n    const int STAG = 600;\n\n    for (int restart = 0; restart < maxRestarts; restart++) {\n        if (elapsedSec() > LIMIT) break;\n\n        vector<uint8_t> curB = b;\n        int e = emptyIdx;\n        vector<char> moves;\n        moves.reserve((size_t)T);\n\n        auto curEval = evaluator.eval(curB);\n        int bestTreeRun = curEval.bestTree;\n        vector<char> bestMovesRun = moves;\n        int bestKRun = 0;\n        int stagnation = 0;\n        int prevDir = -1;\n\n        for (long long step = 0; step < T; step++) {\n            if (curEval.bestTree == FULLTREE) break;\n            if (elapsedSec() > LIMIT) break;\n            if (stagnation >= STAG) break;\n\n            int er = e / N, ec = e % N;\n\n            struct Cand {\n                int dir;\n                int nei;          // new empty index after move1\n                Evaluator::Res r1;\n                int lookVal;      // best val over move2\n            };\n\n            vector<Cand> cands;\n            cands.reserve(4);\n\n            for (int dir = 0; dir < 4; dir++) {\n                // mild anti-backtracking\n                if (prevDir != -1 && dir == opp[prevDir]) {\n                    // don't forbid; just reduce probability by skipping some\n                    if ((rng() % 10) < 7) continue;\n                }\n                int nr = er + dr[dir], nc = ec + dc[dir];\n                if (!inBounds(nr, nc)) continue;\n                int nei = nr * N + nc;\n\n                swap(curB[e], curB[nei]);\n                auto r1 = evaluator.eval(curB);\n                swap(curB[e], curB[nei]);\n\n                Cand c;\n                c.dir = dir;\n                c.nei = nei;\n                c.r1 = r1;\n                c.lookVal = valForSelect(r1); // at least move2=none\n                cands.push_back(c);\n            }\n            if (cands.empty()) break;\n\n            // 2-step lookahead: compute best val over all move2 for each move1 cand\n            for (auto& c : cands) {\n                // apply move1\n                swap(curB[e], curB[c.nei]);\n                int e1 = c.nei;\n                int r1p = e1 / N, c1p = e1 % N;\n\n                int bestLookVal = valForSelect(c.r1);\n\n                for (int dir2 = 0; dir2 < 4; dir2++) {\n                    int nr = r1p + dr[dir2], nc = c1p + dc[dir2];\n                    if (!inBounds(nr, nc)) continue;\n                    int e2 = nr * N + nc;\n\n                    swap(curB[e1], curB[e2]);\n                    auto r2 = evaluator.eval(curB);\n                    swap(curB[e1], curB[e2]);\n\n                    bestLookVal = max(bestLookVal, valForSelect(r2));\n                }\n                // undo move1\n                swap(curB[e], curB[c.nei]);\n\n                c.lookVal = bestLookVal;\n            }\n\n            int curBestTree = curEval.bestTree;\n\n            // If there is any improving 1-step bestTree, pick among them using 2-step lookVal.\n            int bestTree1 = curBestTree;\n            for (auto &c : cands) bestTree1 = max(bestTree1, c.r1.bestTree);\n\n            int chosenIdx = 0;\n            if (bestTree1 > curBestTree) {\n                // among candidates with max r1.bestTree pick max lookVal\n                int bestLook = -1;\n                for (int i = 0; i < (int)cands.size(); i++) {\n                    if (cands[i].r1.bestTree == bestTree1) {\n                        if (cands[i].lookVal > bestLook) {\n                            bestLook = cands[i].lookVal;\n                            chosenIdx = i;\n                        }\n                    }\n                }\n            } else {\n                // epsilon-greedy on lookVal to avoid too-greedy softmax\n                // eps decreases as step advances\n                double eps = 0.30 * (1.0 - (double)step / (double)T) + 0.08;\n                if (eps < 0.05) eps = 0.05;\n\n                // rank by lookVal\n                vector<int> ord(cands.size());\n                iota(ord.begin(), ord.end(), 0);\n                sort(ord.begin(), ord.end(), [&](int i, int j){\n                    if (cands[i].lookVal != cands[j].lookVal) return cands[i].lookVal > cands[j].lookVal;\n                    return cands[i].r1.bestTree > cands[j].r1.bestTree;\n                });\n\n                uniform_real_distribution<double> uni(0.0, 1.0);\n                double r01 = uni(rng);\n\n                if (r01 > eps) {\n                    chosenIdx = ord[0];\n                } else {\n                    int pickBand = min<int>(3, (int)cands.size());\n                    chosenIdx = ord[rng() % pickBand];\n                }\n            }\n\n            // execute chosen move1\n            auto ch = cands[chosenIdx];\n            swap(curB[e], curB[ch.nei]);\n            e = ch.nei;\n            moves.push_back(dirChar[ch.dir]);\n            prevDir = ch.dir;\n            curEval = ch.r1;\n\n            // update run best\n            if (curEval.bestTree > bestTreeRun) {\n                bestTreeRun = curEval.bestTree;\n                bestMovesRun = moves;\n                bestKRun = (int)moves.size();\n                stagnation = 0;\n            } else {\n                stagnation++;\n            }\n\n            // update global best (tie-break smaller K)\n            if (bestTreeRun > bestTreeGlobal) {\n                bestTreeGlobal = bestTreeRun;\n                bestMovesGlobal = bestMovesRun;\n                bestKGlobal = bestKRun;\n            } else if (bestTreeRun == bestTreeGlobal && bestKRun < bestKGlobal) {\n                bestMovesGlobal = bestMovesRun;\n                bestKGlobal = bestKRun;\n            }\n        }\n\n        if (bestTreeGlobal == FULLTREE) {\n            // can't do better on S; sometimes still improve K via more restarts, but stop for time.\n            break;\n        }\n    }\n\n    string out;\n    out.reserve(bestMovesGlobal.size());\n    for (char c : bestMovesGlobal) out.push_back(c);\n    cout << out << \"\\n\";\n    return 0;\n}","ahc012":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\nstatic const ll LIM = 1'000'000'000LL;\n\nstruct Point { ll x, y; };\n\nstruct RNG {\n    uint64_t s;\n    explicit RNG(uint64_t seed) : s(seed) {}\n    static uint64_t splitmix64(uint64_t &x) {\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    ll nextLL(ll l, ll r) {\n        return (ll)(splitmix64(s) % (uint64_t)(r - l + 1)) + l;\n    }\n    int nextInt(int l, int r) { return (int)nextLL(l, r); }\n    bool chance(int p_per_1000) { return nextInt(1, 1000) <= p_per_1000; }\n};\n\nstatic inline bool in_bound(ll v) { return -LIM <= v && v <= LIM; }\n\n// orient:\n// 0: proj1=x,   proj2=y\n// 1: proj1=x,   proj2=x+y\n// 2: proj1=x,   proj2=x-y\n// 3: proj1=x+y, proj2=x-y\nstatic inline ll proj_value(int orient, const Point& p, int which) {\n    if (orient == 0) {\n        return (which == 0 ? p.x : p.y);\n    } else if (orient == 1) {\n        return (which == 0 ? p.x : (p.x + p.y));\n    } else if (orient == 2) {\n        return (which == 0 ? p.x : (p.x - p.y));\n    } else { // orient==3\n        return (which == 0 ? (p.x + p.y) : (p.x - p.y));\n    }\n}\n\nstatic ll choose_cut_for_boundary(\n    ll low, ll high, ll prev,\n    const unordered_set<ll>& occ,\n    RNG& rng,\n    bool allowOnPointMode,\n    int window = 400\n) {\n    if (low > high) swap(low, high);\n\n    auto is_free = [&](ll c)->bool{\n        if (!in_bound(c)) return false;\n        if (allowOnPointMode) return true;\n        return occ.find(c) == occ.end();\n    };\n\n    auto pick_near = [&](ll center)->ll {\n        for (int d = 0; d <= window; d++) {\n            ll c1 = center + d;\n            if (c1 > prev && is_free(c1)) return c1;\n            if (d != 0) {\n                ll c2 = center - d;\n                if (c2 > prev && is_free(c2)) return c2;\n            }\n        }\n        // fallback: first free above prev\n        ll c = max(prev + 1, (ll)-LIM);\n        while (c <= LIM && !allowOnPointMode && occ.find(c) != occ.end()) c++;\n        if (c <= LIM) return c;\n        return prev + 1;\n    };\n\n    // If there exists an integer strictly between low and high, prefer inside.\n    if (high - low >= 2) {\n        ll mid = (low + high) / 2;\n        // ensure strict inside\n        for (int d = 0; d <= window; d++) {\n            for (ll c : {mid + (ll)d, mid - (ll)d}) {\n                if (c <= prev) continue;\n                if (!(low < c && c < high)) continue;\n                if (is_free(c)) return c;\n            }\n        }\n        // if all inside are occupied (rare), relax to nearest above prev\n        return pick_near(mid);\n    }\n\n    // duplicates: low==high\n    if (high == low) {\n        // If allowing cut-through, take exactly low if possible.\n        if (allowOnPointMode && low > prev && in_bound(low)) return low;\n        // else shift by +/-1\n        ll c1 = low - 1;\n        if (c1 > prev && is_free(c1)) return c1;\n        ll c2 = low + 1;\n        if (c2 > prev && is_free(c2)) return c2;\n        return prev + 1;\n    }\n\n    // high == low + 1 : no integer strictly between\n    if (high == low + 1) {\n        if (allowOnPointMode) {\n            // randomly choose between low or high\n            if (rng.chance(500)) {\n                if (low > prev && in_bound(low)) return low;\n                if (high > prev && in_bound(high)) return high;\n            } else {\n                if (high > prev && in_bound(high)) return high;\n                if (low > prev && in_bound(low)) return low;\n            }\n            return prev + 1;\n        } else {\n            // shift boundary: choose high+1 (puts \"high\" points on left) if possible, else low-1\n            ll c = high + 1;\n            if (c > prev && is_free(c)) return c;\n            c = low - 1;\n            if (c > prev && is_free(c)) return c;\n            return prev + 1;\n        }\n    }\n\n    return prev + 1;\n}\n\nstatic vector<ll> make_cuts_by_quantiles(\n    const vector<ll>& sortedProj,\n    const unordered_set<ll>& occ,\n    int numCuts,\n    RNG& rng,\n    bool allowOnPointMode,\n    int maxShift = 2\n) {\n    int N = (int)sortedProj.size();\n    vector<ll> cuts;\n    cuts.reserve(numCuts);\n    if (numCuts == 0) return cuts;\n\n    int cols = numCuts + 1;\n    ll prev = -LIM - 5;\n\n    for (int t = 1; t <= numCuts; t++) {\n        ll desiredLeft = (ll)t * N / cols;\n        int idx = (int)desiredLeft;     // boundary at idx, right starts at idx\n        if (idx < 1) idx = 1;\n        if (idx > N - 1) idx = N - 1;\n\n        int off = rng.nextInt(-maxShift, maxShift);\n        int idx2 = idx + off;\n        idx2 = max(1, min(N - 1, idx2));\n\n        ll low = sortedProj[idx2 - 1];\n        ll high = sortedProj[idx2];\n\n        bool allow = allowOnPointMode && rng.chance(150); // small chance\n        ll c = choose_cut_for_boundary(low, high, prev, occ, rng, allow, 450);\n\n        if (c <= prev) c = prev + 1;\n        if (!in_bound(c)) {\n            c = prev + 1;\n            if (!in_bound(c)) c = -LIM;\n        }\n        if (!allowOnPointMode) {\n            while (c <= LIM && occ.find(c) != occ.end()) c++;\n            if (c > LIM) c = prev + 1;\n        }\n        // enforce strict increasing\n        if (c <= prev) c = prev + 1;\n\n        cuts.push_back(c);\n        prev = c;\n    }\n\n    // final strictness\n    for (int i = 1; i < (int)cuts.size(); i++) {\n        if (cuts[i] <= cuts[i-1]) cuts[i] = cuts[i-1] + 1;\n    }\n    return cuts;\n}\n\nstatic int evaluate_candidate(\n    const vector<ll>& proj1,\n    const vector<ll>& proj2,\n    const vector<ll>& cuts1,\n    const vector<ll>& cuts2,\n    const array<int,11>& a\n) {\n    int V = (int)cuts1.size();\n    int H = (int)cuts2.size();\n    int cols = V + 1;\n    int rows = H + 1;\n    int cells = cols * rows;\n\n    vector<int> cnt(cells, 0);\n\n    for (int i = 0; i < (int)proj1.size(); i++) {\n        ll u = proj1[i];\n        ll v = proj2[i];\n\n        // exclude strawberries on any cut line\n        auto it1 = lower_bound(cuts1.begin(), cuts1.end(), u);\n        if (it1 != cuts1.end() && *it1 == u) continue;\n        int col = (int)(it1 - cuts1.begin());\n\n        auto it2 = lower_bound(cuts2.begin(), cuts2.end(), v);\n        if (it2 != cuts2.end() && *it2 == v) continue;\n        int row = (int)(it2 - cuts2.begin());\n\n        if (0 <= col && col < cols && 0 <= row && row < rows) {\n            cnt[col * rows + row]++;\n        }\n    }\n\n    array<int,11> b{};\n    b.fill(0);\n    for (int x : cnt) {\n        if (1 <= x && x <= 10) b[x]++;\n    }\n\n    int matched = 0;\n    for (int d = 1; d <= 10; d++) matched += min(a[d], b[d]);\n    return matched;\n}\n\n// output line for a cut constant c in different family\nstatic void output_line_vertical(ll x, ostream& out) {\n    out << x << \" \" << -LIM << \" \" << x << \" \" << LIM << \"\\n\";\n}\nstatic void output_line_horizontal(ll y, ostream& out) {\n    out << -LIM << \" \" << y << \" \" << LIM << \" \" << y << \"\\n\";\n}\nstatic void output_line_x_plus_y(ll c, ostream& out) {\n    // x + y = c\n    out << 0 << \" \" << c << \" \" << 1 << \" \" << (c - 1) << \"\\n\";\n}\nstatic void output_line_x_minus_y(ll c, ostream& out) {\n    // x - y = c\n    out << c << \" \" << 0 << \" \" << (c + 1) << \" \" << 1 << \"\\n\";\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, K;\n    cin >> N >> K;\n    array<int,11> a{};\n    int sumA = 0;\n    for (int d = 1; d <= 10; d++) {\n        cin >> a[d];\n        sumA += a[d];\n    }\n\n    vector<Point> pts(N);\n    for (int i = 0; i < N; i++) cin >> pts[i].x >> pts[i].y;\n\n    // Precompute for 4 orientations\n    const int ORI = 4;\n    vector<vector<ll>> proj1(ORI, vector<ll>(N));\n    vector<vector<ll>> proj2(ORI, vector<ll>(N));\n    vector<vector<ll>> sorted1(ORI), sorted2(ORI);\n    vector<unordered_set<ll>> occ1(ORI), occ2(ORI);\n\n    for (int o = 0; o < ORI; o++) {\n        occ1[o].reserve((size_t)N * 2);\n        occ2[o].reserve((size_t)N * 2);\n        sorted1[o].reserve(N);\n        sorted2[o].reserve(N);\n        for (int i = 0; i < N; i++) {\n            ll p1 = proj_value(o, pts[i], 0);\n            ll p2 = proj_value(o, pts[i], 1);\n            proj1[o][i] = p1;\n            proj2[o][i] = p2;\n            sorted1[o].push_back(p1);\n            sorted2[o].push_back(p2);\n            occ1[o].insert(p1);\n            occ2[o].insert(p2);\n        }\n        sort(sorted1[o].begin(), sorted1[o].end());\n        sort(sorted2[o].begin(), sorted2[o].end());\n    }\n\n    // Poisson proxy candidate ranking:\n    // expected b_d ~ cells * P(Poisson(lambda)=d), lambda=N/cells.\n    // Then proxy = sum min(a_d, expected).\n    vector<pair<int,int>> cand;\n    cand.reserve((K+1)*(K+2)/2);\n\n    for (int V = 0; V <= K; V++) {\n        for (int H = 0; H <= K - V; H++) {\n            int cells = (V + 1) * (H + 1);\n            if (cells <= 0) continue;\n\n            long double lambda = (long double)N / (long double)cells;\n            // Filter ranges where d=1..10 has non-negligible probability.\n            if (lambda < 0.25L) continue;\n            if (lambda > 12.0L) continue;\n\n            long double logP0 = -lambda; // ln(exp(-lambda))\n            // Compute probabilities iteratively to avoid underflow:\n            // P(d) = P(0) * lambda^d / d!\n            long double P = expl(logP0); // P(0)\n            long double proxy = 0;\n            for (int d = 1; d <= 10; d++) {\n                // P(d) = P(d-1) * lambda / d\n                P = P * lambda / (long double)d;\n                long double expected = (long double)cells * P;\n                proxy += min((long double)a[d], expected);\n            }\n\n            // also reward more cells mildly (helps avoid huge pieces)\n            proxy += 0.002L * (long double)cells;\n            cand.push_back({V, H});\n        }\n    }\n\n    auto pairProxy = [&](pair<int,int> pr)->long double{\n        int V = pr.first, H = pr.second;\n        int cells = (V + 1) * (H + 1);\n        long double lambda = (long double)N / (long double)cells;\n        long double logP0 = -lambda;\n        long double P = expl(logP0);\n        long double proxy = 0;\n        for (int d = 1; d <= 10; d++) {\n            P = P * lambda / (long double)d;\n            long double expected = (long double)cells * P;\n            proxy += min((long double)a[d], expected);\n        }\n        proxy += 0.002L * (long double)cells;\n        // small balance term\n        proxy -= 0.0005L * fabsl((long double)V - (long double)H);\n        return proxy;\n    };\n\n    sort(cand.begin(), cand.end(), [&](auto &p, auto &q){\n        long double vp = pairProxy(p);\n        long double vq = pairProxy(q);\n        if (vp != vq) return vp > vq;\n        if (p.first + p.second != q.first + q.second) return p.first + p.second > q.first + q.second;\n        return (p.first+1)*(p.second+1) > (q.first+1)*(q.second+1);\n    });\n\n    int TOP = min<int>(120, cand.size());\n    cand.resize(TOP);\n\n    uint64_t seed = (uint64_t)chrono::high_resolution_clock::now().time_since_epoch().count();\n    int bestScore = -1;\n    int bestOri = 0;\n    vector<ll> bestCuts1, bestCuts2;\n\n    // Global randomized search (no local search inside to keep runtime stable)\n    int RESTARTS = 4;\n    int variantsPerPair = 6;\n\n    for (int r = 0; r < RESTARTS; r++) {\n        RNG rng(seed + 1000003ULL * (uint64_t)r);\n\n        for (int o = 0; o < ORI; o++) {\n            for (auto [V, H] : cand) {\n                if (V + H > K) continue;\n                for (int it = 0; it < variantsPerPair; it++) {\n                    bool allowOnPointMode = (it >= 4) && rng.chance(800); // rare\n                    int maxShift = 1 + (it / 3);\n\n                    auto c1 = make_cuts_by_quantiles(sorted1[o], occ1[o], V, rng, allowOnPointMode, maxShift);\n                    auto c2 = make_cuts_by_quantiles(sorted2[o], occ2[o], H, rng, allowOnPointMode, maxShift);\n\n                    int sc = evaluate_candidate(proj1[o], proj2[o], c1, c2, a);\n                    if (sc > bestScore) {\n                        bestScore = sc;\n                        bestOri = o;\n                        bestCuts1 = std::move(c1);\n                        bestCuts2 = std::move(c2);\n                    }\n                }\n            }\n        }\n    }\n\n    // Local search on best solution\n    // Try small moves avoiding cut-through constants when possible.\n    {\n        RNG rng(seed + 9999991ULL);\n        int o = bestOri;\n\n        vector<ll> c1 = bestCuts1;\n        vector<ll> c2 = bestCuts2;\n        int cur = bestScore;\n\n        int iters = 1200;\n        for (int it = 0; it < iters; it++) {\n            bool pickFirst = rng.chance(500);\n            if (pickFirst && !c1.empty()) {\n                int idx = rng.nextInt(0, (int)c1.size() - 1);\n                ll lo = (idx == 0 ? -LIM : c1[idx-1] + 1);\n                ll hi = (idx + 1 == (int)c1.size() ? LIM : c1[idx+1] - 1);\n                if (lo > hi) continue;\n\n                ll delta = (ll)rng.nextInt(0,1) ? 1 : -1;\n                delta *= (ll)rng.nextInt(1,2);\n                ll nc = c1[idx] + delta;\n                if (nc < lo || nc > hi) continue;\n\n                // avoid cut constants hitting points (usually helps)\n                if (occ1[o].find(nc) != occ1[o].end() && rng.chance(700)) continue;\n\n                vector<ll> n1 = c1;\n                n1[idx] = nc;\n\n                int ns = evaluate_candidate(proj1[o], proj2[o], n1, c2, a);\n                if (ns > cur) {\n                    cur = ns;\n                    c1.swap(n1);\n                }\n            } else if (!pickFirst && !c2.empty()) {\n                int idx = rng.nextInt(0, (int)c2.size() - 1);\n                ll lo = (idx == 0 ? -LIM : c2[idx-1] + 1);\n                ll hi = (idx + 1 == (int)c2.size() ? LIM : c2[idx+1] - 1);\n                if (lo > hi) continue;\n\n                ll delta = (ll)rng.nextInt(0,1) ? 1 : -1;\n                delta *= (ll)rng.nextInt(1,2);\n                ll nc = c2[idx] + delta;\n                if (nc < lo || nc > hi) continue;\n\n                if (occ2[o].find(nc) != occ2[o].end() && rng.chance(700)) continue;\n\n                vector<ll> n2 = c2;\n                n2[idx] = nc;\n\n                int ns = evaluate_candidate(proj1[o], proj2[o], c1, n2, a);\n                if (ns > cur) {\n                    cur = ns;\n                    c2.swap(n2);\n                }\n            }\n        }\n\n        bestCuts1.swap(c1);\n        bestCuts2.swap(c2);\n        bestScore = cur;\n    }\n\n    int k = (int)bestCuts1.size() + (int)bestCuts2.size();\n    if (k > K) { // should not happen\n        k = 0;\n        bestCuts1.clear();\n        bestCuts2.clear();\n    }\n\n    cout << k << \"\\n\";\n\n    // Output lines from bestOri and cut constants\n    for (ll c : bestCuts1) {\n        if (bestOri == 3) {\n            // proj1 = x+y\n            output_line_x_plus_y(c, cout);\n        } else {\n            // proj1 = x\n            output_line_vertical(c, cout);\n        }\n    }\n    for (ll c : bestCuts2) {\n        if (bestOri == 0) {\n            // proj2 = y\n            output_line_horizontal(c, cout);\n        } else if (bestOri == 1) {\n            // proj2 = x+y\n            output_line_x_plus_y(c, cout);\n        } else { // bestOri 2 or 3\n            // proj2 = x-y\n            output_line_x_minus_y(c, cout);\n        }\n    }\n\n    return 0;\n}","ahc014":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing u8 = uint8_t;\nusing u16 = uint16_t;\nstatic inline int VID(int N, int x, int y) { return x * N + y; }\n\nstruct Edge {\n    // kind: 0=H, 1=V, 2=D1 (slope +1), 3=DM (slope -1)\n    u8 kind, a, b;\n};\n\nstruct Rect {\n    array<u16, 4> v{};\n    // For LAX/LDI <= 12:\n    // axis eLen = 2*dx + 2*dy <= 48\n    // diag eLen = 2*a + 2*b <= 48\n    static constexpr int MAXE = 48;\n    // mids <= 2*(dx-1)+2*(dy-1) <= 44, same for diag\n    static constexpr int MAXM = 44;\n\n    Edge edges[MAXE];\n    u8 eLen = 0;\n    u16 mids[MAXM];\n    u8 mLen = 0;\n};\n\nstruct Candidate {\n    long long key;\n    int rid;\n    bool operator<(Candidate const& o) const { return key < o.key; } // max-heap\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M;\n    cin >> N >> M;\n    vector<char> initDot(N * N, 0);\n    for (int i = 0; i < M; i++) {\n        int x, y;\n        cin >> x >> y;\n        initDot[VID(N, x, y)] = 1;\n    }\n\n    int c = (N - 1) / 2;\n    vector<long long> weight(N * N, 0);\n    long long baseSum = 0;\n    for (int x = 0; x < N; x++) for (int y = 0; y < N; y++) {\n        long long dx = x - c, dy = y - c;\n        long long w = dx * dx + dy * dy + 1;\n        weight[VID(N, x, y)] = w;\n        if (initDot[VID(N, x, y)]) baseSum += w;\n    }\n\n    // Expanded rectangle family\n    const int LAX = 12;\n    const int LDI = 12;\n\n    // ---------- Precompute rectangles ----------\n    vector<Rect> rects;\n    rects.reserve(1100000);\n\n    auto addAxisRect = [&](int x, int y, int dx, int dy) {\n        Rect r;\n        r.v = { (u16)VID(N, x, y),\n                (u16)VID(N, x + dx, y),\n                (u16)VID(N, x + dx, y + dy),\n                (u16)VID(N, x, y + dy) };\n        r.eLen = 0;\n        r.mLen = 0;\n\n        // bottom + top horizontal unit edges\n        for (int t = 0; t < dx; t++) r.edges[r.eLen++] = Edge{0, (u8)(x + t), (u8)y};\n        for (int t = 0; t < dx; t++) r.edges[r.eLen++] = Edge{0, (u8)(x + t), (u8)(y + dy)};\n\n        // left + right vertical unit edges\n        for (int t = 0; t < dy; t++) r.edges[r.eLen++] = Edge{1, (u8)x, (u8)(y + t)};\n        for (int t = 0; t < dy; t++) r.edges[r.eLen++] = Edge{1, (u8)(x + dx), (u8)(y + t)};\n\n        // midpoints excluding corners\n        for (int t = 1; t < dx; t++) {\n            r.mids[r.mLen++] = (u16)VID(N, x + t, y);\n            r.mids[r.mLen++] = (u16)VID(N, x + t, y + dy);\n        }\n        for (int t = 1; t < dy; t++) {\n            r.mids[r.mLen++] = (u16)VID(N, x, y + t);\n            r.mids[r.mLen++] = (u16)VID(N, x + dx, y + t);\n        }\n\n        rects.push_back(r);\n    };\n\n    for (int dx = 1; dx <= LAX; dx++) {\n        for (int dy = 1; dy <= LAX; dy++) {\n            for (int x = 0; x + dx < N; x++) {\n                for (int y = 0; y + dy < N; y++) {\n                    addAxisRect(x, y, dx, dy);\n                }\n            }\n        }\n    }\n\n    auto addDiagRect = [&](int x, int y, int a, int b) {\n        // A=(x,y)\n        // B=(x+a, y+a)\n        // C=(x+a+b, y+a-b)\n        // D=(x+b, y-b)\n        Rect r;\n        r.v = { (u16)VID(N, x, y),\n                (u16)VID(N, x + a, y + a),\n                (u16)VID(N, x + a + b, y + a - b),\n                (u16)VID(N, x + b, y - b) };\n        r.eLen = 0;\n        r.mLen = 0;\n\n        // A->B slope +1 => D1 edges\n        for (int t = 0; t < a; t++) r.edges[r.eLen++] = Edge{2, (u8)(x + t), (u8)(y + t)};\n\n        // B->C slope -1 => DM edges\n        // unit segment from (x+a+t, y+a-t) to (x+a+t+1, y+a-t-1)\n        // represent by lower endpoint y+a-t-1\n        for (int t = 0; t < b; t++) {\n            r.edges[r.eLen++] = Edge{3, (u8)(x + a + t), (u8)(y + a - t - 1)};\n        }\n\n        // C->D slope +1 (same kind as D->C in reverse, still D1)\n        for (int t = 0; t < a; t++) {\n            r.edges[r.eLen++] = Edge{2, (u8)(x + b + t), (u8)(y - b + t)};\n        }\n\n        // D->A slope -1 => DM edges\n        for (int t = 0; t < b; t++) {\n            r.edges[r.eLen++] = Edge{3, (u8)(x + t), (u8)(y - t - 1)};\n        }\n\n        // midpoints excluding corners\n        for (int t = 1; t < a; t++) r.mids[r.mLen++] = (u16)VID(N, x + t, y + t);\n        for (int t = 1; t < b; t++) r.mids[r.mLen++] = (u16)VID(N, x + a + t, y + a - t);\n        for (int t = 1; t < a; t++) r.mids[r.mLen++] = (u16)VID(N, x + b + t, y - b + t);\n        for (int t = 1; t < b; t++) r.mids[r.mLen++] = (u16)VID(N, x + t, y - t);\n\n        rects.push_back(r);\n    };\n\n    for (int a = 1; a <= LDI; a++) {\n        for (int b = 1; b <= LDI; b++) {\n            // x+a+b < N  and  y-b >= 0  and  y+a < N\n            for (int x = 0; x + a + b < N; x++) {\n                for (int y = b; y + a < N; y++) {\n                    addDiagRect(x, y, a, b);\n                }\n            }\n        }\n    }\n\n    int R = (int)rects.size();\n\n    // ---------- Build adjacencies ----------\n    vector<vector<int>> adjCorner(N * N), adjMid(N * N);\n    for (int rid = 0; rid < R; rid++) {\n        for (int k = 0; k < 4; k++) adjCorner[rects[rid].v[k]].push_back(rid);\n        for (int i = 0; i < rects[rid].mLen; i++) adjMid[rects[rid].mids[i]].push_back(rid);\n    }\n\n    // ---------- Edge indexing and edge->rect mapping ----------\n    int cntH = (N - 1) * N;\n    int cntV = N * (N - 1);\n    int cntD = (N - 1) * (N - 1);\n    int baseV = cntH;\n    int baseD1 = baseV + cntV;\n    int baseD2 = baseD1 + cntD;\n    int totalEdges = baseD2 + cntD;\n\n    auto edgeIndex = [&](const Edge& e) -> int {\n        // H: kind 0\n        if (e.kind == 0) { // (x,y)-(x+1,y), store (a=x, b=y)\n            return (int)e.a * N + (int)e.b;\n        } else if (e.kind == 1) { // V, store (a=x, b=y)\n            return baseV + (int)e.a * (N - 1) + (int)e.b;\n        } else if (e.kind == 2) { // D1 slope +1, store (a=x, b=y)\n            return baseD1 + (int)e.a * (N - 1) + (int)e.b;\n        } else { // kind 3 DM slope -1, store (a=x, b=lower_y)\n            return baseD2 + (int)e.a * (N - 1) + (int)e.b;\n        }\n    };\n\n    vector<vector<int>> edgeToRects(totalEdges);\n    for (int rid = 0; rid < R; rid++) {\n        const Rect& r = rects[rid];\n        for (int i = 0; i < r.eLen; i++) {\n            int ei = edgeIndex(r.edges[i]);\n            edgeToRects[ei].push_back(rid);\n        }\n    }\n\n    // ---------- Initial counts ----------\n    vector<int> initCnt(R, 0), initMidCnt(R, 0);\n    for (int rid = 0; rid < R; rid++) {\n        const Rect& r = rects[rid];\n        int s = 0;\n        for (int k = 0; k < 4; k++) s += initDot[r.v[k]];\n        initCnt[rid] = s;\n        int sm = 0;\n        for (int i = 0; i < r.mLen; i++) sm += initDot[r.mids[i]];\n        initMidCnt[rid] = sm;\n    }\n\n    auto runTrial = [&](long long lambdaPotential, uint64_t seed, bool recordOps)\n        -> pair<long long, vector<array<u16,4>>> {\n\n        vector<char> dot = initDot;\n        vector<int> cnt = initCnt;\n        vector<int> midCnt = initMidCnt;\n\n        vector<u8> usedRect(R, 0);\n        // conflictFlag[r] == 1 if any unit edge of r is already on perimeter of a used rectangle\n        vector<u8> conflictFlag(R, 0);\n\n        priority_queue<Candidate> pq;\n        vector<array<u16,4>> ops;\n        if (recordOps) ops.reserve(90000);\n\n        auto computeKeyAndPush = [&](int rid) {\n            if (usedRect[rid]) return;\n            if (cnt[rid] != 3) return;\n            if (midCnt[rid] != 0) return;\n            if (conflictFlag[rid]) return;\n\n            const Rect& r = rects[rid];\n            int u = -1;\n            int missIdx = -1;\n            for (int k = 0; k < 4; k++) {\n                int vv = (int)r.v[k];\n                if (!dot[vv]) { u = vv; missIdx = k; break; }\n            }\n            if (u < 0) return;\n\n            long long potential = 0;\n            // Potential: how many adjacent rectangles become cnt==3 after placing at u,\n            // approximated by (cnt==2, midCnt==0, conflictFlag==0) currently.\n            for (int rr : adjCorner[u]) {\n                if (usedRect[rr]) continue;\n                if (cnt[rr] != 2) continue;\n                if (midCnt[rr] != 0) continue;\n                if (conflictFlag[rr]) continue;\n                potential++;\n            }\n\n            uint64_t z = seed ^ (uint64_t)rid * 11995408973635179863ULL;\n            long long jitter = (long long)((z >> 32) & 3ULL); // 0..3\n\n            long long key = weight[u] + lambdaPotential * potential + jitter;\n            pq.push(Candidate{key, rid});\n        };\n\n        for (int rid = 0; rid < R; rid++) {\n            if (initCnt[rid] == 3 && initMidCnt[rid] == 0) computeKeyAndPush(rid);\n        }\n\n        long long sumW = baseSum;\n\n        auto applyRect = [&](int rid) {\n            usedRect[rid] = 1;\n            const Rect& r = rects[rid];\n            // mark conflict on all rectangles that share any unit edge with this rectangle\n            for (int i = 0; i < r.eLen; i++) {\n                int ei = edgeIndex(r.edges[i]);\n                for (int rr : edgeToRects[ei]) {\n                    if (usedRect[rr]) continue;\n                    conflictFlag[rr] = 1;\n                }\n            }\n        };\n\n        while (!pq.empty()) {\n            auto cur = pq.top(); pq.pop();\n            int rid = cur.rid;\n\n            if (usedRect[rid]) continue;\n            if (cnt[rid] != 3 || midCnt[rid] != 0) continue;\n            if (conflictFlag[rid]) continue;\n\n            const Rect& r = rects[rid];\n            int u = -1;\n            int missIdx = -1;\n            for (int k = 0; k < 4; k++) {\n                int vv = (int)r.v[k];\n                if (!dot[vv]) { u = vv; missIdx = k; break; }\n            }\n            if (u < 0) continue;\n\n            // execute\n            applyRect(rid);\n            dot[u] = 1;\n            sumW += weight[u];\n\n            if (recordOps) {\n                array<u16,4> op{};\n                for (int t = 0; t < 4; t++) op[t] = r.v[(missIdx + t) % 4]; // p1 is missing corner\n                ops.push_back(op);\n            }\n\n            // update cnt for rectangles where u is a corner\n            for (int rr : adjCorner[u]) {\n                if (usedRect[rr]) continue;\n                cnt[rr]++;\n                if (cnt[rr] == 3) computeKeyAndPush(rr);\n            }\n            // update midCnt for rectangles where u is on a midpoint (they become illegal afterwards)\n            for (int rr : adjMid[u]) {\n                if (usedRect[rr]) continue;\n                midCnt[rr]++;\n            }\n        }\n\n        return {sumW, std::move(ops)};\n    };\n\n    // ---------- Multi-trial search ----------\n    vector<long long> lambdas = {0, 2, 4, 6, 8, 10, 12, 14};\n    int trialsPerLambda = 4;\n\n    vector<uint64_t> seeds;\n    seeds.reserve((int)lambdas.size() * trialsPerLambda + 10);\n\n    uint64_t s0 = (uint64_t)N * 10000019ULL ^ (uint64_t)M * 9176ULL ^ 0x9e3779b97f4a7c15ULL;\n    for (int i = 0; i < (int)lambdas.size() * trialsPerLambda + 20; i++) {\n        uint64_t v = s0 + (uint64_t)i * 0x9e3779b97f4a7c15ULL;\n        v ^= v >> 27;\n        v *= 0x3c79ac492ba7b653ULL;\n        v ^= v >> 31;\n        seeds.push_back(v);\n    }\n\n    long long bestSum = -1;\n    long long bestLam = lambdas[0];\n    uint64_t bestSeed = seeds[0];\n\n    int idxSeed = 0;\n    for (long long lam : lambdas) {\n        for (int t = 0; t < trialsPerLambda; t++) {\n            uint64_t seed = seeds[idxSeed++];\n            auto [sumW, _ops] = runTrial(lam, seed, false);\n            if (sumW > bestSum) {\n                bestSum = sumW;\n                bestLam = lam;\n                bestSeed = seed;\n            }\n        }\n    }\n\n    // Record best\n    auto [finalSum, ops] = runTrial(bestLam, bestSeed, true);\n\n    cout << ops.size() << \"\\n\";\n    for (auto &op : ops) {\n        for (int t = 0; t < 4; t++) {\n            int vid = (int)op[t];\n            int x = vid / N;\n            int y = vid % N;\n            cout << x << \" \" << y << (t == 3 ? '\\n' : ' ');\n        }\n    }\n    return 0;\n}","ahc015":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct State {\n    // value 0..3, 0 means empty\n    array<uint8_t, 100> a{};\n};\n\nstatic inline int id(int r, int c) { return r * 10 + c; }\n\nstatic int neigh[100][4]; // neighbor indices, -1 if out of grid\n\nstatic State tilt(const State& s, int dir) {\n    // dir: 0=F(up), 1=B(down), 2=L(left), 3=R(right)\n    State t;\n    t.a.fill(0);\n\n    if (dir == 0) { // F: r -> 0\n        for (int c = 0; c < 10; c++) {\n            int k = 0;\n            for (int r = 0; r < 10; r++) {\n                uint8_t v = s.a[id(r, c)];\n                if (v) t.a[id(k++, c)] = v;\n            }\n        }\n    } else if (dir == 1) { // B: r -> 9\n        for (int c = 0; c < 10; c++) {\n            int k = 9;\n            for (int r = 9; r >= 0; r--) {\n                uint8_t v = s.a[id(r, c)];\n                if (v) t.a[id(k--, c)] = v;\n            }\n        }\n    } else if (dir == 2) { // L: c -> 0\n        for (int r = 0; r < 10; r++) {\n            int k = 0;\n            for (int c = 0; c < 10; c++) {\n                uint8_t v = s.a[id(r, c)];\n                if (v) t.a[id(r, k++)] = v;\n            }\n        }\n    } else { // R: c -> 9\n        for (int r = 0; r < 10; r++) {\n            int k = 9;\n            for (int c = 9; c >= 0; c--) {\n                uint8_t v = s.a[id(r, c)];\n                if (v) t.a[id(r, k--)] = v;\n            }\n        }\n    }\n    return t;\n}\n\n// BFS connected-component numerator: sum over components (size^2) for same-flavor components\nstatic int visStamp = 1;\nstatic int vis[100];\nstatic int qbuf[100];\n\nstatic long long calcNumerator(const State& s) {\n    if (++visStamp == INT_MAX) {\n        memset(vis, 0, sizeof(vis));\n        visStamp = 1;\n    }\n\n    long long sum = 0;\n    for (int st = 0; st < 100; st++) {\n        if (s.a[st] == 0 || vis[st] == visStamp) continue;\n        uint8_t flavor = s.a[st];\n\n        int head = 0, tail = 0;\n        qbuf[tail++] = st;\n        vis[st] = visStamp;\n\n        long long cnt = 0;\n        while (head < tail) {\n            int v = qbuf[head++];\n            cnt++;\n            for (int k = 0; k < 4; k++) {\n                int u = neigh[v][k];\n                if (u < 0) continue;\n                if (vis[u] == visStamp) continue;\n                if (s.a[u] != flavor) continue;\n                vis[u] = visStamp;\n                qbuf[tail++] = u;\n            }\n        }\n        sum += cnt * cnt;\n    }\n    return sum;\n}\n\nstatic vector<int> emptiesOf(const State& s) {\n    vector<int> e;\n    e.reserve(100);\n    for (int i = 0; i < 100; i++) if (s.a[i] == 0) e.push_back(i);\n    return e;\n}\n\nstatic int findCellByPT(const State& g, int p) {\n    int cnt = 0;\n    for (int i = 0; i < 100; i++) {\n        if (g.a[i] == 0) {\n            cnt++;\n            if (cnt == p) return i;\n        }\n    }\n    return -1;\n}\n\nstatic vector<int> F; // 1..100\n\n// ---------- Exact expectimax for late game ----------\nstatic long double solveExactValue(const State& s, int k) {\n    // if k==100: no more tilts after placing F[k]; final board is s\n    if (k == 100) return (long double)calcNumerator(s);\n\n    uint8_t nextFlavor = (uint8_t)F[k + 1];\n\n    long double best = -1e100L;\n    for (int dir = 0; dir < 4; dir++) {\n        State s1 = tilt(s, dir);\n        vector<int> e = emptiesOf(s1);\n        int E = (int)e.size();\n\n        long double sum = 0;\n        for (int cell : e) {\n            State s2 = s1;\n            s2.a[cell] = nextFlavor;\n            sum += solveExactValue(s2, k + 1);\n        }\n        long double val = sum / (long double)E;\n        best = max(best, val);\n    }\n    return best;\n}\n\nstatic int chooseDirExact(const State& s, int k) {\n    uint8_t nextFlavor = (uint8_t)F[k + 1];\n\n    int bestDir = 0;\n    long double bestVal = -1e100L;\n\n    for (int dir = 0; dir < 4; dir++) {\n        State s1 = tilt(s, dir);\n        vector<int> e = emptiesOf(s1);\n        int E = (int)e.size();\n\n        long double sum = 0;\n        for (int cell : e) {\n            State s2 = s1;\n            s2.a[cell] = nextFlavor;\n            sum += solveExactValue(s2, k + 1);\n        }\n        long double val = sum / (long double)E;\n\n        if (val > bestVal + 1e-12L) {\n            bestVal = val;\n            bestDir = dir;\n        } else if (fabsl(val - bestVal) <= 1e-12L) {\n            // tie-break by immediate numerator after first tilt\n            long long immNew = calcNumerator(s1);\n            long long immBest = calcNumerator(tilt(s, bestDir));\n            if (immNew > immBest) bestDir = dir;\n        }\n    }\n    return bestDir;\n}\n\n// ---------- Stochastic depth-2 lookahead (improved) ----------\nstatic vector<int> sampleK(vector<int> v, int K, mt19937_64& rng) {\n    if ((int)v.size() <= K) return v;\n    shuffle(v.begin(), v.end(), rng);\n    v.resize(K);\n    return v;\n}\n\n// Evaluate: after choosing dir0 at step t, board is s0.\n// We place candy F[t+1] randomly on empty cell, then choose dir1 to maximize expected value,\n// then place candy F[t+2] randomly, then choose dir2 greedily to maximize numerator.\nstatic long double estimateDepth2(const State& s0, int t, mt19937_64& rng) {\n    uint8_t f1 = (uint8_t)F[t + 1];\n    uint8_t f2 = (uint8_t)F[t + 2];\n\n    vector<int> e1 = emptiesOf(s0);\n    int E1 = (int)e1.size();\n    if (E1 == 0) return (long double)calcNumerator(s0);\n\n    int K1;\n    if (E1 <= 16) K1 = E1;\n    else if (E1 <= 40) K1 = 10;\n    else K1 = 6;\n    K1 = min(K1, E1);\n\n    vector<int> cells1 = sampleK(e1, K1, rng);\n\n    long double total = 0;\n    for (int c1 : cells1) {\n        State s1placed = s0;\n        s1placed.a[c1] = f1;\n\n        // Choose dir1 by maximizing expected value (over sampled c2), NOT by immediate greedy.\n        long double bestExpectedDir1 = -1e100L;\n\n        for (int dir1 = 0; dir1 < 4; dir1++) {\n            State t1 = tilt(s1placed, dir1);\n\n            vector<int> e2 = emptiesOf(t1);\n            int E2 = (int)e2.size();\n            if (E2 == 0) {\n                // no further placement; just evaluate after dir2 doesn't exist (but our model expects t has already applied).\n                long long num = calcNumerator(t1);\n                bestExpectedDir1 = max(bestExpectedDir1, (long double)num);\n                continue;\n            }\n\n            int K2;\n            if (E2 <= 16) K2 = E2;\n            else if (E2 <= 40) K2 = 3;\n            else K2 = 2;\n            K2 = min(K2, E2);\n\n            vector<int> cells2 = sampleK(e2, K2, rng);\n\n            long double sum2 = 0;\n            for (int c2 : cells2) {\n                State s2placed = t1;\n                s2placed.a[c2] = f2;\n\n                // choose dir2 greedily (max numerator after that tilt) as approximation\n                long long bestNum2 = -1;\n                for (int dir2 = 0; dir2 < 4; dir2++) {\n                    State t2 = tilt(s2placed, dir2);\n                    bestNum2 = max(bestNum2, calcNumerator(t2));\n                }\n                sum2 += (long double)bestNum2;\n            }\n            long double expectedDir1 = sum2 / (long double)cells2.size();\n            bestExpectedDir1 = max(bestExpectedDir1, expectedDir1);\n        }\n\n        total += bestExpectedDir1 / 1.0L;\n    }\n\n    return total / (long double)cells1.size();\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    for (int r = 0; r < 10; r++) for (int c = 0; c < 10; c++) {\n        int v = id(r, c);\n        neigh[v][0] = (r + 1 < 10) ? id(r + 1, c) : -1;\n        neigh[v][1] = (r - 1 >= 0) ? id(r - 1, c) : -1;\n        neigh[v][2] = (c + 1 < 10) ? id(r, c + 1) : -1;\n        neigh[v][3] = (c - 1 >= 0) ? id(r, c - 1) : -1;\n    }\n\n    F.assign(101, 0);\n    for (int i = 1; i <= 100; i++) cin >> F[i];\n\n    State g;\n    g.a.fill(0);\n\n    const char dirChar[4] = {'F', 'B', 'L', 'R'};\n\n    // RNG seed: depend on flavors for some determinism.\n    uint64_t seed = 0x9e3779b97f4a7c15ULL;\n    for (int i = 1; i <= 100; i++) seed = seed * 1315423911u + (uint64_t)F[i] + i;\n    mt19937_64 rng(seed);\n\n    for (int t = 1; t <= 100; t++) {\n        int p;\n        cin >> p;\n\n        int cell = findCellByPT(g, p);\n        g.a[cell] = (uint8_t)F[t];\n\n        if (t == 100) break;\n\n        int bestDir = 0;\n        if (t >= 95) {\n            bestDir = chooseDirExact(g, t);\n        } else {\n            long double bestVal = -1e100L;\n            for (int dir0 = 0; dir0 < 4; dir0++) {\n                State s0 = tilt(g, dir0);\n                long double val = estimateDepth2(s0, t, rng);\n                if (val > bestVal) {\n                    bestVal = val;\n                    bestDir = dir0;\n                }\n            }\n        }\n\n        g = tilt(g, bestDir);\n        cout << dirChar[bestDir] << \"\\n\" << flush;\n    }\n    return 0;\n}","ahc016":"#include <bits/stdc++.h>\nusing namespace std;\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}\nstatic inline int popcnt_u64(uint64_t x) { return __builtin_popcountll(x); }\n\nstatic inline int logBucket(int x, int cap) {\n    if (x <= 0) return 0;\n    int b = 31 - __builtin_clz((unsigned)x); // floor(log2(x))\n    return min(b, cap);\n}\n\nstatic inline int multisetL1_sorted(const vector<uint64_t>& a, const vector<uint64_t>& b) {\n    // L1 distance between count-multisets:\n    // |A|+|B| - 2*sum_x min(cntA(x), cntB(x))\n    int i = 0, j = 0;\n    int common = 0;\n    while (i < (int)a.size() && j < (int)b.size()) {\n        if (a[i] == b[j]) {\n            uint64_t x = a[i];\n            int i2 = i;\n            while (i2 < (int)a.size() && a[i2] == x) i2++;\n            int j2 = j;\n            while (j2 < (int)b.size() && b[j2] == x) j2++;\n            common += min(i2 - i, j2 - j);\n            i = i2; j = j2;\n        } else if (a[i] < b[j]) {\n            i++;\n        } else {\n            j++;\n        }\n    }\n    return (int)a.size() + (int)b.size() - 2 * common;\n}\n\nstruct Invariants {\n    int edges = 0;\n    long long twoStars = 0;   // sum_v C(deg(v),2)\n    long long triangles = 0; // exact\n};\n\nstruct Signature {\n    // Collision-free quantized integer keys (stored in uint64 for sorting convenience)\n    vector<uint64_t> vKeys;      // sorted\n    vector<uint64_t> eKeysNoCN; // sorted\n    vector<uint64_t> eKeysCN;   // sorted\n    Invariants inv;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int M;\n    double epsInput;\n    cin >> M >> epsInput;\n    double eps = epsInput;\n\n    // --- N schedule (smaller N for larger eps to reduce noise impact) ---\n    int N;\n    if (eps <= 0.10) N = 28;\n    else if (eps <= 0.18) N = 26;\n    else if (eps <= 0.26) N = 24;\n    else if (eps <= 0.34) N = 22;\n    else N = 20;\n    if (N > 63) N = 63; // using uint64 adjacency rows\n\n    const int T = N * (N - 1) / 2;\n\n    // Precompute maskGT[i] = bits strictly greater than i\n    vector<uint64_t> maskGT(N, 0);\n    for (int i = 0; i < N; i++) {\n        uint64_t le = (i + 1 >= 64) ? ~0ULL : ((1ULL << (i + 1)) - 1ULL); // includes i\n        maskGT[i] = (~0ULL) & ~le; // strictly > i\n    }\n\n    // Quantization caps (keep within 4-bit fields)\n    const int DEG_CAP = 15;  // deg bucket in [0..15]\n    const int SUM_CAP = 12;  // logBucket(neighDegSum) in [0..12] (<=15 ok)\n    const int CN_CAP  = 12;  // logBucket(cn) in [0..12]\n\n    auto degB = [&](int d) -> int { return min(d, DEG_CAP); };\n    auto sumB = [&](int s) -> int { return logBucket(s, SUM_CAP); };\n    auto cnB  = [&](int c) -> int { return logBucket(c, CN_CAP); };\n\n    // Key layouts:\n    // vKey: degB (4 bits) | sumB (4 bits) << 4\n    // eNoKey: d1B (4 bits) | d2B (4 bits) << 4\n    // eCNKey: eNoKey | cnB (4 bits) << 8\n    auto makeVKey = [&](int d, int neighSum) -> uint64_t {\n        int a = degB(d);\n        int b = sumB(neighSum);\n        return (uint64_t)a | (uint64_t)(b << 4);\n    };\n    auto makeEKeyNoCN = [&](int d1, int d2) -> uint64_t {\n        int a = degB(d1), b = degB(d2);\n        if (a > b) swap(a, b);\n        return (uint64_t)a | (uint64_t)(b << 4);\n    };\n    auto makeEKeyCN = [&](int d1, int d2, int cn) -> uint64_t {\n        uint64_t base = makeEKeyNoCN(d1, d2);\n        int c = cnB(cn);\n        return base | ((uint64_t)c << 8);\n    };\n\n    bool useCNWeight = (eps <= 0.22);\n\n    // Signature weights for full distance (used for codebook + final scoring)\n    // (kept integer for speed)\n    int wV = 2;\n    int wEno = 1;\n    int wECN = useCNWeight ? 1 : 0;\n\n    auto makeSig = [&](const vector<uint64_t>& adj) -> Signature {\n        vector<int> deg(N, 0);\n        for (int v = 0; v < N; v++) deg[v] = popcnt_u64(adj[v]);\n\n        long long edges2 = 0;\n        long long twoStars = 0;\n        for (int v = 0; v < N; v++) {\n            edges2 += deg[v];\n            twoStars += 1LL * deg[v] * (deg[v] - 1) / 2;\n        }\n        int edges = (int)(edges2 / 2);\n\n        // neighbor degree sum\n        vector<int> neighSum(N, 0);\n        for (int v = 0; v < N; v++) {\n            uint64_t row = adj[v];\n            long long s = 0;\n            while (row) {\n                int u = __builtin_ctzll(row);\n                row &= row - 1;\n                s += deg[u];\n            }\n            neighSum[v] = (int)s;\n        }\n\n        vector<uint64_t> vKeys;\n        vKeys.reserve(N);\n        for (int v = 0; v < N; v++) {\n            vKeys.push_back(makeVKey(deg[v], neighSum[v]));\n        }\n        sort(vKeys.begin(), vKeys.end());\n\n        vector<uint64_t> eNo, eCN;\n        eNo.reserve(edges);\n        eCN.reserve(edges);\n\n        long long sumCn = 0; // will equal 3*triangles\n        for (int i = 0; i < N; i++) {\n            uint64_t row = adj[i] & maskGT[i]; // j > i\n            while (row) {\n                int j = __builtin_ctzll(row);\n                row &= row - 1;\n\n                int d1 = deg[i], d2 = deg[j];\n                int cn = popcnt_u64(adj[i] & adj[j]);\n                sumCn += cn;\n\n                eNo.push_back(makeEKeyNoCN(d1, d2));\n                eCN.push_back(makeEKeyCN(d1, d2, cn));\n            }\n        }\n        sort(eNo.begin(), eNo.end());\n        sort(eCN.begin(), eCN.end());\n\n        long long triangles = sumCn / 3; // exact\n        Invariants inv{edges, twoStars, triangles};\n        return Signature{std::move(vKeys), std::move(eNo), std::move(eCN), inv};\n    };\n\n    auto distFull = [&](const Signature& A, const Signature& B) -> long long {\n        int dV = multisetL1_sorted(A.vKeys, B.vKeys);\n        int dNo = multisetL1_sorted(A.eKeysNoCN, B.eKeysNoCN);\n        int dCN = multisetL1_sorted(A.eKeysCN, B.eKeysCN);\n        return (long long)wV * dV + (long long)wEno * dNo + (long long)wECN * dCN;\n    };\n\n    auto distGlobal = [&](const Signature& A, const Signature& B) -> long long {\n        // for candidate filtering: use edges + wedges + triangles\n        long long de = llabs((long long)A.inv.edges - (long long)B.inv.edges);\n        long long dtw = llabs(A.inv.twoStars - B.inv.twoStars);\n        long long dtri = llabs(A.inv.triangles - B.inv.triangles);\n        // scale down the larger magnitude terms\n        return de * 6 + dtw / 20 + dtri / 40;\n    };\n\n    // --- pool generation ---\n    uint64_t seedBase = 0x6a09e667f3bcc909ULL\n                      ^ splitmix64((uint64_t)(M * 1000ULL))\n                      ^ splitmix64((uint64_t)llround(eps * 1000.0));\n\n    auto nextRand = [&](uint64_t &st) -> uint64_t {\n        st = splitmix64(st);\n        return st;\n    };\n\n    vector<double> ps = {0.20, 0.30, 0.40, 0.50, 0.60, 0.70};\n    int poolSize = min(2400, 22 * M + 200);\n\n    vector<vector<uint64_t>> poolAdj(poolSize, vector<uint64_t>(N, 0ULL));\n    vector<Signature> poolSig(poolSize);\n\n    for (int p = 0; p < poolSize; p++) {\n        uint64_t st = seedBase ^ splitmix64((uint64_t)p * 0x9e3779b97f4a7c15ULL);\n        int pi = (int)(nextRand(st) % ps.size());\n        double prob = ps[pi];\n        int thr = (int)llround(prob * 1024.0);\n\n        vector<uint64_t> adj(N, 0ULL);\n        for (int i = 0; i < N; i++) adj[i] = 0ULL;\n\n        for (int i = 0; i < N; i++) {\n            for (int j = i + 1; j < N; j++) {\n                uint64_t r = nextRand(st);\n                if ((r & 1023ULL) < (uint64_t)thr) {\n                    adj[i] |= (1ULL << j);\n                    adj[j] |= (1ULL << i);\n                }\n            }\n        }\n        poolAdj[p] = std::move(adj);\n        poolSig[p] = makeSig(poolAdj[p]);\n    }\n\n    // --- greedy farthest selection under full distance ---\n    vector<int> chosen;\n    chosen.reserve(M);\n    chosen.push_back(0);\n\n    vector<long long> minDist(poolSize, (1LL<<60));\n    for (int i = 0; i < poolSize; i++) minDist[i] = distFull(poolSig[i], poolSig[chosen[0]]);\n    minDist[chosen[0]] = -1;\n\n    while ((int)chosen.size() < M) {\n        int bestIdx = -1;\n        long long bestVal = -1;\n        for (int i = 0; i < poolSize; i++) {\n            if (minDist[i] > bestVal) {\n                bestVal = minDist[i];\n                bestIdx = i;\n            }\n        }\n        chosen.push_back(bestIdx);\n\n        for (int i = 0; i < poolSize; i++) {\n            if (minDist[i] < 0) continue;\n            long long d = distFull(poolSig[i], poolSig[bestIdx]);\n            if (d < minDist[i]) minDist[i] = d;\n        }\n        minDist[bestIdx] = -1;\n    }\n\n    vector<vector<uint64_t>> GAdj(M, vector<uint64_t>(N, 0ULL));\n    vector<Signature> Gsig(M);\n\n    for (int k = 0; k < M; k++) {\n        int idx = chosen[k];\n        GAdj[k] = poolAdj[idx];\n        Gsig[k] = poolSig[idx];\n    }\n\n    // Output graphs\n    cout << N << \"\\n\";\n    for (int k = 0; k < M; k++) {\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                s.push_back(((GAdj[k][i] >> j) & 1ULL) ? '1' : '0');\n            }\n        }\n        cout << s << \"\\n\";\n    }\n    cout.flush();\n\n    // --- decode with two-stage approach ---\n    const int TOPK = 18; // top candidates by global invariants\n\n    for (int qi = 0; qi < 100; qi++) {\n        string H;\n        cin >> H;\n\n        vector<uint64_t> adjH(N, 0ULL);\n        int idx = 0;\n        for (int i = 0; i < N; i++) {\n            for (int j = i + 1; j < N; j++) {\n                if (H[idx++] == '1') {\n                    adjH[i] |= (1ULL << j);\n                    adjH[j] |= (1ULL << i);\n                }\n            }\n        }\n\n        Signature qSig = makeSig(adjH);\n\n        // Stage 1: filter by global invariants\n        vector<pair<long long,int>> gList;\n        gList.reserve(M);\n        for (int k = 0; k < M; k++) {\n            gList.push_back({distGlobal(qSig, Gsig[k]), k});\n        }\n        nth_element(gList.begin(), gList.begin() + min(TOPK, M), gList.end(),\n                    [](auto &a, auto &b){ return a.first < b.first; });\n        int limit = min(TOPK, M);\n        if (limit < M) {\n            gList.resize(limit);\n        } else {\n            sort(gList.begin(), gList.end(), [](auto &a, auto &b){ return a.first < b.first; });\n        }\n\n        // Stage 2: full signature distance on filtered candidates\n        int best = gList[0].second;\n        long long bestScore = (1LL<<62);\n        for (auto &pr : gList) {\n            int k = pr.second;\n            long long sc = distFull(qSig, Gsig[k]);\n            // optional tiny tie-break by global\n            sc = sc * 2 + (pr.first / 50);\n            if (sc < bestScore) {\n                bestScore = sc;\n                best = k;\n            }\n        }\n\n        cout << best << \"\\n\";\n        cout.flush();\n    }\n\n    return 0;\n}","ahc017":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct AdjEdge {\n    int to;\n    int eid;\n    int nxt;\n};\n\nstatic const long long INFLL = (1LL << 60);\nstatic const long long UNREACH = 1000000000LL;\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<long long> W(M);\n    vector<vector<AdjEdge>> g(N); // will reserve below\n\n    for (int i = 0; i < M; i++) {\n        int u, v;\n        long long w;\n        cin >> u >> v >> w;\n        --u; --v;\n        W[i] = w;\n        g[u].push_back({v, i, -1});\n        g[v].push_back({u, i, -1});\n    }\n\n    // coords unused\n    for (int i = 0; i < N; i++) {\n        int x, y;\n        cin >> x >> y;\n    }\n\n    mt19937_64 rng(1234567);\n\n    // -----------------------------\n    // Lightweight importance for initialization:\n    // few-source shortest-path tree subtree sizes (as in previous refinement)\n    // -----------------------------\n    int Qimp = min(8, N);\n    vector<int> sourcesImp;\n    sourcesImp.reserve(Qimp);\n    vector<int> anchors = {0, N/2, N-1};\n    for (int a : anchors) if ((int)sourcesImp.size() < Qimp) sourcesImp.push_back(a);\n    while ((int)sourcesImp.size() < Qimp) {\n        int s = (int)(rng() % N);\n        bool ok = true;\n        for (int t : sourcesImp) if (t == s) ok = false;\n        if (ok) sourcesImp.push_back(s);\n    }\n\n    vector<long long> dist(N);\n    vector<int> parent(N), parentEdge(N);\n    vector<vector<int>> children(N);\n    vector<int> order(N), subtree(N);\n\n    // parent chosen from all shortest predecessors (single parent for tree)\n    auto dijkstra_original = [&](int src, vector<long long>& d) {\n        fill(d.begin(), d.end(), INFLL);\n        priority_queue<pair<long long,int>, vector<pair<long long,int>>, greater<pair<long long,int>>> pq;\n        d[src] = 0;\n        pq.push({0, src});\n        while (!pq.empty()) {\n            auto [cd, v] = pq.top(); pq.pop();\n            if (cd != d[v]) continue;\n            for (auto &e : g[v]) {\n                int to = e.to, id = e.eid;\n                long long nd = cd + W[id];\n                if (nd < d[to]) {\n                    d[to] = nd;\n                    pq.push({nd, to});\n                }\n            }\n        }\n    };\n\n    vector<long long> edgeCount(M, 0);\n\n    for (int s : sourcesImp) {\n        dijkstra_original(s, dist);\n\n        for (int i = 0; i < N; i++) {\n            parent[i] = -1;\n            parentEdge[i] = -1;\n            children[i].clear();\n        }\n\n        parent[s] = s;\n        parentEdge[s] = -1;\n\n        for (int v = 0; v < N; v++) {\n            if (v == s) continue;\n            long long dv = dist[v];\n            long long bestDu = INFLL;\n            int bestE = -1, bestP = -1;\n\n            // scan predecessors by checking all neighbors u with dist[u]+w(u,v)=dist[v]\n            for (auto &e : g[v]) {\n                int u = e.to;\n                int eid = e.eid;\n                if (dist[u] == INFLL) continue;\n                if (dist[u] + W[eid] == dv) {\n                    if (dist[u] < bestDu || (dist[u] == bestDu && eid < bestE)) {\n                        bestDu = dist[u];\n                        bestE = eid;\n                        bestP = u;\n                    }\n                }\n            }\n            parent[v] = bestP;\n            parentEdge[v] = bestE;\n        }\n\n        iota(order.begin(), order.end(), 0);\n        sort(order.begin(), order.end(), [&](int a, int b){ return dist[a] > dist[b]; });\n\n        for (int v = 0; v < N; v++) if (v != s) children[parent[v]].push_back(v);\n\n        for (int v = 0; v < N; v++) subtree[v] = 1;\n        for (int v : order) {\n            int sum = 1;\n            for (int c : children[v]) sum += subtree[c];\n            subtree[v] = sum;\n        }\n\n        for (int v = 0; v < N; v++) {\n            if (v == s) continue;\n            int e = parentEdge[v];\n            if (e >= 0) edgeCount[e] += subtree[v];\n        }\n    }\n\n    vector<long double> impRaw(M);\n    long double mxRaw = 0;\n    for (int e = 0; e < M; e++) {\n        impRaw[e] = (long double)edgeCount[e] * (long double)W[e];\n        mxRaw = max(mxRaw, impRaw[e]);\n    }\n    if (mxRaw <= 0) mxRaw = 1;\n\n    vector<double> imp(M);\n    long double scale = mxRaw;\n    for (int e = 0; e < M; e++) {\n        // concave log transform\n        long double x = impRaw[e] / scale * 100.0L + 1.0L;\n        imp[e] = (double)log1pl(x);\n    }\n    double mxImp = 0;\n    for (double x : imp) mxImp = max(mxImp, x);\n    if (mxImp <= 0) mxImp = 1;\n    for (int e = 0; e < M; e++) imp[e] /= mxImp;\n\n    // -----------------------------\n    // Initial schedule: greedy balance by imp\n    // -----------------------------\n    vector<int> edgeOrder(M);\n    iota(edgeOrder.begin(), edgeOrder.end(), 0);\n    sort(edgeOrder.begin(), edgeOrder.end(), [&](int a, int b){\n        if (imp[a] != imp[b]) return imp[a] > imp[b];\n        return W[a] > W[b];\n    });\n\n    vector<int> dayOfEdge(M, -1), posInDay(M, -1);\n    vector<vector<int>> edgesByDay(D);\n    vector<vector<unsigned char>> removed(D, vector<unsigned char>(M, 0));\n    vector<int> cntDay(D, 0);\n    vector<long double> sumImpDay(D, 0.0L);\n\n    struct PQNode { long double s; int c; int d; int ver; };\n    struct PQCmp {\n        bool operator()(const PQNode& a, const PQNode& b) const {\n            if (a.s != b.s) return a.s > b.s;\n            if (a.c != b.c) return a.c > b.c;\n            return a.d > b.d;\n        }\n    };\n\n    priority_queue<PQNode, vector<PQNode>, PQCmp> pq;\n    vector<int> ver(D, 0);\n    for (int d = 0; d < D; d++) pq.push({0.0L, 0, d, ver[d]});\n\n    for (int e : edgeOrder) {\n        while (true) {\n            auto cur = pq.top(); pq.pop();\n            int d = cur.d;\n            if (cur.ver != ver[d]) continue;\n            if ((int)edgesByDay[d].size() >= K) continue;\n\n            dayOfEdge[e] = d;\n            posInDay[e] = (int)edgesByDay[d].size();\n            edgesByDay[d].push_back(e);\n            removed[d][e] = 1;\n            cntDay[d]++;\n            sumImpDay[d] += (long double)imp[e];\n\n            ver[d]++;\n            pq.push({sumImpDay[d], cntDay[d], d, ver[d]});\n            break;\n        }\n    }\n\n    // -----------------------------\n    // Dijkstra proxy local search\n    // -----------------------------\n    int Qfast = min(14, N);\n    vector<int> sourcesFast;\n    sourcesFast.reserve(Qfast);\n    {\n        unordered_set<int> used;\n        while ((int)sourcesFast.size() < Qfast) {\n            int s = (int)(rng() % N);\n            if (used.insert(s).second) sourcesFast.push_back(s);\n        }\n    }\n\n    auto dijkstra_original_src = [&](int src, vector<long long>& d) {\n        fill(d.begin(), d.end(), INFLL);\n        priority_queue<pair<long long,int>, vector<pair<long long,int>>, greater<pair<long long,int>>> pq;\n        d[src] = 0;\n        pq.push({0, src});\n        while (!pq.empty()) {\n            auto [cd, v] = pq.top(); pq.pop();\n            if (cd != d[v]) continue;\n            for (auto &e : g[v]) {\n                int to = e.to, id = e.eid;\n                long long nd = cd + W[id];\n                if (nd < d[to]) {\n                    d[to] = nd;\n                    pq.push({nd, to});\n                }\n            }\n        }\n    };\n\n    vector<vector<long long>> baseDist(Qfast, vector<long long>(N, INFLL));\n    for (int i = 0; i < Qfast; i++) dijkstra_original_src(sourcesFast[i], baseDist[i]);\n\n    auto dijkstra_day = [&](int day, int src, vector<long long>& d) {\n        fill(d.begin(), d.end(), INFLL);\n        priority_queue<pair<long long,int>, vector<pair<long long,int>>, greater<pair<long long,int>>> pq;\n        d[src] = 0;\n        pq.push({0, src});\n        while (!pq.empty()) {\n            auto [cd, v] = pq.top(); pq.pop();\n            if (cd != d[v]) continue;\n            for (auto &e : g[v]) {\n                int to = e.to, id = e.eid;\n                if (removed[day][id]) continue; // repaired on this day => removed\n                long long nd = cd + W[id];\n                if (nd < d[to]) {\n                    d[to] = nd;\n                    pq.push({nd, to});\n                }\n            }\n        }\n    };\n\n    vector<long long> distWork(N);\n    auto computeProxyDay = [&](int day) -> long double {\n        long double sum = 0.0L;\n        for (int si = 0; si < Qfast; si++) {\n            int s = sourcesFast[si];\n            dijkstra_day(day, s, distWork);\n            for (int v = 0; v < N; v++) {\n                if (v == s) continue;\n                long long dk = (distWork[v] == INFLL ? UNREACH : distWork[v]);\n                long long d0 = baseDist[si][v];\n                // dk >= d0 in this monotone edge removal scenario, so nonnegative\n                sum += (long double)(dk - d0);\n            }\n        }\n        return sum;\n    };\n\n    vector<long double> proxyDay(D, 0.0L);\n    long double totalProxy = 0.0L;\n    for (int day = 0; day < D; day++) {\n        proxyDay[day] = computeProxyDay(day);\n        totalProxy += proxyDay[day];\n    }\n\n    auto swapEdges = [&](int eA, int eB) {\n        if (eA == eB) return;\n        int d1 = dayOfEdge[eA], d2 = dayOfEdge[eB];\n        if (d1 == d2) return;\n\n        int p1 = posInDay[eA];\n        int p2 = posInDay[eB];\n\n        // swap edge IDs inside day vectors\n        edgesByDay[d1][p1] = eB;\n        edgesByDay[d2][p2] = eA;\n\n        posInDay[eB] = p1;\n        posInDay[eA] = p2;\n\n        dayOfEdge[eA] = d2;\n        dayOfEdge[eB] = d1;\n\n        // update removed flags for each day\n        removed[d1][eA] = 0;\n        removed[d2][eB] = 0;\n        removed[d1][eB] = 1;\n        removed[d2][eA] = 1;\n    };\n\n    auto elapsedSec = [&](){\n        static auto start = chrono::steady_clock::now();\n        return chrono::duration<double>(chrono::steady_clock::now() - start).count();\n    };\n\n    double TIME_LIMIT = 5.85; // conservative\n    int iter = 0;\n\n    auto pickCandidatesHigh = [&](int d, int take) {\n        // sample some edges from day d, return the top-by-imp 'take' edges\n        auto &vec = edgesByDay[d];\n        int sz = (int)vec.size();\n        int samples = min(sz, 18);\n        vector<int> cand;\n        cand.reserve(samples);\n        for (int t = 0; t < samples; t++) {\n            int id = (int)(rng() % sz);\n            cand.push_back(vec[id]);\n        }\n        sort(cand.begin(), cand.end(), [&](int a, int b){ return imp[a] > imp[b]; });\n        cand.erase(unique(cand.begin(), cand.end()), cand.end());\n        if ((int)cand.size() > take) cand.resize(take);\n        while ((int)cand.size() < take && sz > 0) {\n            int id = (int)(rng() % sz);\n            cand.push_back(vec[id]);\n            sort(cand.begin(), cand.end(), [&](int a, int b){ return imp[a] > imp[b]; });\n            cand.erase(unique(cand.begin(), cand.end()), cand.end());\n            if ((int)cand.size() > take) cand.resize(take);\n        }\n        return cand;\n    };\n\n    auto pickCandidatesLow = [&](int d, int take) {\n        auto &vec = edgesByDay[d];\n        int sz = (int)vec.size();\n        int samples = min(sz, 18);\n        vector<int> cand;\n        cand.reserve(samples);\n        for (int t = 0; t < samples; t++) {\n            int id = (int)(rng() % sz);\n            cand.push_back(vec[id]);\n        }\n        sort(cand.begin(), cand.end(), [&](int a, int b){ return imp[a] < imp[b]; });\n        cand.erase(unique(cand.begin(), cand.end()), cand.end());\n        if ((int)cand.size() > take) cand.resize(take);\n        while ((int)cand.size() < take && sz > 0) {\n            int id = (int)(rng() % sz);\n            cand.push_back(vec[id]);\n            sort(cand.begin(), cand.end(), [&](int a, int b){ return imp[a] < imp[b]; });\n            cand.erase(unique(cand.begin(), cand.end()), cand.end());\n            if ((int)cand.size() > take) cand.resize(take);\n        }\n        return cand;\n    };\n\n    while (true) {\n        if (elapsedSec() > TIME_LIMIT) break;\n        iter++;\n\n        // sort days by proxy\n        vector<int> days(D);\n        iota(days.begin(), days.end(), 0);\n        sort(days.begin(), days.end(), [&](int a, int b){ return proxyDay[a] > proxyDay[b]; });\n\n        int topCount = min(3, D);\n        int botCount = min(3, D);\n        int dHigh = days[(int)(rng() % topCount)];                // among worst\n        int dLow = days[D-1 - (int)(rng() % botCount)];          // among best\n        if (dHigh == dLow) continue;\n\n        // candidate edges on those days\n        auto candHigh = pickCandidatesHigh(dHigh, 3); // largest imp\n        auto candLow  = pickCandidatesLow(dLow, 3);  // smallest imp\n\n        // generate candidate pairs, prioritize by predicted improvement in proxy (imp difference heuristic)\n        struct PairCand { int eA, eB; double score; };\n        vector<PairCand> pairs;\n        for (int eA : candHigh) for (int eB : candLow) {\n            if (eA == eB) continue;\n            if (dayOfEdge[eA] != dHigh || dayOfEdge[eB] != dLow) continue;\n            double sc = imp[eA] - imp[eB];\n            pairs.push_back({eA, eB, sc});\n        }\n        if (pairs.empty()) continue;\n        sort(pairs.begin(), pairs.end(), [&](const PairCand& a, const PairCand& b){\n            return a.score > b.score;\n        });\n\n        // evaluate a few best pairs exactly by proxy\n        long double bestNewTotal = totalProxy;\n        int bestEA = -1, bestEB = -1;\n        long double bestNewHigh = 0, bestNewLow = 0;\n\n        int evalLimit = min(6, (int)pairs.size());\n        for (int pi = 0; pi < evalLimit; pi++) {\n            int eA = pairs[pi].eA;\n            int eB = pairs[pi].eB;\n\n            swapEdges(eA, eB);\n\n            long double newHigh = computeProxyDay(dHigh); // day indices unchanged\n            long double newLow  = computeProxyDay(dLow);\n            long double newTotal = totalProxy - proxyDay[dHigh] - proxyDay[dLow] + newHigh + newLow;\n\n            swapEdges(eA, eB); // revert to original\n\n            if (newTotal < bestNewTotal) {\n                bestNewTotal = newTotal;\n                bestEA = eA; bestEB = eB;\n                bestNewHigh = newHigh;\n                bestNewLow = newLow;\n            }\n        }\n\n        // apply best improving swap\n        if (bestEA != -1) {\n            swapEdges(bestEA, bestEB);\n            proxyDay[dHigh] = bestNewHigh;\n            proxyDay[dLow] = bestNewLow;\n            totalProxy = bestNewTotal;\n        }\n    }\n\n    // Output schedule\n    for (int e = 0; e < M; e++) {\n        cout << (dayOfEdge[e] + 1) << (e + 1 == M ? '\\n' : ' ');\n    }\n    return 0;\n}","ahc019":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic inline int idx3(int D, int x, int y, int z) { // z fastest\n    return x * D * D + y * D + z;\n}\n\nstruct SplitMix64 {\n    uint64_t x;\n    explicit SplitMix64(uint64_t seed = 0) : x(seed) {}\n    uint64_t next_u64() {\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    template <class T>\n    void shuffle_vec(vector<T>& a) {\n        for (int i = (int)a.size() - 1; i > 0; --i) {\n            int j = (int)(next_u64() % (uint64_t)(i + 1));\n            swap(a[i], a[j]);\n        }\n    }\n};\n\nstruct HopcroftKarp {\n    int nL, nR;\n    vector<vector<int>> adj;\n    vector<int> dist, matchL, matchR;\n\n    HopcroftKarp(int nL_ = 0, int nR_ = 0) { init(nL_, nR_); }\n\n    void init(int nL_, int nR_) {\n        nL = nL_; nR = nR_;\n        adj.assign(nL, {});\n        dist.assign(nL, 0);\n        matchL.assign(nL, -1);\n        matchR.assign(nR, -1);\n    }\n\n    void add_edge(int u, int v) { adj[u].push_back(v); }\n\n    bool bfs() {\n        deque<int> q;\n        for (int i = 0; i < nL; i++) {\n            if (matchL[i] == -1) dist[i] = 0, q.push_back(i);\n            else dist[i] = -1;\n        }\n        bool reachFreeR = false;\n        while (!q.empty()) {\n            int v = q.front(); q.pop_front();\n            for (int to : adj[v]) {\n                int u = matchR[to];\n                if (u == -1) reachFreeR = true;\n                else if (dist[u] == -1) dist[u] = dist[v] + 1, q.push_back(u);\n            }\n        }\n        return reachFreeR;\n    }\n\n    bool dfs(int v) {\n        for (int to : adj[v]) {\n            int u = matchR[to];\n            if (u == -1 || (dist[u] == dist[v] + 1 && dfs(u))) {\n                matchL[v] = to;\n                matchR[to] = v;\n                return true;\n            }\n        }\n        dist[v] = -1;\n        return false;\n    }\n\n    int max_matching() {\n        int flow = 0;\n        while (bfs()) {\n            for (int i = 0; i < nL; i++) {\n                if (matchL[i] == -1 && dfs(i)) flow++;\n            }\n        }\n        return flow;\n    }\n};\n\nstatic vector<pair<int,int>> maxDominoPairs(\n    int D,\n    const vector<int>& parity,\n    const vector<array<int,6>>& neigh,\n    const vector<int>& remCubes\n) {\n    int N = D*D*D;\n    int m = (int)remCubes.size();\n    vector<int> posToLocal(N, -1);\n    for (int i = 0; i < m; i++) posToLocal[remCubes[i]] = i;\n\n    vector<int> leftIdx, rightIdx; // local indices into remCubes\n    leftIdx.reserve(m); rightIdx.reserve(m);\n    vector<int> localToRight(m, -1);\n\n    for (int i = 0; i < m; i++) {\n        int g = remCubes[i];\n        if (parity[g] == 0) leftIdx.push_back(i);\n        else {\n            localToRight[i] = (int)rightIdx.size();\n            rightIdx.push_back(i);\n        }\n    }\n\n    HopcroftKarp hk((int)leftIdx.size(), (int)rightIdx.size());\n\n    for (int li = 0; li < (int)leftIdx.size(); li++) {\n        int lLocal = leftIdx[li];\n        int g = remCubes[lLocal];\n        for (int dir = 0; dir < 6; dir++) {\n            int ng = neigh[g][dir];\n            if (ng < 0) continue;\n            int vLocal = posToLocal[ng];\n            if (vLocal < 0) continue;\n            int rv = localToRight[vLocal];\n            if (rv >= 0) hk.add_edge(li, rv);\n        }\n    }\n\n    hk.max_matching();\n\n    vector<pair<int,int>> pairs;\n    pairs.reserve((int)leftIdx.size());\n    for (int li = 0; li < (int)leftIdx.size(); li++) {\n        int rmatch = hk.matchL[li];\n        if (rmatch != -1) {\n            int lLocal = leftIdx[li];\n            int rLocal = rightIdx[rmatch];\n            pairs.push_back({remCubes[lLocal], remCubes[rLocal]});\n        }\n    }\n    return pairs;\n}\n\ntemplate<int K>\nstatic vector<int> greedyPackMaxK(\n    const vector<int>& candIdx,                   // indices into placements\n    const vector<array<int,K>>& placements,\n    vector<unsigned char>& used,                 // modified\n    SplitMix64& rng\n) {\n    vector<int> order = candIdx;\n    rng.shuffle_vec(order);\n    vector<int> chosen;\n    chosen.reserve(order.size());\n    for (int pi : order) {\n        const auto &pl = placements[pi];\n        bool ok = true;\n        for (int i = 0; i < K; i++) {\n            if (used[pl[i]]) { ok = false; break; }\n        }\n        if (!ok) continue;\n        for (int i = 0; i < K; i++) used[pl[i]] = 1;\n        chosen.push_back(pi);\n    }\n    return chosen;\n}\n\nstatic vector<int> randomSubsetK(const vector<int>& v, int k, SplitMix64& rng) {\n    if (k <= 0) return {};\n    if ((int)v.size() <= k) return v;\n    vector<int> tmp = v;\n    rng.shuffle_vec(tmp);\n    tmp.resize(k);\n    return tmp;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int D;\n    cin >> D;\n    int N = D*D*D;\n\n    vector<vector<string>> f(2, vector<string>(D)), r(2, vector<string>(D));\n    for (int i = 0; i < 2; i++) {\n        for (int z = 0; z < D; z++) cin >> f[i][z];\n        for (int z = 0; z < D; z++) cin >> r[i][z];\n    }\n\n    vector<vector<unsigned char>> exist(2, vector<unsigned char>(N, 0));\n    for (int obj = 0; obj < 2; obj++) {\n        for (int x = 0; x < D; x++) for (int y = 0; y < D; y++) for (int z = 0; z < D; z++) {\n            if (f[obj][z][x] == '1' && r[obj][z][y] == '1') exist[obj][idx3(D,x,y,z)] = 1;\n        }\n    }\n\n    // parity and neighbors for domino matching\n    vector<int> parity(N, 0);\n    vector<array<int,6>> neigh(N);\n    for (int x = 0; x < D; x++) for (int y = 0; y < D; y++) for (int z = 0; z < D; z++) {\n        int id = idx3(D,x,y,z);\n        parity[id] = (x+y+z) & 1;\n        array<int,6> nb; nb.fill(-1);\n        if (x+1 < D) nb[0] = idx3(D,x+1,y,z);\n        if (x-1 >=0) nb[1] = idx3(D,x-1,y,z);\n        if (y+1 < D) nb[2] = idx3(D,x,y+1,z);\n        if (y-1 >=0) nb[3] = idx3(D,x,y-1,z);\n        if (z+1 < D) nb[4] = idx3(D,x,y,z+1);\n        if (z-1 >=0) nb[5] = idx3(D,x,y,z-1);\n        neigh[id] = nb;\n    }\n\n    // Precompute placements for prisms\n    vector<array<int,8>> P8;\n    for (int x = 0; x+2 <= D; x++)\n        for (int y = 0; y+2 <= D; y++)\n            for (int z = 0; z+2 <= D; z++) {\n                array<int,8> a{};\n                int t = 0;\n                for (int dx=0;dx<2;dx++) for (int dy=0;dy<2;dy++) for (int dz=0;dz<2;dz++)\n                    a[t++] = idx3(D,x+dx,y+dy,z+dz);\n                P8.push_back(a);\n            }\n\n    vector<array<int,6>> P6;\n    // permutations of (3,2,1)\n    vector<array<int,3>> dims6 = {\n        {3,2,1},{3,1,2},{2,3,1},{2,1,3},{1,3,2},{1,2,3}\n    };\n    for (auto d : dims6) {\n        int dx=d[0], dy=d[1], dz=d[2];\n        for (int x = 0; x+dx <= D; x++)\n            for (int y = 0; y+dy <= D; y++)\n                for (int z = 0; z+dz <= D; z++) {\n                    array<int,6> a{};\n                    int t = 0;\n                    for (int i0=0;i0<dx;i0++) for (int j0=0;j0<dy;j0++) for (int k0=0;k0<dz;k0++)\n                        a[t++] = idx3(D,x+i0,y+j0,z+k0);\n                    P6.push_back(a);\n                }\n    }\n\n    vector<array<int,4>> P4;\n    // orientations of 2x2x1: (2,2,1),(2,1,2),(1,2,2)\n    vector<array<int,3>> dims4 = { {2,2,1},{2,1,2},{1,2,2} };\n    for (auto d : dims4) {\n        int dx=d[0], dy=d[1], dz=d[2];\n        for (int x = 0; x+dx <= D; x++)\n            for (int y = 0; y+dy <= D; y++)\n                for (int z = 0; z+dz <= D; z++) {\n                    array<int,4> a{};\n                    int t = 0;\n                    for (int i0=0;i0<dx;i0++) for (int j0=0;j0<dy;j0++) for (int k0=0;k0<dz;k0++)\n                        a[t++] = idx3(D,x+i0,y+j0,z+k0);\n                    P4.push_back(a);\n                }\n    }\n\n    vector<array<int,3>> P3;\n    // orientations of 1x1x3: (3,1,1),(1,3,1),(1,1,3)\n    vector<array<int,3>> dims3 = { {3,1,1},{1,3,1},{1,1,3} };\n    for (auto d : dims3) {\n        int dx=d[0], dy=d[1], dz=d[2];\n        for (int x = 0; x+dx <= D; x++)\n            for (int y = 0; y+dy <= D; y++)\n                for (int z = 0; z+dz <= D; z++) {\n                    array<int,3> a{};\n                    int t = 0;\n                    for (int i0=0;i0<dx;i0++) for (int j0=0;j0<dy;j0++) for (int k0=0;k0<dz;k0++)\n                        a[t++] = idx3(D,x+i0,y+j0,z+k0);\n                    P3.push_back(a);\n                }\n    }\n\n    // Candidate placement indices fully inside exist mask\n    vector<vector<int>> cand8(2), cand6(2), cand4(2), cand3(2);\n    for (int obj = 0; obj < 2; obj++) {\n        cand8[obj].reserve(P8.size());\n        for (int i = 0; i < (int)P8.size(); i++) {\n            bool ok = true;\n            for (int c : P8[i]) if (!exist[obj][c]) { ok = false; break; }\n            if (ok) cand8[obj].push_back(i);\n        }\n        cand6[obj].reserve(P6.size());\n        for (int i = 0; i < (int)P6.size(); i++) {\n            bool ok = true;\n            for (int c : P6[i]) if (!exist[obj][c]) { ok = false; break; }\n            if (ok) cand6[obj].push_back(i);\n        }\n        cand4[obj].reserve(P4.size());\n        for (int i = 0; i < (int)P4.size(); i++) {\n            bool ok = true;\n            for (int c : P4[i]) if (!exist[obj][c]) { ok = false; break; }\n            if (ok) cand4[obj].push_back(i);\n        }\n        cand3[obj].reserve(P3.size());\n        for (int i = 0; i < (int)P3.size(); i++) {\n            bool ok = true;\n            for (int c : P3[i]) if (!exist[obj][c]) { ok = false; break; }\n            if (ok) cand3[obj].push_back(i);\n        }\n    }\n\n    // Search best trial\n    const int T_outer = 9;\n\n    double bestEval = 1e100;\n    int bestKeep8=0,bestKeep6=0,bestKeep4=0,bestKeep3=0,bestKeepDom=0;\n    vector<int> bestS8[2], bestS6[2], bestS4[2], bestS3[2];\n    vector<pair<int,int>> bestDomPairs[2];\n\n    for (int trial = 0; trial < T_outer; trial++) {\n        SplitMix64 rng0(1234567ULL + (uint64_t)trial*10007ULL + 31ULL*(uint64_t)D);\n        SplitMix64 rng1(998244353ULL + (uint64_t)trial*9176ULL + 17ULL*(uint64_t)D);\n\n        // ---- 8 blocks ----\n        vector<int> full8[2];\n        for (int obj = 0; obj < 2; obj++) {\n            vector<unsigned char> used(N, 0);\n            SplitMix64 &rng = (obj==0 ? rng0 : rng1);\n            full8[obj] = greedyPackMaxK<8>(cand8[obj], P8, used, rng);\n        }\n        int keep8 = min((int)full8[0].size(), (int)full8[1].size());\n        vector<int> s8[2];\n        for (int obj=0; obj<2; obj++) {\n            SplitMix64 &rng = (obj==0 ? rng0 : rng1);\n            s8[obj] = randomSubsetK(full8[obj], keep8, rng);\n        }\n\n        vector<unsigned char> usedBase[2];\n        for (int obj=0; obj<2; obj++) {\n            usedBase[obj].assign(N, 0);\n            for (int pi : s8[obj]) for (int c : P8[pi]) usedBase[obj][c] = 1;\n        }\n\n        // ---- 6 blocks ----\n        vector<int> full6[2], s6[2];\n        for (int obj=0; obj<2; obj++) {\n            vector<unsigned char> usedTmp = usedBase[obj];\n            SplitMix64 &rng = (obj==0 ? rng0 : rng1);\n            full6[obj] = greedyPackMaxK<6>(cand6[obj], P6, usedTmp, rng);\n        }\n        int keep6 = min((int)full6[0].size(), (int)full6[1].size());\n        for (int obj=0; obj<2; obj++) {\n            SplitMix64 &rng = (obj==0 ? rng0 : rng1);\n            s6[obj] = randomSubsetK(full6[obj], keep6, rng);\n        }\n        for (int obj=0; obj<2; obj++) {\n            for (int pi : s6[obj]) for (int c : P6[pi]) usedBase[obj][c] = 1;\n        }\n\n        // ---- 4 blocks ----\n        vector<int> full4[2], s4[2];\n        for (int obj=0; obj<2; obj++) {\n            vector<unsigned char> usedTmp = usedBase[obj];\n            SplitMix64 &rng = (obj==0 ? rng0 : rng1);\n            full4[obj] = greedyPackMaxK<4>(cand4[obj], P4, usedTmp, rng);\n        }\n        int keep4 = min((int)full4[0].size(), (int)full4[1].size());\n        for (int obj=0; obj<2; obj++) {\n            SplitMix64 &rng = (obj==0 ? rng0 : rng1);\n            s4[obj] = randomSubsetK(full4[obj], keep4, rng);\n        }\n        for (int obj=0; obj<2; obj++) {\n            for (int pi : s4[obj]) for (int c : P4[pi]) usedBase[obj][c] = 1;\n        }\n\n        // ---- 3 blocks ----\n        vector<int> full3[2], s3[2];\n        for (int obj=0; obj<2; obj++) {\n            vector<unsigned char> usedTmp = usedBase[obj];\n            SplitMix64 &rng = (obj==0 ? rng0 : rng1);\n            full3[obj] = greedyPackMaxK<3>(cand3[obj], P3, usedTmp, rng);\n        }\n        int keep3 = min((int)full3[0].size(), (int)full3[1].size());\n        for (int obj=0; obj<2; obj++) {\n            SplitMix64 &rng = (obj==0 ? rng0 : rng1);\n            s3[obj] = randomSubsetK(full3[obj], keep3, rng);\n        }\n        for (int obj=0; obj<2; obj++) {\n            for (int pi : s3[obj]) for (int c : P3[pi]) usedBase[obj][c] = 1;\n        }\n\n        // ---- Remaining for dominos ----\n        vector<int> rem[2];\n        for (int obj=0; obj<2; obj++) {\n            rem[obj].clear();\n            for (int id=0; id<N; id++) {\n                if (exist[obj][id] && !usedBase[obj][id]) rem[obj].push_back(id);\n            }\n        }\n        auto pairs0 = maxDominoPairs(D, parity, neigh, rem[0]);\n        auto pairs1 = maxDominoPairs(D, parity, neigh, rem[1]);\n        int keepDom = min((int)pairs0.size(), (int)pairs1.size());\n\n        // Units counts (exact): every unoccupied rem cube becomes a unit,\n        // dominos cover 2*keepDom cubes.\n        int units0 = (int)rem[0].size() - 2*keepDom;\n        int units1 = (int)rem[1].size() - 2*keepDom;\n        int maxUnits = max(units0, units1);\n\n        double eval = (double)maxUnits\n            + (double)keepDom/2.0\n            + (double)keep3/3.0\n            + (double)keep4/4.0\n            + (double)keep6/6.0\n            + (double)keep8/8.0;\n\n        if (eval < bestEval) {\n            bestEval = eval;\n            bestKeep8 = keep8; bestKeep6 = keep6; bestKeep4 = keep4; bestKeep3 = keep3; bestKeepDom = keepDom;\n            for (int obj=0; obj<2; obj++) {\n                bestS8[obj] = s8[obj];\n                bestS6[obj] = s6[obj];\n                bestS4[obj] = s4[obj];\n                bestS3[obj] = s3[obj];\n            }\n            bestDomPairs[0].assign(pairs0.begin(), pairs0.begin()+keepDom);\n            bestDomPairs[1].assign(pairs1.begin(), pairs1.begin()+keepDom);\n        }\n    }\n\n    // ---- Build final answer ----\n    vector<int> b0(N, 0), b1(N, 0);\n    int id = 1;\n\n    auto markBlocks = [&](vector<int>& b, int startId, const vector<int>& sel, const auto& P) {\n        int cur = startId;\n        for (int pi : sel) {\n            for (int c : P[pi]) b[c] = cur;\n            cur++;\n        }\n        return cur;\n    };\n\n    // shared 2x2x2 (vol 8)\n    for (int k = 0; k < bestKeep8; k++) {\n        int pi0 = bestS8[0][k];\n        int pi1 = bestS8[1][k];\n        for (int c : P8[pi0]) b0[c] = id;\n        for (int c : P8[pi1]) b1[c] = id;\n        id++;\n    }\n\n    // shared 3x2x1 (vol 6)\n    for (int k = 0; k < bestKeep6; k++) {\n        int pi0 = bestS6[0][k];\n        int pi1 = bestS6[1][k];\n        for (int c : P6[pi0]) b0[c] = id;\n        for (int c : P6[pi1]) b1[c] = id;\n        id++;\n    }\n\n    // shared 2x2x1 (vol 4)\n    for (int k = 0; k < bestKeep4; k++) {\n        int pi0 = bestS4[0][k];\n        int pi1 = bestS4[1][k];\n        for (int c : P4[pi0]) b0[c] = id;\n        for (int c : P4[pi1]) b1[c] = id;\n        id++;\n    }\n\n    // shared 1x1x3 (vol 3)\n    for (int k = 0; k < bestKeep3; k++) {\n        int pi0 = bestS3[0][k];\n        int pi1 = bestS3[1][k];\n        for (int c : P3[pi0]) b0[c] = id;\n        for (int c : P3[pi1]) b1[c] = id;\n        id++;\n    }\n\n    int domStart = id;\n\n    // shared dominos (vol 2)\n    for (int t = 0; t < bestKeepDom; t++) {\n        int bid = domStart + t;\n        auto [a0, c0] = bestDomPairs[0][t];\n        auto [a1, c1] = bestDomPairs[1][t];\n        b0[a0] = bid; b0[c0] = bid;\n        b1[a1] = bid; b1[c1] = bid;\n    }\n\n    int unitBase = domStart + bestKeepDom;\n\n    // assign units to remaining exist-cubes (different counts ok)\n    vector<int> units0, units1;\n    for (int cid = 0; cid < N; cid++) {\n        if (exist[0][cid] && b0[cid] == 0) units0.push_back(cid);\n        if (exist[1][cid] && b1[cid] == 0) units1.push_back(cid);\n    }\n    int maxUnits = max((int)units0.size(), (int)units1.size());\n    for (int t = 0; t < (int)units0.size(); t++) b0[units0[t]] = unitBase + t;\n    for (int t = 0; t < (int)units1.size(); t++) b1[units1[t]] = unitBase + t;\n\n    int nBlocks = unitBase + maxUnits - 1;\n    if (nBlocks < 1) nBlocks = 1; // should not happen\n\n    cout << nBlocks << \"\\n\";\n    auto printB = [&](const vector<int>& b) {\n        bool first = true;\n        for (int x=0;x<D;x++) for (int y=0;y<D;y++) for (int z=0;z<D;z++) {\n            if (!first) cout << ' ';\n            first = false;\n            cout << b[idx3(D,x,y,z)];\n        }\n        cout << \"\\n\";\n    };\n    printB(b0);\n    printB(b1);\n    return 0;\n}","ahc020":"#include <bits/stdc++.h>\nusing namespace std;\nusing ll = long long;\n\nstatic int ceil_sqrt_ll(long long x) {\n    if (x <= 0) return 0;\n    long long r = (long long)sqrt((long double)x);\n    while (r * r < x) ++r;\n    while ((r - 1) * (r - 1) >= x) --r;\n    return (int)r;\n}\n\nstruct Fenwick {\n    int n = 0;\n    vector<int> bit;\n    int bitMask = 1;\n\n    void init(int n_) {\n        n = n_;\n        bit.assign(n + 1, 0);\n        bitMask = 1;\n        while (bitMask < n) bitMask <<= 1;\n    }\n    void add(int idx, int delta) { // idx in [1..n]\n        for (; idx <= n; idx += idx & -idx) bit[idx] += delta;\n    }\n    int kth(int k) const { // smallest idx s.t. prefix sum >= k, k>=1\n        int idx = 0;\n        for (int d = bitMask; d > 0; d >>= 1) {\n            int nxt = idx + d;\n            if (nxt <= n && bit[nxt] < k) {\n                idx = nxt;\n                k -= bit[nxt];\n            }\n        }\n        return idx + 1;\n    }\n    int getMax(int total) const { // radii are 0..LIM mapped to (r+1)\n        if (total == 0) return 0;\n        int pos = kth(total);\n        return pos - 1;\n    }\n};\n\nstruct SPT {\n    vector<int> parent;\n    vector<int> parentEdgeId;\n    vector<ll> weightToParent;\n    vector<vector<int>> children;\n    vector<vector<int>> anc;   // nodes on path v->root excluding root, including v\n    vector<int> depthCnt;      // |anc[v]|\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, K;\n    cin >> N >> M >> K;\n\n    vector<ll> x(N), y(N);\n    for (int i = 0; i < N; i++) cin >> x[i] >> y[i];\n\n    vector<int> U(M), V(M);\n    vector<ll> W(M);\n    vector<vector<tuple<int,ll,int>>> adj(N);\n    for (int j = 0; j < M; j++) {\n        cin >> U[j] >> V[j] >> W[j];\n        --U[j]; --V[j];\n        adj[U[j]].push_back({V[j], W[j], j});\n        adj[V[j]].push_back({U[j], W[j], j});\n    }\n\n    vector<ll> ax(K), ay(K);\n    for (int k = 0; k < K; k++) cin >> ax[k] >> ay[k];\n\n    const int LIM = 5000;\n    const ll LIM2 = 1LL * LIM * LIM;\n\n    vector<vector<uint16_t>> r(N, vector<uint16_t>(K, LIM + 1));\n    for (int i = 0; i < N; i++) {\n        for (int k = 0; k < K; k++) {\n            ll dx = x[i] - ax[k];\n            ll dy = y[i] - ay[k];\n            ll dist2 = dx*dx + dy*dy;\n            if (dist2 <= LIM2) {\n                int rr = ceil_sqrt_ll(dist2);\n                if (rr <= LIM) r[i][k] = (uint16_t)rr;\n            }\n        }\n    }\n\n    auto buildSPT = [&](uint64_t seed) -> SPT {\n        mt19937_64 rng(seed);\n\n        const ll INF = (1LL<<62);\n        vector<ll> dist(N, INF);\n        vector<int> parent(N, -1), parentEdgeId(N, -1);\n        vector<ll> bestEdgeW(N, INF);\n\n        dist[0] = 0;\n        bestEdgeW[0] = 0;\n        parent[0] = -1;\n\n        using PII = pair<ll,int>;\n        priority_queue<PII, vector<PII>, greater<PII>> pq;\n        pq.push({0, 0});\n\n        while (!pq.empty()) {\n            auto [d, u] = pq.top(); pq.pop();\n            if (d != dist[u]) continue;\n\n            for (auto [v, ww, id] : adj[u]) {\n                ll nd = d + ww;\n                if (nd < dist[v]) {\n                    dist[v] = nd;\n                    parent[v] = u;\n                    parentEdgeId[v] = id;\n                    bestEdgeW[v] = ww;\n                    pq.push({nd, v});\n                } else if (nd == dist[v]) {\n                    if (ww < bestEdgeW[v]) {\n                        parent[v] = u;\n                        parentEdgeId[v] = id;\n                        bestEdgeW[v] = ww;\n                    } else if (ww == bestEdgeW[v]) {\n                        // random tie break among equal cable weights\n                        if ((rng() & 1ULL) == 0) {\n                            parent[v] = u;\n                            parentEdgeId[v] = id;\n                        }\n                    }\n                }\n            }\n        }\n\n        vector<ll> weightToParent(N, 0);\n        for (int v = 1; v < N; v++) weightToParent[v] = W[parentEdgeId[v]];\n\n        vector<vector<int>> children(N);\n        for (int v = 1; v < N; v++) children[parent[v]].push_back(v);\n\n        vector<vector<int>> anc(N);\n        vector<int> depthCnt(N, 0);\n        for (int v = 1; v < N; v++) {\n            int cur = v;\n            while (cur != 0) {\n                anc[v].push_back(cur);\n                cur = parent[cur];\n            }\n            depthCnt[v] = (int)anc[v].size();\n        }\n\n        return SPT{std::move(parent), std::move(parentEdgeId), std::move(weightToParent),\n                   std::move(children), std::move(anc), std::move(depthCnt)};\n    };\n\n    auto buildCandidates = [&](const SPT& spt,\n                               int Lnear, int Lshallow,\n                               int ancestorSpan, int Lcap) {\n        vector<vector<int>> cand(K);\n        vector<pair<int,int>> tmp; // (need, station)\n\n        for (int k = 0; k < K; k++) {\n            tmp.clear();\n            tmp.reserve(N);\n            for (int i = 0; i < N; i++) {\n                int need = (int)r[i][k];\n                if (need <= LIM) tmp.push_back({need, i});\n            }\n            sort(tmp.begin(), tmp.end()); // by need\n\n            vector<char> used(N, 0);\n            vector<int> res;\n            res.reserve(Lcap);\n\n            auto addStation = [&](int s) {\n                if (!used[s] && (int)r[s][k] <= LIM) {\n                    used[s] = 1;\n                    res.push_back(s);\n                }\n            };\n\n            // near stations + their ancestors (encourage shared paths)\n            for (int t = 0; t < (int)tmp.size() && t < Lnear && (int)res.size() < Lcap; t++) {\n                int s = tmp[t].second;\n                int cur = s;\n                for (int step = 0; step <= ancestorSpan; step++) {\n                    addStation(cur);\n                    if (cur == 0) break;\n                    cur = spt.parent[cur];\n                    if (cur < 0) break;\n                    if ((int)res.size() >= Lcap) break;\n                }\n            }\n\n            // shallow by depth\n            if ((int)res.size() < Lcap) {\n                vector<pair<int,int>> tmp2;\n                tmp2.reserve(tmp.size());\n                for (auto &pr : tmp) tmp2.push_back({spt.depthCnt[pr.second], pr.second});\n                sort(tmp2.begin(), tmp2.end());\n                for (int t = 0; t < (int)tmp2.size() && t < Lshallow && (int)res.size() < Lcap; t++) {\n                    addStation(tmp2[t].second);\n                }\n            }\n\n            // fallback\n            if (res.empty()) addStation(tmp[0].second);\n\n            if ((int)res.size() > Lcap) res.resize(Lcap);\n            cand[k] = std::move(res);\n        }\n        return cand;\n    };\n\n    auto greedyInit = [&](const SPT& spt, const vector<vector<int>>& cand,\n                           uint64_t seed) -> vector<int> {\n        mt19937_64 rng(seed);\n        vector<int> assign(K, -1);\n\n        vector<int> sz(N, 0), curMax(N, 0), subtreeCnt(N, 0);\n\n        vector<int> order(K);\n        iota(order.begin(), order.end(), 0);\n        shuffle(order.begin(), order.end(), rng);\n\n        for (int k : order) {\n            ll bestDelta = (1LL<<62);\n            vector<int> bests;\n\n            for (int to : cand[k]) {\n                int need = (int)r[to][k];\n                int oldMax = curMax[to];\n                int newMax = max(oldMax, need);\n                ll deltaP = 1LL*newMax*newMax - 1LL*oldMax*oldMax;\n\n                ll deltaE = 0;\n                if (sz[to] == 0) {\n                    // activating station toggles edge on when subtreeCnt becomes 1\n                    for (int u : spt.anc[to]) {\n                        if (subtreeCnt[u] == 0) deltaE += spt.weightToParent[u];\n                    }\n                }\n\n                ll delta = deltaP + deltaE;\n                if (delta < bestDelta) {\n                    bestDelta = delta;\n                    bests.clear();\n                    bests.push_back(to);\n                } else if (delta == bestDelta) {\n                    bests.push_back(to);\n                }\n            }\n\n            int chosen = bests[(size_t)(rng() % (uint64_t)bests.size())];\n            assign[k] = chosen;\n\n            int need = (int)r[chosen][k];\n            bool wasInactive = (sz[chosen] == 0);\n\n            sz[chosen]++;\n            curMax[chosen] = max(curMax[chosen], need);\n\n            if (wasInactive) {\n                for (int u : spt.anc[chosen]) subtreeCnt[u]++;\n            }\n        }\n        return assign;\n    };\n\n    auto solveTrial = [&](const SPT& spt,\n                           const vector<vector<int>>& cand,\n                           const vector<int>& assignInit,\n                           uint64_t seed,\n                           int timeLimitMs,\n                           bool enableSA) -> pair<ll, vector<int>> {\n        mt19937_64 rng(seed);\n\n        auto tStart = chrono::steady_clock::now();\n        auto timeUp = [&]() {\n            return chrono::duration_cast<chrono::milliseconds>(chrono::steady_clock::now() - tStart).count() > timeLimitMs;\n        };\n\n        vector<int> assign = assignInit;\n\n        vector<Fenwick> fenw(N);\n        for (int i = 0; i < N; i++) fenw[i].init(LIM + 1);\n\n        vector<int> sz(N, 0), P(N, 0);\n        for (int k = 0; k < K; k++) {\n            int i = assign[k];\n            int need = (int)r[i][k];\n            fenw[i].add(need + 1, +1);\n            sz[i]++;\n        }\n\n        ll Pcost = 0;\n        for (int i = 0; i < N; i++) {\n            if (sz[i] > 0) P[i] = fenw[i].getMax(sz[i]);\n            else P[i] = 0;\n            Pcost += 1LL * P[i] * P[i];\n        }\n\n        // subtreeCnt = number of ACTIVE stations in subtree\n        vector<int> subtreeCnt(N, 0);\n        function<int(int)> dfs = [&](int v) -> int {\n            int cnt = (sz[v] > 0) ? 1 : 0;\n            for (int to : spt.children[v]) cnt += dfs(to);\n            subtreeCnt[v] = cnt;\n            return cnt;\n        };\n        dfs(0);\n\n        ll edgeCost = 0;\n        for (int v = 1; v < N; v++) if (subtreeCnt[v] > 0) edgeCost += spt.weightToParent[v];\n\n        ll totalCost = Pcost + edgeCost;\n        ll bestCost = totalCost;\n        vector<int> bestAssign = assign;\n\n        // deltaEdge helpers\n        vector<int> mark(N, 0), deltaVal(N, 0), touched;\n        touched.reserve(N);\n        int stamp = 1;\n\n        auto deltaEdge = [&](int from, int to, bool fromInactive, bool toActive) -> ll {\n            if (!fromInactive && !toActive) return 0LL;\n\n            if (fromInactive && !toActive) {\n                // removing last resident at from => subtreeCnt[u]-- along anc[from]\n                ll dE = 0;\n                for (int u : spt.anc[from]) {\n                    // edge (u,parent[u]) turns off if before was 1\n                    if (subtreeCnt[u] == 1) dE -= spt.weightToParent[u];\n                }\n                return dE;\n            }\n\n            if (!fromInactive && toActive) {\n                // adding first resident at to => subtreeCnt[u]++ along anc[to]\n                ll dE = 0;\n                for (int u : spt.anc[to]) {\n                    // edge turns on if before was 0\n                    if (subtreeCnt[u] == 0) dE += spt.weightToParent[u];\n                }\n                return dE;\n            }\n\n            // both toggles: net changes -1 along anc[from], +1 along anc[to]\n            stamp++;\n            touched.clear();\n\n            auto addDeltaPath = [&](int start, int d) {\n                for (int u : spt.anc[start]) {\n                    if (mark[u] != stamp) {\n                        mark[u] = stamp;\n                        deltaVal[u] = 0;\n                        touched.push_back(u);\n                    }\n                    deltaVal[u] += d;\n                }\n            };\n\n            addDeltaPath(from, -1);\n            addDeltaPath(to, +1);\n\n            ll dE = 0;\n            for (int u : touched) {\n                int before = subtreeCnt[u];\n                int after = before + deltaVal[u];\n                bool b1 = before > 0, b2 = after > 0;\n                if (b1 != b2) dE += (b2 ? +spt.weightToParent[u] : -spt.weightToParent[u]);\n            }\n            return dE;\n        };\n\n        auto evalDelta = [&](int k, int to) -> ll {\n            int from = assign[k];\n            if (to == from) return 0LL;\n\n            int rFrom = (int)r[from][k];\n            int rTo = (int)r[to][k];\n\n            int oldPFrom = P[from], oldPTo = P[to];\n            bool fromInactive = (sz[from] == 1);\n            bool toActive = (sz[to] == 0);\n\n            ll dE = deltaEdge(from, to, fromInactive, toActive);\n\n            // delta P via Fenwick max update, rollback\n            fenw[from].add(rFrom + 1, -1);\n            sz[from]--;\n            fenw[to].add(rTo + 1, +1);\n            sz[to]++;\n\n            int newPFrom = (sz[from] == 0 ? 0 : fenw[from].getMax(sz[from]));\n            int newPTo   = (sz[to] == 0 ? 0 : fenw[to].getMax(sz[to]));\n\n            ll dP = 1LL*newPFrom*newPFrom + 1LL*newPTo*newPTo\n                  - (1LL*oldPFrom*oldPFrom + 1LL*oldPTo*oldPTo);\n\n            // rollback\n            fenw[to].add(rTo + 1, -1);\n            sz[to]--;\n            fenw[from].add(rFrom + 1, +1);\n            sz[from]++;\n\n            return dP + dE;\n        };\n\n        auto commitMove = [&](int k, int to) {\n            int from = assign[k];\n            if (to == from) return;\n\n            int rFrom = (int)r[from][k];\n            int rTo = (int)r[to][k];\n\n            int oldPFrom = P[from], oldPTo = P[to];\n            bool fromInactive = (sz[from] == 1);\n            bool toActive = (sz[to] == 0);\n\n            fenw[from].add(rFrom + 1, -1);\n            sz[from]--;\n            fenw[to].add(rTo + 1, +1);\n            sz[to]++;\n\n            int newPFrom = (sz[from] == 0 ? 0 : fenw[from].getMax(sz[from]));\n            int newPTo   = (sz[to] == 0 ? 0 : fenw[to].getMax(sz[to]));\n\n            Pcost += 1LL*newPFrom*newPFrom + 1LL*newPTo*newPTo\n                   - (1LL*oldPFrom*oldPFrom + 1LL*oldPTo*oldPTo);\n\n            if (fromInactive) {\n                for (int u : spt.anc[from]) {\n                    subtreeCnt[u]--;\n                    if (subtreeCnt[u] == 0) edgeCost -= spt.weightToParent[u];\n                }\n            }\n            if (toActive) {\n                for (int u : spt.anc[to]) {\n                    if (subtreeCnt[u] == 0) edgeCost += spt.weightToParent[u];\n                    subtreeCnt[u]++;\n                }\n            }\n\n            P[from] = newPFrom;\n            P[to] = newPTo;\n            assign[k] = to;\n\n            totalCost = Pcost + edgeCost;\n            if (totalCost < bestCost) {\n                bestCost = totalCost;\n                bestAssign = assign;\n            }\n        };\n\n        // Hill-climb\n        vector<int> order(K);\n        iota(order.begin(), order.end(), 0);\n\n        int passes = 3;\n        for (int pass = 0; pass < passes && !timeUp(); pass++) {\n            shuffle(order.begin(), order.end(), rng);\n            bool any = false;\n\n            for (int k : order) {\n                if (timeUp()) break;\n                int from = assign[k];\n\n                ll bestDelta = 0;\n                int bestTo = -1;\n\n                for (int to : cand[k]) {\n                    if (to == from) continue;\n                    ll d = evalDelta(k, to);\n                    if (d < bestDelta) {\n                        bestDelta = d;\n                        bestTo = to;\n                    }\n                }\n\n                if (bestTo != -1) {\n                    commitMove(k, bestTo);\n                    any = true;\n                }\n            }\n            if (!any) break;\n        }\n\n        // SA escape\n        if (enableSA && !timeUp()) {\n            double temp = 3e6;\n            int steps = 80000; // will be limited by timeUp()\n            for (int it = 0; it < steps && !timeUp(); it++) {\n                int k = (int)(rng() % (uint64_t)K);\n                const auto &vec = cand[k];\n                if (vec.empty()) continue;\n\n                int from = assign[k];\n                int to = vec[(size_t)(rng() % (uint64_t)vec.size())];\n                if (to == from) continue;\n\n                ll d = evalDelta(k, to);\n                if (d <= 0) {\n                    commitMove(k, to);\n                } else {\n                    double prob = exp(-(double)d / temp);\n                    uint64_t r01raw = rng() >> 11; // 53 bits\n                    double r01 = (double)r01raw / (double)(1ULL << 53);\n                    if (r01 < prob) commitMove(k, to);\n                }\n                temp *= 0.9997;\n            }\n        }\n\n        // Rebuild final P and B from bestAssign\n        vector<int> sz2(N, 0), P2(N, 0);\n        vector<Fenwick> fenw2(N);\n        for (int i = 0; i < N; i++) fenw2[i].init(LIM + 1);\n\n        for (int k = 0; k < K; k++) {\n            int s = bestAssign[k];\n            sz2[s]++;\n            fenw2[s].add((int)r[s][k] + 1, +1);\n        }\n        for (int i = 0; i < N; i++) P2[i] = (sz2[i] ? fenw2[i].getMax(sz2[i]) : 0);\n\n        vector<int> subtreeCnt2(N, 0);\n        function<int(int)> dfs2 = [&](int v) -> int {\n            int cnt = (sz2[v] > 0) ? 1 : 0;\n            for (int to : spt.children[v]) cnt += dfs2(to);\n            subtreeCnt2[v] = cnt;\n            return cnt;\n        };\n        dfs2(0);\n\n        vector<int> activeEdges(M, 0);\n        for (int v = 1; v < N; v++) if (subtreeCnt2[v] > 0) activeEdges[spt.parentEdgeId[v]] = 1;\n\n        vector<int> out(N + M);\n        for (int i = 0; i < N; i++) out[i] = P2[i];\n        for (int j = 0; j < M; j++) out[N + j] = activeEdges[j];\n\n        return {bestCost, out};\n    };\n\n    // Overall loop\n    auto overallStart = chrono::steady_clock::now();\n    auto elapsedMs = [&]() -> int {\n        return (int)chrono::duration_cast<chrono::milliseconds>(chrono::steady_clock::now() - overallStart).count();\n    };\n    auto timeUpOverall = [&]() -> bool { return elapsedMs() > 1900; };\n\n    vector<uint64_t> sptSeeds = {1234567ULL, 987654321ULL, 19260817ULL, 5555557ULL, 246813579ULL};\n\n    int Lnear = 16, Lshallow = 8;\n    int ancestorSpan = 4;\n    int Lcap = 32;\n    int maxTrialsPerSPT = 4;\n\n    ll bestCost = (1LL<<62);\n    vector<int> bestOut(N + M, 0);\n\n    int trialsLeft = (int)sptSeeds.size() * maxTrialsPerSPT;\n\n    for (int si = 0; si < (int)sptSeeds.size() && !timeUpOverall(); si++) {\n        SPT spt = buildSPT(sptSeeds[si]);\n        auto cand = buildCandidates(spt, Lnear, Lshallow, ancestorSpan, Lcap);\n\n        vector<vector<int>> inits;\n        inits.reserve(maxTrialsPerSPT);\n\n        // Init 0: minimal required radius among candidates\n        {\n            vector<int> a(K, 0);\n            for (int k = 0; k < K; k++) {\n                int best = cand[k][0];\n                int bestNeed = (int)r[best][k];\n                for (int s : cand[k]) {\n                    int need = (int)r[s][k];\n                    if (need < bestNeed) { bestNeed = need; best = s; }\n                }\n                a[k] = best;\n            }\n            inits.push_back(std::move(a));\n        }\n\n        // Init 1: biased random among smallest by radius\n        {\n            mt19937_64 rng(7777 + si * 131);\n            vector<int> a(K, 0);\n            for (int k = 0; k < K; k++) {\n                vector<pair<int,int>> tmp;\n                tmp.reserve(cand[k].size());\n                for (int s : cand[k]) tmp.push_back({(int)r[s][k], s});\n                sort(tmp.begin(), tmp.end());\n                int T = min(4, (int)tmp.size());\n                a[k] = tmp[(size_t)(rng() % (uint64_t)T)].second;\n            }\n            inits.push_back(std::move(a));\n        }\n\n        // Init 2,3: accurate greedy model\n        if ((int)inits.size() < maxTrialsPerSPT) inits.push_back(greedyInit(spt, cand, 1000003ULL + si * 999983ULL));\n        if ((int)inits.size() < maxTrialsPerSPT) inits.push_back(greedyInit(spt, cand, 1000003ULL + si * 999983ULL + 12345ULL));\n\n        for (int ti = 0; ti < (int)inits.size() && !timeUpOverall(); ti++) {\n            int remaining = 1900 - elapsedMs();\n            int tl = max(70, min(280, remaining / max(1, trialsLeft)));\n            trialsLeft--;\n\n            uint64_t trialSeed = sptSeeds[si] * 10000019ULL + (uint64_t)ti * 10007ULL + 89123ULL;\n\n            auto [cost, out] = solveTrial(spt, cand, inits[ti], trialSeed, tl, true);\n            if (cost < bestCost) {\n                bestCost = cost;\n                bestOut = std::move(out);\n            }\n        }\n    }\n\n    for (int i = 0; i < N; i++) {\n        if (i) cout << ' ';\n        cout << bestOut[i];\n    }\n    cout << '\\n';\n    for (int j = 0; j < M; j++) {\n        if (j) cout << ' ';\n        cout << bestOut[N + j];\n    }\n    cout << '\\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 LIM = 10000;\nstatic constexpr int KEY_SAMP = 40;\nstatic constexpr int E_SAMP = 60;\n\nstruct SwapOp {\n    short x1, y1, x2, y2;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    auto id = [](int x, int y) -> int { return x * (x + 1) / 2 + y; };\n\n    vector<int> cx(V), cy(V);\n    for (int x = 0; x < N; x++) for (int y = 0; y <= x; y++) {\n        int idx = id(x, y);\n        cx[idx] = x;\n        cy[idx] = y;\n    }\n\n    // Read\n    vector<int> at(V), pos(V);\n    for (int x = 0; x < N; x++) for (int y = 0; y <= x; y++) {\n        int b; cin >> b;\n        int idx = id(x, y);\n        at[idx] = b;\n        pos[b] = idx;\n    }\n\n    // key partition by value rank: blocks 1,2,...,30\n    // pref[t] = sum_{i=1..t+1} i = (t+1)(t+2)/2, and block t is values in [pref[t-1], pref[t]-1]\n    vector<int> pref(N);\n    for (int t = 0; t < N; t++) pref[t] = (t + 1) * (t + 2) / 2;\n\n    vector<int> key(V);\n    for (int v = 0; v < V; v++) {\n        int t = 0;\n        while (t < N && v >= pref[t]) t++;\n        key[v] = t;\n    }\n\n    // Build cover edges: u at tier x -> child at tier x+1 (two children)\n    // store directed edges list (from[e] -> to[e])\n    // and for each cell, store up to 2 incoming/outgoing cover edges.\n    vector<int> from, to;\n    from.reserve(870);\n    to.reserve(870);\n\n    vector<array<int,2>> outEdge(V, array<int,2>{-1,-1});\n    vector<array<int,2>> inEdge(V, array<int,2>{-1,-1});\n\n    auto add_out = [&](int u, int eidx) {\n        if (outEdge[u][0] == -1) outEdge[u][0] = eidx;\n        else outEdge[u][1] = eidx;\n    };\n    auto add_in = [&](int v, int eidx) {\n        if (inEdge[v][0] == -1) inEdge[v][0] = eidx;\n        else inEdge[v][1] = eidx;\n    };\n\n    int M = 0;\n    for (int x = 0; x <= N - 2; x++) {\n        for (int y = 0; y <= x; y++) {\n            int u = id(x, y);\n            int c1 = id(x + 1, y);\n            int c2 = id(x + 1, y + 1);\n\n            int e1 = M++;\n            from.push_back(u); to.push_back(c1);\n            add_out(u, e1); add_in(c1, e1);\n\n            int e2 = M++;\n            from.push_back(u); to.push_back(c2);\n            add_out(u, e2); add_in(c2, e2);\n        }\n    }\n\n    auto affectedEdges = [&](int a, int b, int buf[16]) -> int {\n        int cnt = 0;\n        auto add = [&](int e) {\n            if (e < 0) return;\n            for (int i = 0; i < cnt; i++) if (buf[i] == e) return;\n            buf[cnt++] = e;\n        };\n        for (int k = 0; k < 2; k++) {\n            add(outEdge[a][k]); add(inEdge[a][k]);\n            add(outEdge[b][k]); add(inEdge[b][k]);\n        }\n        return cnt;\n    };\n\n    // Swap implementation\n    vector<SwapOp> ops;\n    ops.reserve(LIM);\n    int K = 0;\n\n    auto doSwap = [&](int a, int b) -> bool {\n        if (K >= LIM) return false;\n        if (a == b) return true;\n        ops.push_back(SwapOp{(short)cx[a], (short)cy[a], (short)cx[b], (short)cy[b]});\n        K++;\n        int va = at[a], vb = at[b];\n        swap(at[a], at[b]);\n        pos[va] = b;\n        pos[vb] = a;\n        return true;\n    };\n\n    // Stage 1: key violations along cover edges\n    vector<char> keyViol(M, 0);\n    deque<int> qKey;\n    int keyViolCnt = 0;\n\n    for (int e = 0; e < M; e++) {\n        int u = from[e], v = to[e];\n        bool w = key[at[u]] > key[at[v]];\n        keyViol[e] = (char)w;\n        if (w) { keyViolCnt++; qKey.push_back(e); }\n    }\n\n    auto computeKeyDelta = [&](int a, int b) -> int {\n        int buf[16];\n        int cnt = affectedEdges(a, b, buf);\n        int va = at[a], vb = at[b];\n        int oldSum = 0, newSum = 0;\n        for (int i = 0; i < cnt; i++) {\n            int e = buf[i];\n            oldSum += (keyViol[e] ? 1 : 0);\n            int u = from[e], v = to[e];\n            int newUVal = (u == a ? vb : (u == b ? va : at[u]));\n            int newVVal = (v == a ? vb : (v == b ? va : at[v]));\n            bool nw = key[newUVal] > key[newVVal];\n            newSum += (nw ? 1 : 0);\n        }\n        return newSum - oldSum;\n    };\n\n    auto updateKeyAround = [&](int a, int b, deque<int> &queue) {\n        int buf[16];\n        int cnt = affectedEdges(a, b, buf);\n        for (int i = 0; i < cnt; i++) {\n            int e = buf[i];\n            int u = from[e], v = to[e];\n            bool nw = key[at[u]] > key[at[v]];\n            if ((bool)keyViol[e] != nw) {\n                keyViolCnt += (nw ? +1 : -1);\n                keyViol[e] = (char)nw;\n                if (nw) queue.push_back(e);\n            }\n        }\n    };\n\n    int stuckKey = 0;\n    while (keyViolCnt > 0 && K < LIM) {\n        if (qKey.empty()) {\n            for (int e = 0; e < M; e++) if (keyViol[e]) qKey.push_back(e);\n            if (qKey.empty()) break;\n        }\n\n        vector<int> cand;\n        cand.reserve(KEY_SAMP);\n        while (!qKey.empty() && (int)cand.size() < KEY_SAMP) {\n            int e = qKey.front(); qKey.pop_front();\n            if (keyViol[e]) cand.push_back(e);\n        }\n\n        int bestE = -1;\n        int bestDelta = INT_MAX;\n\n        for (int e : cand) {\n            int a = from[e], b = to[e];\n            int delta = computeKeyDelta(a, b);\n            if (delta < bestDelta) {\n                bestDelta = delta;\n                bestE = e;\n            }\n        }\n\n        // Reinsert other candidates (keep queue alive)\n        for (int e : cand) if (e != bestE) qKey.push_back(e);\n\n        if (bestE == -1) break;\n        int a = from[bestE], b = to[bestE];\n\n        // Prefer non-increasing key violations; occasionally allow small increase if stuck.\n        bool accept = false;\n        if (bestDelta <= 0) accept = true;\n        else if (stuckKey > 200 && bestDelta <= 1) accept = true;\n\n        if (!accept) {\n            stuckKey++;\n            // As a fallback, accept best non-stale edge directly if it still violates.\n            // (This should be rare.)\n            if (bestDelta <= 2) accept = true;\n        }\n\n        if (!accept) break; // let Stage 2 handle remaining if any\n\n        if (!doSwap(a, b)) break;\n        updateKeyAround(a, b, qKey);\n        stuckKey = (bestDelta <= 0 ? 0 : stuckKey + 1);\n    }\n\n    // compute E and actViol\n    vector<char> actViol(M, 0);\n    long long Ecnt = 0;\n    for (int e = 0; e < M; e++) {\n        int u = from[e], v = to[e];\n        bool w = at[u] > at[v];\n        actViol[e] = (char)w;\n        if (w) Ecnt++;\n    }\n\n    if (Ecnt == 0) {\n        cout << K << \"\\n\";\n        for (auto &op : ops) cout << op.x1 << \" \" << op.y1 << \" \" << op.x2 << \" \" << op.y2 << \"\\n\";\n        return 0;\n    }\n\n    // Stage 2: fix only equal-key edges (but choose best delta)\n    deque<int> qAct;\n    for (int e = 0; e < M; e++) {\n        int u = from[e], v = to[e];\n        if (actViol[e] && key[at[u]] == key[at[v]]) qAct.push_back(e);\n    }\n\n    auto computeEDelta = [&](int a, int b) -> long long {\n        int buf[16];\n        int cnt = affectedEdges(a, b, buf);\n        int va = at[a], vb = at[b];\n        long long oldSum = 0, newSum = 0;\n        for (int i = 0; i < cnt; i++) {\n            int e = buf[i];\n            oldSum += (actViol[e] ? 1 : 0);\n            int u = from[e], v = to[e];\n            int newUVal = (u == a ? vb : (u == b ? va : at[u]));\n            int newVVal = (v == a ? vb : (v == b ? va : at[v]));\n            bool nw = newUVal > newVVal;\n            newSum += (nw ? 1 : 0);\n        }\n        return newSum - oldSum;\n    };\n\n    auto updateActAround = [&](int a, int b, deque<int> &queue) {\n        int buf[16];\n        int cnt = affectedEdges(a, b, buf);\n        for (int i = 0; i < cnt; i++) {\n            int e = buf[i];\n            int u = from[e], v = to[e];\n            bool nw = at[u] > at[v];\n            if ((bool)actViol[e] != nw) {\n                Ecnt += (nw ? +1 : -1);\n                actViol[e] = (char)nw;\n            }\n            // Always consider pushing if violated and keys equal\n            if (nw) {\n                if (key[at[u]] == key[at[v]]) queue.push_back(e);\n            }\n        }\n    };\n\n    int stuckE = 0;\n    while (Ecnt > 0 && K < LIM) {\n        if (qAct.empty()) {\n            for (int e = 0; e < M; e++) {\n                if (actViol[e]) {\n                    int u = from[e], v = to[e];\n                    if (key[at[u]] == key[at[v]]) qAct.push_back(e);\n                }\n            }\n            if (qAct.empty()) break; // no equal-key moves\n        }\n\n        vector<int> cand;\n        cand.reserve(E_SAMP);\n        while (!qAct.empty() && (int)cand.size() < E_SAMP) {\n            int e = qAct.front(); qAct.pop_front();\n            if (!actViol[e]) continue;\n            int u = from[e], v = to[e];\n            if (key[at[u]] != key[at[v]]) continue;\n            cand.push_back(e);\n        }\n        if (cand.empty()) continue;\n\n        int bestE = -1;\n        long long bestDelta = (1LL<<60);\n\n        for (int e : cand) {\n            int a = from[e], b = to[e];\n            long long delta = computeEDelta(a, b);\n            if (delta < bestDelta) {\n                bestDelta = delta;\n                bestE = e;\n            }\n        }\n\n        for (int e : cand) if (e != bestE) qAct.push_back(e);\n\n        if (bestE == -1) continue;\n        int a = from[bestE], b = to[bestE];\n\n        // Accept rules: prefer delta<0, allow delta==0, avoid delta>0 unless stuck.\n        bool accept = false;\n        if (bestDelta < 0) accept = true;\n        else if (bestDelta == 0) accept = (stuckE > 50); // reduce plateau wandering\n        else {\n            // bestDelta > 0\n            accept = (stuckE > 400 && bestDelta <= 2);\n        }\n\n        if (!accept) {\n            stuckE++;\n            // If very stuck, do a deterministic rescue: take any violated equal-key edge.\n            if (stuckE > 800) {\n                int rescueE = -1;\n                for (int e : cand) { if (actViol[e]) { rescueE = e; break; } }\n                if (rescueE == -1) break;\n                a = from[rescueE]; b = to[rescueE];\n                if (!doSwap(a, b)) break;\n                updateActAround(a, b, qAct);\n                stuckE = 0;\n            }\n            continue;\n        }\n\n        if (!doSwap(a, b)) break;\n        updateActAround(a, b, qAct);\n        stuckE = 0;\n    }\n\n    cout << K << \"\\n\";\n    for (auto &op : ops) cout << op.x1 << \" \" << op.y1 << \" \" << op.x2 << \" \" << op.y2 << \"\\n\";\n    return 0;\n}","toyota2023summer-final":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\n\nstatic const int dx4[4] = {-1, 1, 0, 0}; // up, down, left, right in i\nstatic const int dy4[4] = {0, 0, -1, 1}; // u, d, l, r in j\n\nstruct Tree {\n    int V = 0;\n    int ent = -1;\n    vector<int> parent;\n    vector<int> depth;\n    vector<int> bfsOrder;\n    vector<vector<int>> children; // rooted tree edges: parent -> children\n};\n\nstatic Tree build_bfs_tree(\n    int D,\n    const vector<vector<int>> &id,\n    int ent,\n    const vector<pair<int,int>> &coord,\n    const array<int,4> &dirOrder\n){\n    int V = 0;\n    for (int i = 0; i < D; i++) for (int j = 0; j < D; j++)\n        if (id[i][j] >= 0) V = max(V, id[i][j] + 1);\n\n    vector<int> parent(V, -1), depth(V, -1), bfsOrder(V, -1);\n    vector<vector<int>> children(V);\n    vector<char> vis(V, 0);\n\n    queue<int> q;\n    vis[ent] = 1;\n    depth[ent] = 0;\n    parent[ent] = -1;\n    q.push(ent);\n\n    // Choose parent by BFS with specified neighbor order.\n    while (!q.empty()) {\n        int v = q.front(); q.pop();\n        auto [x, y] = coord[v];\n        for (int k = 0; k < 4; k++) {\n            int dir = dirOrder[k]; // 0..3\n            int nx = x + dx4[dir];\n            int ny = y + dy4[dir];\n            if (nx < 0 || nx >= D || ny < 0 || ny >= D) continue;\n            int nid = id[nx][ny];\n            if (nid < 0) continue;\n            if (vis[nid]) continue;\n            vis[nid] = 1;\n            parent[nid] = v;\n            depth[nid] = depth[v] + 1;\n            q.push(nid);\n        }\n    }\n\n    // children\n    for (int v = 0; v < V; v++) {\n        if (v == ent) continue;\n        int p = parent[v];\n        if (p >= 0) children[p].push_back(v);\n    }\n\n    // bfsOrder along the rooted-tree edges (level-order within tree)\n    vector<char> inq(V, 0);\n    queue<int> qq;\n    bfsOrder[ent] = 0;\n    inq[ent] = 1;\n    qq.push(ent);\n    int ord = 1;\n    while (!qq.empty()) {\n        int v = qq.front(); qq.pop();\n        for (int ch : children[v]) {\n            if (inq[ch]) continue;\n            inq[ch] = 1;\n            bfsOrder[ch] = ord++;\n            qq.push(ch);\n        }\n    }\n\n    Tree t;\n    t.V = V;\n    t.ent = ent;\n    t.parent = move(parent);\n    t.depth = move(depth);\n    t.bfsOrder = move(bfsOrder);\n    t.children = move(children);\n    return t;\n}\n\nstatic vector<int> compute_subtree_sizes(const Tree &t) {\n    vector<int> sub(t.V, 1);\n    vector<int> nodes(t.V);\n    iota(nodes.begin(), nodes.end(), 0);\n    sort(nodes.begin(), nodes.end(), [&](int a,int b){\n        return t.depth[a] > t.depth[b];\n    });\n    for (int v : nodes) {\n        if (v == t.ent) continue;\n        int p = t.parent[v];\n        if (p >= 0) sub[p] += sub[v];\n    }\n    return sub;\n}\n\n// simulate greedy removal order under structural priorities (no labels).\n// parent must be removed before child (ancestor-before-descendant poset).\nstatic vector<int> simulate_proxy_pos(\n    const Tree &t,\n    const vector<ll> &key1,\n    const vector<ll> &key2\n){\n    int M = t.V - 1;\n    vector<int> pos(t.V, -1);\n    vector<char> removed(t.V, 0);\n\n    struct Node {\n        ll k1, k2;\n        int ord;\n        int v;\n    };\n    struct Cmp {\n        bool operator()(const Node &a, const Node &b) const {\n            if (a.k1 != b.k1) return a.k1 > b.k1; // min heap\n            if (a.k2 != b.k2) return a.k2 > b.k2;\n            if (a.ord != b.ord) return a.ord > b.ord;\n            return a.v > b.v;\n        }\n    };\n\n    priority_queue<Node, vector<Node>, Cmp> pq;\n    for (int ch : t.children[t.ent]) {\n        pq.push({key1[ch], key2[ch], t.bfsOrder[ch], ch});\n    }\n\n    int cnt = 0;\n    while (cnt < M) {\n        auto cur = pq.top(); pq.pop();\n        int v = cur.v;\n        if (removed[v]) continue;\n        removed[v] = 1;\n        pos[v] = cnt++;\n        for (int ch : t.children[v]) {\n            if (!removed[ch]) pq.push({key1[ch], key2[ch], t.bfsOrder[ch], ch});\n        }\n    }\n    return pos;\n}\n\nstruct Fenwick {\n    int n;\n    vector<int> bit;\n    Fenwick(int n=0): n(n), bit(n+1, 0) {}\n    void add(int i, int v){ // i: 0-index\n        for(i++; i <= n; i += i&-i) bit[i] += v;\n    }\n    int sumInclusive(int r){ // sum [0..r]\n        if(r < 0) return 0;\n        int s = 0;\n        for(int i = r+1; i > 0; i -= i&-i) s += bit[i];\n        return s;\n    }\n};\n\nstatic ll count_inversions(const vector<int> &a, int maxVal) {\n    int n = (int)a.size();\n    Fenwick fw(maxVal + 1);\n    ll inv = 0;\n    for (int i = 0; i < n; i++) {\n        int x = a[i];\n        int le = fw.sumInclusive(x); // count of <= x so far\n        inv += (ll)i - le;           // previous > x\n        fw.add(x, 1);\n    }\n    return inv;\n}\n\nstruct InsertionHeuristic {\n    int V = 0;\n    int M = 0;\n    int P = 0;\n    vector<vector<int>> proxyPos; // P x V\n};\n\nstatic inline ll candidate_cost(\n    int v, int tval,\n    const InsertionHeuristic &ih,\n    const vector<int> &assignedNodes,\n    const vector<int> &label\n){\n    ll total = 0;\n    for (int p = 0; p < ih.P; p++) {\n        int pv = ih.proxyPos[p][v];\n        for (int u : assignedNodes) {\n            int pu = ih.proxyPos[p][u];\n            int lu = label[u];\n            if (pu < pv) {\n                if (lu > tval) total++;\n            } else { // pu > pv (proxy ranks are permutation)\n                if (tval > lu) total++;\n            }\n        }\n    }\n    return total;\n}\n\nstatic int pick_best_node(\n    const Tree &t,\n    const InsertionHeuristic &ih,\n    const vector<int> &readyVec,\n    const vector<char> &readyFlag,\n    const vector<int> &assignedNodes,\n    const vector<int> &label,\n    int tval\n){\n    int bestV = -1;\n    ll bestCost = (1LL<<62);\n    ll bestTie = (1LL<<62);\n\n    for (int v : readyVec) {\n        if (!readyFlag[v]) continue;\n        ll c = candidate_cost(v, tval, ih, assignedNodes, label);\n\n        ll tie = 0;\n        for (int p = 0; p < ih.P; p++) {\n            int pv = ih.proxyPos[p][v];\n            tie += llabs((ll)pv - (ll)tval);\n        }\n\n        if (c < bestCost || (c == bestCost && tie < bestTie)) {\n            bestCost = c;\n            bestTie = tie;\n            bestV = v;\n        }\n    }\n    return bestV;\n}\n\nstatic void compute_tin_tout(const Tree &t, vector<int> &tin, vector<int> &tout){\n    int V = t.V;\n    tin.assign(V, -1);\n    tout.assign(V, -1);\n    int timer = 0;\n    vector<int> it(V, 0);\n    vector<int> st;\n    st.reserve(V);\n    st.push_back(t.ent);\n    tin[t.ent] = timer++;\n    while (!st.empty()) {\n        int v = st.back();\n        if (it[v] < (int)t.children[v].size()) {\n            int to = t.children[v][it[v]++];\n            tin[to] = timer++;\n            st.push_back(to);\n        } else {\n            tout[v] = timer;\n            st.pop_back();\n        }\n    }\n}\n\nstatic inline bool isAncestor(const vector<int> &tin, const vector<int> &tout, int a, int b){\n    return tin[a] <= tin[b] && tin[b] < tout[a];\n}\n\n// swap order adjacent elements if it doesn't violate partial order.\nstatic void swap_improve_order(\n    const Tree &t,\n    const vector<int> &labels,\n    vector<int> &orderNodes,\n    const vector<int> &tin,\n    const vector<int> &tout\n){\n    int M = (int)orderNodes.size();\n    auto canSwapAdj = [&](int A, int B)->bool{\n        // if one is ancestor of the other, swapping breaks feasibility\n        return !(isAncestor(tin,tout,A,B) || isAncestor(tin,tout,B,A));\n    };\n\n    for (int pass = 0; pass < M; pass++) {\n        bool changed = false;\n        for (int i = 0; i + 1 < M; i++) {\n            int A = orderNodes[i];\n            int B = orderNodes[i+1];\n            if (labels[A] > labels[B] && canSwapAdj(A,B)) {\n                swap(orderNodes[i], orderNodes[i+1]);\n                changed = true;\n            }\n        }\n        if (!changed) break;\n    }\n}\n\nstatic vector<int> build_transport_order_greedy(\n    const Tree &t,\n    const vector<int> &labels,\n    int mode\n){\n    int M = t.V - 1;\n    vector<char> removed(t.V, 0);\n\n    struct Node { int k1, k2, ord, v; };\n    struct Cmp {\n        bool operator()(const Node& a, const Node& b) const {\n            if (a.k1 != b.k1) return a.k1 > b.k1; // min by k1\n            if (a.k2 != b.k2) return a.k2 > b.k2;\n            if (a.ord != b.ord) return a.ord > b.ord;\n            return a.v > b.v;\n        }\n    };\n    priority_queue<Node, vector<Node>, Cmp> pq;\n\n    auto push = [&](int v){\n        int lab = labels[v];\n        if (mode == 0) {\n            // min label; break ties by shallower depth then bfsOrder\n            pq.push({lab, t.depth[v], t.bfsOrder[v], v});\n        } else if (mode == 1) {\n            // min label; break ties by deeper depth\n            pq.push({lab, -t.depth[v], t.bfsOrder[v], v});\n        } else {\n            // max label; break ties by shallower depth\n            pq.push({-lab, t.depth[v], t.bfsOrder[v], v});\n        }\n    };\n\n    for (int ch : t.children[t.ent]) push(ch);\n\n    vector<int> order;\n    order.reserve(M);\n    while ((int)order.size() < M) {\n        auto cur = pq.top(); pq.pop();\n        int v = cur.v;\n        if (removed[v]) continue;\n        removed[v] = 1;\n        order.push_back(v);\n        for (int ch : t.children[v]) if (!removed[ch]) push(ch);\n    }\n    return order;\n}\n\nstatic ll simulate_pipeline(\n    const Tree &t,\n    const InsertionHeuristic &ih,\n    const vector<int> &perm,   // arrival order labels t_d = perm[d]\n    const vector<int> &tin,\n    const vector<int> &tout\n){\n    int M = ih.M;\n\n    // online insertion simulation producing label assignment\n    vector<int> labels(t.V, -1);\n    vector<int> remChildCnt(t.V, 0);\n    for (int v = 0; v < t.V; v++) {\n        if (v == t.ent) continue;\n        remChildCnt[v] = (int)t.children[v].size();\n    }\n\n    vector<char> readyFlag(t.V, 0);\n    vector<int> readyVec;\n    readyVec.reserve(M);\n    for (int v = 0; v < t.V; v++) {\n        if (v == t.ent) continue;\n        if (remChildCnt[v] == 0) {\n            readyFlag[v] = 1;\n            readyVec.push_back(v);\n        }\n    }\n\n    vector<int> assignedNodes;\n    assignedNodes.reserve(M);\n\n    for (int d = 0; d < M; d++) {\n        int t_d = perm[d];\n        int v = pick_best_node(t, ih, readyVec, readyFlag, assignedNodes, labels, t_d);\n\n        readyFlag[v] = 0;\n        labels[v] = t_d;\n        assignedNodes.push_back(v);\n\n        int p = t.parent[v];\n        if (p >= 0 && p != t.ent) {\n            remChildCnt[p]--;\n            if (remChildCnt[p] == 0) {\n                readyFlag[p] = 1;\n                readyVec.push_back(p);\n            }\n        }\n    }\n\n    // offline transport: try multiple modes + constrained swap improvement\n    ll bestInv = (1LL<<62);\n    vector<int> bestOrder;\n\n    for (int mode = 0; mode < 3; mode++) {\n        vector<int> orderNodes = build_transport_order_greedy(t, labels, mode);\n        swap_improve_order(t, labels, orderNodes, tin, tout);\n\n        vector<int> seq;\n        seq.reserve(M);\n        for (int v : orderNodes) seq.push_back(labels[v]);\n        ll inv = count_inversions(seq, M-1);\n        if (inv < bestInv) {\n            bestInv = inv;\n            bestOrder = move(orderNodes);\n        }\n    }\n    return bestInv;\n}\n\nint main(){\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int D, N;\n    cin >> D >> N;\n    vector<vector<bool>> obs(D, vector<bool>(D,false));\n    vector<pair<int,int>> obstacles;\n    obstacles.reserve(N);\n    for (int k=0;k<N;k++){\n        int ri, rj;\n        cin >> ri >> rj;\n        obs[ri][rj] = true;\n        obstacles.push_back({ri,rj});\n    }\n\n    int ent_i = 0, ent_j = (D-1)/2;\n\n    vector<vector<int>> id(D, vector<int>(D, -1));\n    vector<pair<int,int>> coord;\n    coord.reserve(D*D);\n\n    int V = 0;\n    for (int i=0;i<D;i++) for (int j=0;j<D;j++){\n        if (obs[i][j]) continue;\n        id[i][j] = V++;\n        coord.push_back({i,j});\n    }\n\n    int ent = id[ent_i][ent_j];\n    int M = V - 1;\n\n    vector<array<int,4>> dirCandidates = {\n        array<int,4>{0,3,1,2},\n        array<int,4>{0,2,1,3},\n        array<int,4>{1,3,0,2},\n        array<int,4>{1,2,0,3},\n        array<int,4>{3,0,2,1},\n        array<int,4>{2,0,3,1},\n    };\n\n    // deterministic seed base\n    auto mix64 = [](uint64_t x)->uint64_t{\n        x ^= x >> 33;\n        x *= 0xff51afd7ed558ccdULL;\n        x ^= x >> 33;\n        x *= 0xc4ceb9fe1a85ec53ULL;\n        x ^= x >> 33;\n        return x;\n    };\n\n    uint64_t base = 0x123456789abcdefULL;\n    for (auto [a,b] : obstacles) base ^= mix64((uint64_t)a*1315423911ULL + (uint64_t)b*2654435761ULL + 0x9e3779b97f4a7c15ULL);\n    base ^= mix64((uint64_t)N * 1000003ULL);\n\n    int S = 2; // samples per tree candidate (tree evaluation now matches final pipeline)\n    ll bestAvg = (1LL<<62);\n    Tree bestTree;\n    InsertionHeuristic bestIH;\n\n    for (int ci = 0; ci < (int)dirCandidates.size(); ci++) {\n        auto dirOrder = dirCandidates[ci];\n        Tree t = build_bfs_tree(D, id, ent, coord, dirOrder);\n\n        // structural proxy preparation\n        auto sub = compute_subtree_sizes(t);\n\n        vector<ll> key1a(t.V), key2a(t.V);\n        vector<ll> key1b(t.V), key2b(t.V);\n        vector<ll> key1c(t.V), key2c(t.V);\n        vector<ll> key1d(t.V), key2d(t.V);\n\n        for (int v=0; v<t.V; v++){\n            if (v == t.ent) continue;\n            key1a[v] = t.depth[v];      key2a[v] = 0;\n            key1b[v] = t.depth[v];      key2b[v] = - (ll)sub[v];\n            key1c[v] = t.depth[v];      key2c[v] = + (ll)sub[v];\n            key1d[v] = - (ll)t.depth[v];key2d[v] = + (ll)sub[v];\n        }\n\n        vector<vector<int>> proxyPos;\n        proxyPos.push_back(simulate_proxy_pos(t, key1a, key2a));\n        proxyPos.push_back(simulate_proxy_pos(t, key1b, key2b));\n        proxyPos.push_back(simulate_proxy_pos(t, key1c, key2c));\n        proxyPos.push_back(simulate_proxy_pos(t, key1d, key2d));\n\n        InsertionHeuristic ih;\n        ih.V = t.V;\n        ih.M = M;\n        ih.P = (int)proxyPos.size();\n        ih.proxyPos = move(proxyPos);\n\n        // ancestor info for swap feasibility\n        vector<int> tin, tout;\n        compute_tin_tout(t, tin, tout);\n\n        ll sumBestInv = 0;\n        for (int s = 0; s < S; s++) {\n            // deterministic permutation\n            uint64_t seed = mix64(base ^ (uint64_t)ci * 1000003ULL ^ (uint64_t)s * 10007ULL);\n            mt19937 rng((uint32_t)seed);\n\n            vector<int> perm(M);\n            iota(perm.begin(), perm.end(), 0);\n            shuffle(perm.begin(), perm.end(), rng);\n\n            sumBestInv += simulate_pipeline(t, ih, perm, tin, tout);\n        }\n        ll avg = sumBestInv / S;\n\n        if (avg < bestAvg) {\n            bestAvg = avg;\n            bestTree = move(t);\n            bestIH = move(ih);\n        }\n    }\n\n    // ===== Real online insertion with bestTree/bestIH =====\n    const Tree &t = bestTree;\n    const InsertionHeuristic &ih = bestIH;\n\n    vector<int> remChildCnt(t.V, 0);\n    for (int v=0; v<t.V; v++){\n        if(v == t.ent) continue;\n        remChildCnt[v] = (int)t.children[v].size();\n    }\n\n    vector<char> readyFlag(t.V, 0);\n    vector<int> readyVec;\n    readyVec.reserve(M);\n    for (int v=0; v<t.V; v++){\n        if(v == t.ent) continue;\n        if(remChildCnt[v] == 0){\n            readyFlag[v] = 1;\n            readyVec.push_back(v);\n        }\n    }\n\n    vector<int> labels(t.V, -1);\n    vector<int> assignedNodes;\n    assignedNodes.reserve(M);\n\n    for (int d=0; d<M; d++){\n        int t_d;\n        cin >> t_d;\n\n        int v = pick_best_node(t, ih, readyVec, readyFlag, assignedNodes, labels, t_d);\n\n        auto [pi,pj] = coord[v];\n        cout << pi << ' ' << pj << \"\\n\" << flush;\n\n        readyFlag[v] = 0;\n        labels[v] = t_d;\n        assignedNodes.push_back(v);\n\n        int p = t.parent[v];\n        if(p >= 0 && p != t.ent){\n            remChildCnt[p]--;\n            if(remChildCnt[p] == 0){\n                readyFlag[p] = 1;\n                readyVec.push_back(p);\n            }\n        }\n    }\n\n    // ===== Real transport: same refined pipeline as evaluation =====\n    vector<int> tin, tout;\n    compute_tin_tout(t, tin, tout);\n\n    ll bestInv = (1LL<<62);\n    vector<int> bestOrderNodes;\n\n    for (int mode=0; mode<3; mode++){\n        vector<int> orderNodes = build_transport_order_greedy(t, labels, mode);\n        swap_improve_order(t, labels, orderNodes, tin, tout);\n\n        vector<int> seq;\n        seq.reserve(M);\n        for(int v: orderNodes) seq.push_back(labels[v]);\n        ll inv = count_inversions(seq, M-1);\n        if(inv < bestInv){\n            bestInv = inv;\n            bestOrderNodes = move(orderNodes);\n        }\n    }\n\n    for (int k=0;k<M;k++){\n        auto [qi,qj] = coord[bestOrderNodes[k]];\n        cout << qi << ' ' << qj << \"\\n\" << flush;\n    }\n    return 0;\n}","ahc024":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const int DIRS[4][2] = {{1,0},{-1,0},{0,1},{0,-1}};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int n, m;\n    cin >> n >> m;\n    vector<vector<int>> a(n, vector<int>(n));\n    for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) cin >> a[i][j];\n\n    const int N = n * n;\n    auto id = [&](int i, int j) { return i * n + j; };\n    auto ij = [&](int v) { return pair<int,int>(v / n, v % n); };\n\n    // neighbor list for within-grid traversal\n    vector<array<int,4>> nb(N);\n    for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) {\n        int v = id(i,j);\n        for (int k = 0; k < 4; k++) {\n            int ni = i + DIRS[k][0], nj = j + DIRS[k][1];\n            nb[v][k] = (0 <= ni && ni < n && 0 <= nj && nj < n) ? id(ni,nj) : -1;\n        }\n    }\n\n    // original adjacency matrix among colors\n    vector<vector<unsigned char>> adjOrig(m+1, vector<unsigned char>(m+1, 0));\n    for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) {\n        int c1 = a[i][j];\n        for (int k = 0; k < 4; k++) {\n            int ni = i + DIRS[k][0], nj = j + DIRS[k][1];\n            int c2 = (ni < 0 || ni >= n || nj < 0 || nj >= n) ? 0 : a[ni][nj];\n            if (c1 == c2) continue;\n            int x = min(c1,c2), y = max(c1,c2);\n            adjOrig[x][y] = 1;\n        }\n    }\n\n    // touchOutside and boundary cells\n    vector<unsigned char> touchOutside(m+1, 0);\n    vector<vector<int>> boundaryCells(m+1);\n    for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) {\n        int c = a[i][j];\n        if (i==0 || i==n-1 || j==0 || j==n-1) {\n            touchOutside[c] = 1;\n            boundaryCells[c].push_back(id(i,j));\n        }\n    }\n\n    // forbidden colors: not touching outside in original\n    vector<unsigned char> forbidden(m+1, 0);\n    for (int c = 1; c <= m; c++) forbidden[c] = !touchOutside[c];\n\n    // isColor and posByColor\n    vector<vector<unsigned char>> isColor(m+1, vector<unsigned char>(N, 0));\n    vector<vector<int>> posByColor(m+1);\n    for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) {\n        int c = a[i][j];\n        int v = id(i,j);\n        isColor[c][v] = 1;\n        posByColor[c].push_back(v);\n    }\n\n    // mustKeepAllowed[c] for allowed colors:\n    // keep every allowed cell adjacent to some forbidden-color cell in original\n    vector<vector<int>> mustKeepAllowed(m+1);\n    for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) {\n        int c = a[i][j];\n        if (c == 0 || forbidden[c]) continue;\n        bool ok = false;\n        for (int k = 0; k < 4; k++) {\n            int ni = i + DIRS[k][0], nj = j + DIRS[k][1];\n            if (ni < 0 || ni >= n || nj < 0 || nj >= n) continue;\n            int cc = a[ni][nj];\n            if (cc != 0 && forbidden[cc]) { ok = true; break; }\n        }\n        if (ok) mustKeepAllowed[c].push_back(id(i,j));\n    }\n\n    // representative edges for allowed-allowed adjacencies: store endpoint pair for each adjacency between colors in original\n    vector<vector<vector<pair<int,int>>>> repEdges(m+1, vector<vector<pair<int,int>>>(m+1));\n    for (int i = 0; i < n; i++) for (int j = 0; j+1 < n; j++) {\n        int u = a[i][j], v = a[i][j+1];\n        if (u == 0 || v == 0) continue;\n        if (u == v) continue;\n        if (forbidden[u] || forbidden[v]) continue;\n        int x = min(u,v), y = max(u,v);\n        int id_x = (u == x) ? id(i,j) : id(i,j+1);\n        int id_y = (u == x) ? id(i,j+1) : id(i,j);\n        repEdges[x][y].push_back({id_x, id_y});\n    }\n    for (int i = 0; i+1 < n; i++) for (int j = 0; j < n; j++) {\n        int u = a[i][j], v = a[i+1][j];\n        if (u == 0 || v == 0) continue;\n        if (u == v) continue;\n        if (forbidden[u] || forbidden[v]) continue;\n        int x = min(u,v), y = max(u,v);\n        int id_x = (u == x) ? id(i,j) : id(i+1,j);\n        int id_y = (u == x) ? id(i+1,j) : id(i,j);\n        repEdges[x][y].push_back({id_x, id_y});\n    }\n\n    // list of allowed-allowed adjacent color pairs present in original\n    vector<pair<int,int>> allowedAdjPairs;\n    for (int x = 1; x <= m; x++) if (!forbidden[x]) {\n        for (int y = x+1; y <= m; y++) if (!forbidden[y]) {\n            if (adjOrig[x][y] && !repEdges[x][y].empty()) allowedAdjPairs.push_back({x,y});\n        }\n    }\n\n    // Precompute distToMustKeep and distToBoundary for allowed colors\n    vector<vector<int>> distToMustKeep(m+1, vector<int>(N, -1));\n    vector<vector<int>> distToBoundary(m+1, vector<int>(N, -1));\n\n    auto bfsMultiSource = [&](int c, const vector<int>& sources, vector<int>& distOut) {\n        fill(distOut.begin(), distOut.end(), -1);\n        queue<int> q;\n        for (int s : sources) {\n            if (!isColor[c][s]) continue;\n            distOut[s] = 0;\n            q.push(s);\n        }\n        while(!q.empty()){\n            int v = q.front(); q.pop();\n            auto [i,j] = ij(v);\n            for (int k = 0; k < 4; k++) {\n                int u = nb[v][k];\n                if (u == -1) continue;\n                if (!isColor[c][u]) continue;\n                if (distOut[u] != -1) continue;\n                distOut[u] = distOut[v] + 1;\n                q.push(u);\n            }\n        }\n    };\n\n    for (int c = 1; c <= m; c++) if (!forbidden[c]) {\n        if (!mustKeepAllowed[c].empty())\n            bfsMultiSource(c, mustKeepAllowed[c], distToMustKeep[c]);\n        if (!boundaryCells[c].empty())\n            bfsMultiSource(c, boundaryCells[c], distToBoundary[c]);\n    }\n\n    // RNG\n    mt19937_64 rng((uint64_t)chrono::high_resolution_clock::now().time_since_epoch().count());\n    auto rndInt = [&](int bound)->int { return (int)(rng() % (uint64_t)bound); };\n\n    // BFS distance within original color c\n    auto bfsDistWithinColor = [&](int c, int s, vector<int>& distOut) {\n        fill(distOut.begin(), distOut.end(), -1);\n        queue<int> q;\n        distOut[s] = 0;\n        q.push(s);\n        while(!q.empty()){\n            int v = q.front(); q.pop();\n            for (int k = 0; k < 4; k++) {\n                int u = nb[v][k];\n                if (u == -1) continue;\n                if (!isColor[c][u]) continue;\n                if (distOut[u] != -1) continue;\n                distOut[u] = distOut[v] + 1;\n                q.push(u);\n            }\n        }\n    };\n\n    // BFS shortest path within original color c from s to t; mark union along ONE shortest path found by BFS parents\n    auto bfsPathMark = [&](int c, int s, int t, vector<unsigned char>& keepMask) {\n        vector<int> parent(N, -1);\n        queue<int> q;\n        parent[s] = s;\n        q.push(s);\n        while(!q.empty()){\n            int v = q.front(); q.pop();\n            if (v == t) break;\n            for (int k = 0; k < 4; k++) {\n                int u = nb[v][k];\n                if (u == -1) continue;\n                if (!isColor[c][u]) continue;\n                if (parent[u] != -1) continue;\n                parent[u] = v;\n                q.push(u);\n            }\n        }\n        if (parent[t] == -1) return;\n        int cur = t;\n        while(true){\n            keepMask[cur] = 1;\n            if (cur == s) break;\n            cur = parent[cur];\n            if (cur == -1) break;\n        }\n    };\n\n    // Connectivity repair: connect components of color c in current b using MST over component reps (keep previous working logic)\n    // (We focus improvements on Steiner stage.)\n    auto connectColorMST = [&](vector<vector<int>>& b, int c) {\n        vector<unsigned char> vis(N, 0);\n        vector<int> compReps;\n        queue<int> q;\n\n        for (int v : posByColor[c]) {\n            if (b[v/n][v%n] != c) continue;\n            if (vis[v]) continue;\n            vis[v] = 1;\n            compReps.push_back(v);\n            q.push(v);\n            while(!q.empty()){\n                int cur = q.front(); q.pop();\n                for (int k = 0; k < 4; k++) {\n                    int u = nb[cur][k];\n                    if (u == -1) continue;\n                    if (vis[u]) continue;\n                    if (b[u/n][u%n] != c) continue;\n                    vis[u] = 1;\n                    q.push(u);\n                }\n            }\n        }\n        int k = (int)compReps.size();\n        if (k <= 1) return;\n\n        // compute distances between reps via BFS each time\n        vector<int> dist(N);\n        vector<vector<int>> distMat(k, vector<int>(k, -1));\n        for (int i = 0; i < k; i++) {\n            bfsDistWithinColor(c, compReps[i], dist);\n            for (int j = 0; j < k; j++) distMat[i][j] = dist[compReps[j]];\n        }\n\n        // Prim MST on component reps\n        vector<int> key(k, INT_MAX), parent(k, -1);\n        vector<unsigned char> used(k, 0);\n        int root = rndInt(k);\n        key[root] = 0;\n\n        for (int it = 0; it < k; it++) {\n            int v = -1;\n            for (int i = 0; i < k; i++) if (!used[i] && (v==-1 || key[i] < key[v])) v = i;\n            used[v] = 1;\n            for (int u = 0; u < k; u++) if (!used[u]) {\n                int w = distMat[v][u];\n                if (w >= 0 && w < key[u]) {\n                    key[u] = w;\n                    parent[u] = v;\n                }\n            }\n        }\n\n        // keep all already-colored-c cells\n        vector<unsigned char> keepMask(N, 0);\n        for (int v : posByColor[c]) if (b[v/n][v%n] == c) keepMask[v] = 1;\n\n        // add shortest paths along MST edges\n        for (int i = 0; i < k; i++) if (i != root) {\n            int p = parent[i];\n            if (p < 0) continue;\n            bfsPathMark(c, compReps[p], compReps[i], keepMask);\n        }\n\n        for (int v = 0; v < N; v++) if (keepMask[v]) b[v/n][v%n] = c;\n    };\n\n    // Improved Steiner construction for allowed color:\n    // incremental Prim-like Steiner where sources are vertices already connected to the current tree.\n    auto buildSteinerIncremental = [&](vector<vector<int>>& b, int c, const vector<int>& terminals, int rootCompIdx) {\n        if (terminals.empty()) return;\n\n        // Determine terminal components under adjacency of terminal vertices only\n        vector<unsigned char> isTerm(N, 0), seenTerm(N, 0);\n        for (int t : terminals) isTerm[t] = 1;\n\n        vector<vector<int>> compTerms;\n        vector<int> compRep; // representative vertex per component\n\n        for (int t : terminals) {\n            if (seenTerm[t]) continue;\n            seenTerm[t] = 1;\n            vector<int> comp;\n            queue<int> q;\n            q.push(t);\n            comp.push_back(t);\n            while(!q.empty()){\n                int v = q.front(); q.pop();\n                for (int k = 0; k < 4; k++) {\n                    int u = nb[v][k];\n                    if (u == -1) continue;\n                    if (!isTerm[u]) continue;\n                    if (seenTerm[u]) continue;\n                    seenTerm[u] = 1;\n                    q.push(u);\n                    comp.push_back(u);\n                }\n            }\n            compRep.push_back(comp[0]);\n            compTerms.push_back(std::move(comp));\n        }\n\n        int K = (int)compTerms.size();\n        if (K <= 1) {\n            // just set all terminals\n            for (int t : terminals) b[t/n][t%n] = c;\n            return;\n        }\n\n        vector<unsigned char> keepMask(N, 0);\n        for (int t : terminals) keepMask[t] = 1; // terminals always kept\n\n        vector<unsigned char> inTree(N, 0);\n        vector<unsigned char> compConnected(K, 0);\n        if (rootCompIdx < 0) rootCompIdx = rndInt(K);\n\n        // init: connected subset = terminals of root component\n        compConnected[rootCompIdx] = 1;\n        for (int t : compTerms[rootCompIdx]) inTree[t] = 1;\n\n        int connectedCount = 1;\n\n        vector<int> dist(N, -1), parent(N, -1);\n        queue<int> q;\n\n        while (connectedCount < K) {\n            // multi-source BFS from current inTree vertices within original color c\n            fill(dist.begin(), dist.end(), -1);\n            fill(parent.begin(), parent.end(), -1);\n            while(!q.empty()) q.pop();\n\n            for (int v = 0; v < N; v++) {\n                if (inTree[v] && isColor[c][v]) {\n                    dist[v] = 0;\n                    parent[v] = -1; // source\n                    q.push(v);\n                }\n            }\n\n            while(!q.empty()){\n                int v = q.front(); q.pop();\n                for (int k = 0; k < 4; k++) {\n                    int u = nb[v][k];\n                    if (u == -1) continue;\n                    if (!isColor[c][u]) continue;\n                    if (dist[u] != -1) continue;\n                    dist[u] = dist[v] + 1;\n                    parent[u] = v;\n                    q.push(u);\n                }\n            }\n\n            // select nearest not-yet-connected terminal component rep\n            int bestComp = -1;\n            int bestD = INT_MAX;\n            for (int comp = 0; comp < K; comp++) if (!compConnected[comp]) {\n                int r = compRep[comp];\n                int d = dist[r];\n                if (d != -1 && d < bestD) {\n                    bestD = d;\n                    bestComp = comp;\n                }\n            }\n            if (bestComp == -1) {\n                // fallback: star from root component representative\n                int rootV = compRep[rootCompIdx];\n                vector<unsigned char> tmpKeep = keepMask;\n                for (int comp = 0; comp < K; comp++) if (!compConnected[comp]) {\n                    bfsPathMark(c, rootV, compRep[comp], tmpKeep);\n                }\n                for (int v = 0; v < N; v++) if (tmpKeep[v]) b[v/n][v%n] = c;\n                return;\n            }\n\n            // connect bestComp rep to the inTree via shortest path using parent pointers\n            int cur = compRep[bestComp];\n            while(!inTree[cur]) {\n                keepMask[cur] = 1;\n                inTree[cur] = 1;\n                int p = parent[cur];\n                if (p == -1) break;\n                cur = p;\n            }\n\n            // mark terminals of this component as inTree (now connected)\n            compConnected[bestComp] = 1;\n            connectedCount++;\n            for (int t : compTerms[bestComp]) inTree[t] = 1;\n        }\n\n        // apply keepMask to b\n        for (int v = 0; v < N; v++) if (keepMask[v]) b[v/n][v%n] = c;\n    };\n\n    auto getScoreDist = [&](int c, int v) -> int {\n        int d = distToMustKeep[c][v];\n        if (d >= 0) return d;\n        return distToBoundary[c][v]; // may be 0.. or -1, but boundary BFS should make it reachable for in-region cells\n    };\n\n    auto checkAll = [&](const vector<vector<int>>& b) -> bool {\n        // ward connectivity for colors 1..m\n        vector<unsigned char> vis(N, 0);\n        queue<int> q;\n        for (int c = 1; c <= m; c++) {\n            int start = -1, tot = 0;\n            for (int v : posByColor[c]) {\n                if (b[v/n][v%n] == c) {\n                    tot++;\n                    if (start == -1) start = v;\n                }\n            }\n            if (tot == 0) return false;\n            fill(vis.begin(), vis.end(), 0);\n            while(!q.empty()) q.pop();\n            vis[start] = 1;\n            q.push(start);\n            int cnt = 1;\n            while(!q.empty()){\n                int cur = q.front(); q.pop();\n                for (int k = 0; k < 4; k++) {\n                    int u = nb[cur][k];\n                    if (u == -1) continue;\n                    if (vis[u]) continue;\n                    if (b[u/n][u%n] != c) continue;\n                    vis[u] = 1;\n                    q.push(u);\n                    cnt++;\n                }\n            }\n            if (cnt != tot) return false;\n        }\n\n        // 0 connectivity via outside\n        int N2 = n + 2;\n        auto idExt = [&](int x, int y){ return x*N2 + y; };\n        vector<unsigned char> vis0(N2*N2, 0);\n        queue<pair<int,int>> q0;\n        vis0[idExt(0,0)] = 1;\n        q0.push({0,0});\n        while(!q0.empty()){\n            auto [x,y] = q0.front(); q0.pop();\n            for (int k = 0; k < 4; k++) {\n                int nx = x + DIRS[k][0], ny = y + DIRS[k][1];\n                if (nx < 0 || nx >= N2 || ny < 0 || ny >= N2) continue;\n                bool pass;\n                if (nx==0 || nx==N2-1 || ny==0 || ny==N2-1) pass = true;\n                else pass = (b[nx-1][ny-1] == 0);\n                if (!pass) continue;\n                int nid = idExt(nx,ny);\n                if (vis0[nid]) continue;\n                vis0[nid] = 1;\n                q0.push({nx,ny});\n            }\n        }\n        for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) {\n            if (b[i][j] == 0) {\n                if (!vis0[idExt(i+1,j+1)]) return false;\n            }\n        }\n\n        // adjacency equivalence\n        vector<vector<unsigned char>> adjOut(m+1, vector<unsigned char>(m+1, 0));\n        for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) {\n            int c1 = b[i][j];\n            for (int k = 0; k < 4; k++) {\n                int ni = i + DIRS[k][0], nj = j + DIRS[k][1];\n                int c2 = (ni < 0 || ni >= n || nj < 0 || nj >= n) ? 0 : b[ni][nj];\n                if (c1 == c2) continue;\n                int x = min(c1,c2), y = max(c1,c2);\n                adjOut[x][y] = 1;\n            }\n        }\n        for (int x = 0; x <= m; x++) for (int y = x+1; y <= m; y++) {\n            if (adjOut[x][y] != adjOrig[x][y]) return false;\n        }\n        return true;\n    };\n\n    auto countZeros = [&](const vector<vector<int>>& b) -> int {\n        int z = 0;\n        for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) if (b[i][j] == 0) z++;\n        return z;\n    };\n\n    vector<vector<int>> best = a;\n    int bestZero = -1;\n\n    auto startTime = chrono::high_resolution_clock::now();\n    int T = 26;\n\n    for (int trial = 0; trial < T; trial++) {\n        double elapsed = chrono::duration<double>(chrono::high_resolution_clock::now() - startTime).count();\n        if (elapsed > 1.95) break;\n\n        vector<vector<int>> b(n, vector<int>(n, 0));\n        for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) {\n            int c = a[i][j];\n            if (forbidden[c]) b[i][j] = c;\n        }\n\n        // terminals per allowed color\n        vector<vector<int>> terminals(m+1);\n        vector<vector<unsigned char>> marked(m+1, vector<unsigned char>(N, 0));\n\n        bool ok = true;\n\n        // mustKeepAllowed terminals + choose a boundary seed (best by getScoreDist)\n        for (int c = 1; c <= m; c++) if (!forbidden[c]) {\n            for (int v : mustKeepAllowed[c]) {\n                if (!marked[c][v]) {\n                    marked[c][v] = 1;\n                    terminals[c].push_back(v);\n                }\n            }\n            if (boundaryCells[c].empty()) { ok = false; break; }\n\n            int chosen = -1;\n            int bestD = INT_MAX;\n            for (int bd : boundaryCells[c]) {\n                int d = getScoreDist(c, bd);\n                if (d < bestD) { bestD = d; chosen = bd; }\n            }\n            if (chosen == -1) chosen = boundaryCells[c][rndInt((int)boundaryCells[c].size())];\n\n            if (!marked[c][chosen]) {\n                marked[c][chosen] = 1;\n                terminals[c].push_back(chosen);\n            }\n\n            if (terminals[c].empty()) { ok = false; break; }\n        }\n        if (!ok) continue;\n\n        // choose representative endpoints for each allowed-adjacent pair, biased by distance-to-mandatory/boundary\n        const int DELTA = 2;\n        for (auto [x,y] : allowedAdjPairs) {\n            auto &vec = repEdges[x][y];\n            if (vec.empty()) continue;\n\n            int bestScore = INT_MAX;\n            vector<pair<int,int>> cand;\n            for (auto &e : vec) {\n                int sx = e.first, sy = e.second;\n                int dx = getScoreDist(x, sx);\n                int dy = getScoreDist(y, sy);\n                if (dx < 0 || dy < 0) continue;\n                int sc = dx + dy;\n                if (sc < bestScore) {\n                    bestScore = sc;\n                    cand.clear();\n                    cand.push_back(e);\n                } else if (sc <= bestScore + DELTA) {\n                    cand.push_back(e);\n                }\n            }\n            if (cand.empty()) cand = vec;\n            auto chosenEdge = cand[rndInt((int)cand.size())];\n\n            int sx = chosenEdge.first;\n            int sy = chosenEdge.second;\n            if (!marked[x][sx]) { marked[x][sx] = 1; terminals[x].push_back(sx); }\n            if (!marked[y][sy]) { marked[y][sy] = 1; terminals[y].push_back(sy); }\n        }\n\n        // Build Steiner for each allowed color (incremental Prim-like)\n        for (int c = 1; c <= m; c++) if (!forbidden[c]) {\n            if (terminals[c].empty()) { ok = false; break; }\n            int rootCompIdx = -1; // random inside\n            buildSteinerIncremental(b, c, terminals[c], rootCompIdx);\n        }\n        if (!ok) continue;\n\n        // 0 connectivity repair loop and reconnect affected components\n        for (int iter = 0; iter < 12; iter++) {\n            int N2 = n + 2;\n            auto idExt = [&](int x, int y){ return x*N2 + y; };\n            vector<unsigned char> vis0(N2*N2, 0);\n            queue<pair<int,int>> q0;\n            vis0[idExt(0,0)] = 1;\n            q0.push({0,0});\n            while(!q0.empty()){\n                auto [x,y] = q0.front(); q0.pop();\n                for (int k = 0; k < 4; k++) {\n                    int nx = x + DIRS[k][0], ny = y + DIRS[k][1];\n                    if (nx < 0 || nx >= N2 || ny < 0 || ny >= N2) continue;\n                    bool pass;\n                    if (nx==0 || nx==N2-1 || ny==0 || ny==N2-1) pass = true;\n                    else pass = (b[nx-1][ny-1] == 0);\n                    if (!pass) continue;\n                    int nid = idExt(nx,ny);\n                    if (vis0[nid]) continue;\n                    vis0[nid] = 1;\n                    q0.push({nx,ny});\n                }\n            }\n\n            vector<unsigned char> changed(m+1, 0);\n            bool anyHole = false;\n            for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) {\n                if (b[i][j] == 0 && !vis0[idExt(i+1,j+1)]) {\n                    anyHole = true;\n                    int origColor = a[i][j];\n                    b[i][j] = origColor;\n                    if (!forbidden[origColor]) changed[origColor] = 1;\n                }\n            }\n            if (!anyHole) break;\n            for (int c = 1; c <= m; c++) if (changed[c]) connectColorMST(b, c);\n        }\n\n        if (!checkAll(b)) continue;\n\n        int z = countZeros(b);\n        if (z > bestZero) {\n            bestZero = z;\n            best = std::move(b);\n        }\n    }\n\n    if (bestZero < 0) best = a;\n\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            if (j) cout << ' ';\n            cout << best[i][j];\n        }\n        cout << '\\n';\n    }\n    return 0;\n}","ahc025":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Judge {\n    int N, D, Q;\n    int used = 0;\n    vector<vector<int8_t>> memo; // 2=unknown, -1/0/+1 known for singleton i vs j\n\n    Judge(int n, int d, int q) : N(n), D(d), Q(q) {\n        memo.assign(N, vector<int8_t>(N, 2));\n    }\n\n    int doQuery(const vector<int>& L, const vector<int>& R) {\n        // L and R must be non-empty, disjoint\n        used++;\n        cout << (int)L.size() << ' ' << (int)R.size();\n        for (int x : L) cout << ' ' << x;\n        for (int x : R) cout << ' ' << x;\n        cout << '\\n' << flush;\n\n        string s;\n        cin >> s;\n        char c = s[0];\n        if (c == '<') return -1;\n        if (c == '>') return 1;\n        return 0; // '='\n    }\n\n    int cmpSingleton(int i, int j) {\n        if (i == j) return 0;\n        int8_t &m = memo[i][j];\n        if (m != 2) return (int)m;\n        vector<int> L{ i }, R{ j };\n        int s = doQuery(L, R);\n        m = (int8_t)s;\n        memo[j][i] = (int8_t)(-s);\n        return s;\n    }\n\n    // A and B must be non-empty and disjoint\n    int cmpSets(const vector<int>& A, const vector<int>& B) {\n        if (A.empty() || B.empty()) return 0;\n        return doQuery(A, B);\n    }\n};\n\nstatic int ceil_log2_int(int x) {\n    int b = 0, v = 1;\n    while (v < x) { v <<= 1; b++; }\n    return b;\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    Judge judge(N, D, Q);\n\n    // --- Parameters for estimation from generator distribution ---\n    const double lambda = 1e-5;\n    const double cap = 1e5 * (double)N / (double)D;\n\n    auto estimateFromBucket = [&](int bucket, int Kp) -> double {\n        // bucket in [0..Kp]\n        // Use p=(bucket+0.5)/(Kp+1) as in earlier stable heuristic.\n        double p = (bucket + 0.5) / (double)(Kp + 1);\n        p = min(max(p, 1e-12), 1.0 - 1e-12);\n        double x = -log(1.0 - p) / lambda;\n        x = max(1.0, min(cap, x));\n        return x;\n    };\n\n    // --- Choose Kp under a budget for ordering info ---\n    auto chooseKp = [&]() -> int {\n        long long orderingBudget = (long long)(0.55L * (long long)Q);\n        int maxKp = min(24, N);\n\n        int best = 1;\n        for (int Kp = 1; Kp <= maxKp; Kp++) {\n            long long sortCost = 1LL * Kp * (Kp - 1) / 2; // worst-case insertion sort\n            long long itemCost = 1LL * (N - Kp) * ceil_log2_int(Kp + 1);\n            long long cost = sortCost + itemCost;\n            if (cost <= orderingBudget) best = Kp;\n            else break;\n        }\n        return best;\n    };\n\n    int Kp = chooseKp();\n\n    // --- Pick pivots and sort them by singleton comparisons ---\n    uint64_t seed = 712367821ULL ^ (uint64_t)N * 1000003ULL ^ (uint64_t)D * 9176ULL ^ (uint64_t)Q * 1237ULL;\n    mt19937_64 rng(seed);\n\n    vector<int> ids(N);\n    iota(ids.begin(), ids.end(), 0);\n    shuffle(ids.begin(), ids.end(), rng);\n    vector<int> pivots(ids.begin(), ids.begin() + Kp);\n\n    // insertion sort ascending\n    for (int i = 1; i < Kp; i++) {\n        int j = i;\n        while (j > 0) {\n            int s = judge.cmpSingleton(pivots[j], pivots[j - 1]); // piv[j] ? piv[j-1]\n            if (s == -1) {\n                swap(pivots[j], pivots[j - 1]); // piv[j] < piv[j-1]\n                j--;\n            } else break;\n            if (judge.used >= Q) break;\n        }\n        if (judge.used >= Q) break;\n    }\n\n    vector<int> pivotPos(N, -1);\n    for (int i = 0; i < Kp; i++) pivotPos[pivots[i]] = i;\n\n    // --- Estimate weights by pivot bucketization ---\n    vector<int> bucket(N, Kp / 2);\n    vector<double> w_est(N, 1.0);\n\n    // pivots\n    for (int p : pivots) {\n        int pos = pivotPos[p];\n        bucket[p] = pos;\n        w_est[p] = estimateFromBucket(pos, Kp);\n    }\n\n    // non-pivots: k = #pivots strictly less than item\n    for (int item = 0; item < N; item++) {\n        if (pivotPos[item] != -1) continue;\n\n        int lo = 0, hi = Kp;\n        while (lo < hi && judge.used < Q) {\n            int mid = (lo + hi) / 2;\n            int s = judge.cmpSingleton(item, pivots[mid]); // item ? piv[mid]\n            if (s == 1) lo = mid + 1;\n            else hi = mid;\n        }\n        int k = lo;\n        bucket[item] = k;\n        w_est[item] = estimateFromBucket(k, Kp);\n    }\n\n    // --- Initial partition: LPT (place largest estimated into smallest bin) ---\n    vector<int> order(N);\n    iota(order.begin(), order.end(), 0);\n    sort(order.begin(), order.end(), [&](int a, int b) {\n        if (w_est[a] != w_est[b]) return w_est[a] > w_est[b];\n        return a < b;\n    });\n\n    vector<vector<int>> bins(D);\n    vector<double> binSumEst(D, 0.0);\n    vector<int> d_i(N, 0), posInBin(N, -1);\n\n    for (int x : order) {\n        int best = 0;\n        for (int b = 1; b < D; b++) if (binSumEst[b] < binSumEst[best]) best = b;\n        d_i[x] = best;\n        posInBin[x] = (int)bins[best].size();\n        bins[best].push_back(x);\n        binSumEst[best] += w_est[x];\n    }\n\n    // --- Local refinement ---\n    double totalEst = 0;\n    for (double v : w_est) totalEst += v;\n    double meanEst = totalEst / (double)D;\n\n    auto moveItem = [&](int x, int from, int to) {\n        int idx = posInBin[x];\n        auto &vf = bins[from];\n        int y = vf.back();\n        vf[idx] = y;\n        posInBin[y] = idx;\n        vf.pop_back();\n\n        bins[to].push_back(x);\n        posInBin[x] = (int)bins[to].size() - 1;\n\n        d_i[x] = to;\n        binSumEst[from] -= w_est[x];\n        binSumEst[to] += w_est[x];\n    };\n\n    int maxIters = 0;\n    if (Q > judge.used) maxIters = min(800, Q - judge.used); // 1 query/iter\n    for (int it = 0; it < maxIters && judge.used < Q; it++) {\n        // choose light bin (min estimated sum) among non-empty bins\n        int light = -1;\n        for (int b = 0; b < D; b++) {\n            if (bins[b].empty()) continue;\n            if (light == -1 || binSumEst[b] < binSumEst[light]) light = b;\n        }\n        // choose heavy bin (max estimated sum) among bins with size>=2 (avoid emptying)\n        int heavy = -1;\n        for (int b = 0; b < D; b++) {\n            if ((int)bins[b].size() < 2) continue;\n            if (heavy == -1 || binSumEst[b] > binSumEst[heavy]) heavy = b;\n        }\n        if (light == -1 || heavy == -1) break;\n        if (heavy == light) break;\n\n        // verify direction using one balance query\n        // want heavy.actual >= light.actual\n        int s = judge.cmpSets(bins[heavy], bins[light]);\n        if (s == -1) {\n            // swap roles only if it doesn't break the size>=2 condition\n            if ((int)bins[light].size() >= 2) swap(heavy, light);\n            else break;\n        }\n        if ((int)bins[heavy].size() < 2) break;\n\n        // choose x in heavy that minimizes estimated delta-variance\n        double devH = binSumEst[heavy] - meanEst;\n        double devL = binSumEst[light] - meanEst;\n\n        int bestX = -1;\n        double bestDelta = 0; // we require negative delta (improvement)\n        for (int x : bins[heavy]) {\n            double w = w_est[x];\n            double newDevH = devH - w;\n            double newDevL = devL + w;\n            double oldObj = devH * devH + devL * devL;\n            double newObj = newDevH * newDevH + newDevL * newDevL;\n            double delta = newObj - oldObj;\n\n            if (bestX == -1 || delta < bestDelta) {\n                bestDelta = delta;\n                bestX = x;\n            }\n        }\n\n        if (bestX == -1) break;\n        if (bestDelta >= -1e-9) break; // no estimated improvement\n\n        moveItem(bestX, heavy, light);\n    }\n\n    // --- Use remaining queries (dummy) ---\n    while (judge.used < Q) {\n        // valid disjoint non-empty sets: {0}, {1}\n        int a = 0, b = 1;\n        if (a == b) b = (b + 1) % N;\n        if (b == a) b = (a + 1) % N;\n        vector<int> L{a}, R{b};\n        judge.doQuery(L, R);\n    }\n\n    // --- Output division ---\n    for (int i = 0; i < N; i++) {\n        if (i) cout << ' ';\n        cout << d_i[i];\n    }\n    cout << '\\n' << flush;\n    return 0;\n}","ahc026":"#include <bits/stdc++.h>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int n, m;\n    cin >> n >> m;\n    vector<vector<int>> st(m);\n    for (int i = 0; i < m; i++) {\n        st[i].resize(n / m);\n        for (int j = 0; j < n / m; j++) cin >> st[i][j];\n    }\n\n    vector<int> posStack(n + 1, -1), posIndex(n + 1, -1);\n    for (int i = 0; i < m; i++) {\n        for (int j = 0; j < (int)st[i].size(); j++) {\n            int x = st[i][j];\n            posStack[x] = i;\n            posIndex[x] = j;\n        }\n    }\n\n    vector<pair<int,int>> ops; // (v, i) where i=0 for op2\n    ops.reserve(5000);\n\n    const int INF = 1e9;\n\n    for (int v = 1; v <= n; v++) {\n        int s = posStack[v];\n        int idx = posIndex[v];\n\n        // v is already on top\n        if (idx == (int)st[s].size() - 1) {\n            ops.emplace_back(v, 0);\n            st[s].pop_back();\n            posStack[v] = -1;\n            posIndex[v] = -1;\n            continue;\n        }\n\n        // Need to move the chunk starting from the box immediately above v\n        int u = st[s][idx + 1];\n        vector<int> S(st[s].begin() + (idx + 1), st[s].end()); // moved boxes\n\n        int bestDest = -1;\n        // lexicographic key we construct as tuple<int,int,int>\n        // For inv==0: key = (0, minD, sizeD)  (minD smaller better)\n        // Else:        key = (inv, -minD, sizeD) (minD larger better via -minD)\n        tuple<int,int,int> bestKey;\n\n        for (int d = 0; d < m; d++) if (d != s) {\n            // inversion count between D and S: count pairs (x in D, y in S) with x < y\n            int inv = 0;\n            const auto &D = st[d];\n            for (int x : D) {\n                for (int y : S) {\n                    if (x < y) inv++;\n                }\n            }\n\n            int minD = INF;\n            if (!D.empty()) {\n                minD = *min_element(D.begin(), D.end());\n            }\n\n            int sizeD = (int)D.size();\n\n            tuple<int,int,int> key;\n            if (inv == 0) {\n                // fully safe (or empty destination)\n                key = {0, minD, sizeD};\n            } else {\n                key = {inv, -minD, sizeD};\n            }\n\n            if (bestDest == -1 || key < bestKey) {\n                bestDest = d;\n                bestKey = key;\n            }\n        }\n\n        // Operation 1: move box u (= S[0] bottom) and all above to destination bestDest\n        ops.emplace_back(u, bestDest + 1);\n\n        int startDest = (int)st[bestDest].size();\n        // append S to destination and update positions\n        for (int j = 0; j < (int)S.size(); j++) {\n            int y = S[j];\n            st[bestDest].push_back(y);\n            posStack[y] = bestDest;\n            posIndex[y] = startDest + j;\n        }\n        // remove S from source (suffix after idx)\n        st[s].erase(st[s].begin() + (idx + 1), st[s].end());\n\n        // Now v must be on top of source, carry it out\n        ops.emplace_back(v, 0);\n        st[s].pop_back();\n        posStack[v] = -1;\n        posIndex[v] = -1;\n    }\n\n    // Safety check\n    if ((int)ops.size() > 5000) return 0;\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 RNG {\n    uint64_t x;\n    explicit RNG(uint64_t seed) : x(seed) {}\n    uint64_t next_u64() {\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 next_int(int l, int r) { // inclusive\n        return l + (int)(next_u64() % (uint64_t)(r - l + 1));\n    }\n    double next_double(double l, double r) { // [l, r)\n        long double t = (long double)next_u64() / (long double)numeric_limits<uint64_t>::max();\n        return (double)((long double)l + t * (long double)(r - l));\n    }\n};\n\nstatic inline char dirChar(int N, int a, int b) {\n    int ai = a / N, aj = a % N;\n    int bi = b / N, bj = b % N;\n    if (bi == ai + 1 && bj == aj) return 'D';\n    if (bi == ai - 1 && bj == aj) return 'U';\n    if (bi == ai && bj == aj + 1) return 'R';\n    if (bi == ai && bj == aj - 1) return 'L';\n    return '?';\n}\n\nstruct EvalState {\n    long long numer; // sum_{t=L}^{2L-1} S_t\n    int L;\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(max(0, N - 1));\n    for (int i = 0; i < N - 1; i++) cin >> h[i];\n    vector<string> v(N);\n    for (int i = 0; i < N; i++) cin >> v[i];\n\n    int V = N * N;\n    vector<int> d(V);\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) cin >> d[i * N + j];\n    }\n\n    auto idx = [&](int i, int j) { return i * N + j; };\n    const int root = 0;\n\n    // Build adjacency graph (respecting walls)\n    vector<vector<int>> g(V);\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            int a = idx(i, j);\n            if (i + 1 < N && h[i][j] == '0') {\n                int b = idx(i + 1, j);\n                g[a].push_back(b);\n                g[b].push_back(a);\n            }\n            if (j + 1 < N && v[i][j] == '0') {\n                int b = idx(i, j + 1);\n                g[a].push_back(b);\n                g[b].push_back(a);\n            }\n        }\n    }\n\n    // BFS distances from root\n    vector<int> dist(V, -1);\n    queue<int> q;\n    dist[root] = 0;\n    q.push(root);\n    while (!q.empty()) {\n        int x = q.front(); q.pop();\n        for (int y : g[x]) if (dist[y] == -1) {\n            dist[y] = dist[x] + 1;\n            q.push(y);\n        }\n    }\n\n    // Candidate parents: neighbors with dist-1\n    vector<vector<int>> candParents(V);\n    for (int x = 0; x < V; x++) {\n        if (x == root) continue;\n        int dx = dist[x];\n        for (int y : g[x]) if (dist[y] == dx - 1) candParents[x].push_back(y);\n        if (candParents[x].empty()) candParents[x].push_back(root); // safety\n    }\n\n    vector<int> verts(V);\n    iota(verts.begin(), verts.end(), 0);\n    // deep-to-shallow order for subtree DP\n    sort(verts.begin(), verts.end(), [&](int a, int b) { return dist[a] > dist[b]; });\n\n    long long sum_d = 0;\n    for (int x : d) sum_d += x;\n\n    int L0 = 2 * (V - 1);\n\n    // Fast exact evaluation of average dirtiness:\n    // given pos array of length L (pos[k] = vertex moved into after k+1-th move in the cycle)\n    // compute numer = sum_{t=L}^{2L-1} S_t where S_t = total dirtiness at time t.\n    vector<int> last(V, 0), seen(V, 0);\n    int seen_id = 1;\n\n    auto evalByPos = [&](auto getPos, int L) -> EvalState {\n        // getPos(k) for 0 <= k < L\n        seen_id++;\n        if (seen_id == INT_MAX) {\n            fill(seen.begin(), seen.end(), 0);\n            seen_id = 1;\n        }\n\n        long long numer = 0;\n        long long sum_d_last = 0;\n\n        int T = 2 * L - 1;\n        for (int t = 1; t <= T; t++) {\n            int idxPos = (t - 1) % L;\n            int vv = getPos(idxPos);\n\n            int old = 0;\n            if (seen[vv] == seen_id) old = last[vv];\n            else seen[vv] = seen_id;\n\n            last[vv] = t;\n            sum_d_last += 1LL * d[vv] * (t - old);\n\n            long long S = 1LL * t * sum_d - sum_d_last;\n            if (t >= L) numer += S;\n        }\n        return {numer, L};\n    };\n\n    auto betterAvg = [&](const EvalState& A, const EvalState& B) -> bool {\n        // A.numer/A.L < B.numer/B.L\n        __int128 left = (__int128)A.numer * B.L;\n        __int128 right = (__int128)B.numer * A.L;\n        return left < right;\n    };\n\n    auto buildBase = [&](const vector<int>& parent, vector<vector<int>>& childrenOrder,\n                         vector<int>& basePos, string& baseMoves) {\n        for (int i = 0; i < V; i++) childrenOrder[i].clear();\n\n        for (int x = 0; x < V; x++) if (x != root) {\n            childrenOrder[parent[x]].push_back(x);\n        }\n\n        // already ordered by caller\n        basePos.clear();\n        baseMoves.clear();\n        basePos.reserve(L0);\n        baseMoves.reserve(L0);\n\n        // iterative DFS Euler tour on the tree\n        vector<pair<int,int>> st;\n        st.reserve(V);\n        st.push_back({root, 0});\n\n        while (!st.empty()) {\n            int u = st.back().first;\n            int &it = st.back().second;\n            if (it == (int)childrenOrder[u].size()) {\n                st.pop_back();\n                if (st.empty()) break;\n                int p = parent[u];\n                baseMoves.push_back(dirChar(N, u, p));\n                basePos.push_back(p);\n            } else {\n                int c = childrenOrder[u][it++];\n                baseMoves.push_back(dirChar(N, u, c));\n                basePos.push_back(c);\n                st.push_back({c, 0});\n            }\n        }\n        // basePos.size() should be L0\n        // (tree has V nodes => Euler tour length 2*(V-1))\n    };\n\n    // Random search for best base tree & child order\n    RNG rng((uint64_t)chrono::steady_clock::now().time_since_epoch().count());\n\n    vector<int> parent(V, -1);\n    vector<vector<int>> childrenOrder(V);\n\n    EvalState bestBase{(1LL<<62), L0};\n    vector<int> bestBasePos;\n    string bestBaseMoves;\n    vector<int> bestParent;\n    vector<vector<int>> bestChildrenOrder;\n\n    auto start = chrono::steady_clock::now();\n    double TIME_BASE = 1.25;\n\n    auto chooseParent = [&](int x, double alpha, double greedyProb) {\n        // candParents[x] are all dist-1 neighbors\n        auto &cp = candParents[x];\n        if (cp.empty()) return root;\n        if (rng.next_double(0.0, 1.0) < greedyProb) {\n            int best = cp[0];\n            for (int u : cp) if (d[u] > d[best]) best = u;\n            return best;\n        } else {\n            // weight ~ d[u]^alpha\n            double total = 0;\n            vector<double> w(cp.size());\n            for (int i = 0; i < (int)cp.size(); i++) {\n                w[i] = pow((double)d[cp[i]], alpha);\n                total += w[i];\n            }\n            double r = rng.next_double(0.0, total);\n            for (int i = 0; i < (int)cp.size(); i++) {\n                r -= w[i];\n                if (r <= 0) return cp[i];\n            }\n            return cp.back();\n        }\n    };\n\n    while (true) {\n        double elapsed = chrono::duration<double>(chrono::steady_clock::now() - start).count();\n        if (elapsed > TIME_BASE) break;\n\n        double alpha = rng.next_double(0.6, 2.2);\n        double greedyProb = rng.next_double(0.75, 0.98);\n        int orderType = rng.next_int(0, 2); // 0 subMax, 1 subSum, 2 d(child)\n        bool ascending = rng.next_int(0, 1);\n        double noiseRate = rng.next_double(0.0, 0.28);\n\n        // build parent\n        parent[root] = -1;\n        vector<int> byDistAsc = verts;\n        sort(byDistAsc.begin(), byDistAsc.end(), [&](int a, int b){ return dist[a] < dist[b]; });\n        for (int x : byDistAsc) {\n            if (x == root) continue;\n            parent[x] = chooseParent(x, alpha, greedyProb);\n        }\n\n        // build children lists (unsorted)\n        vector<vector<int>> children(V);\n        for (int i = 0; i < V; i++) children[i].clear();\n        for (int x = 0; x < V; x++) if (x != root) children[parent[x]].push_back(x);\n\n        // subtree DP\n        vector<long long> subMax(V), subSum(V);\n        for (int x : verts) { // deep -> shallow\n            subMax[x] = d[x];\n            subSum[x] = d[x];\n            for (int c : children[x]) {\n                subMax[x] = max(subMax[x], subMax[c]);\n                subSum[x] += subSum[c];\n            }\n        }\n\n        // order children\n        childrenOrder.assign(V, {});\n        for (int u = 0; u < V; u++) {\n            auto &ch = children[u];\n            childrenOrder[u] = ch;\n\n            if (ch.size() <= 1) continue;\n            vector<pair<double,int>> tmp;\n            tmp.reserve(ch.size());\n            for (int c : ch) {\n                double key;\n                if (orderType == 0) key = (double)subMax[c];\n                else if (orderType == 1) key = (double)subSum[c];\n                else key = (double)d[c];\n\n                double sign = rng.next_double(-1.0, 1.0);\n                double adj = key + noiseRate * key * sign;\n                tmp.push_back({adj, c});\n            }\n            sort(tmp.begin(), tmp.end(), [&](auto &A, auto &B) {\n                if (A.first != B.first) return ascending ? (A.first < B.first) : (A.first > B.first);\n                return A.second < B.second;\n            });\n            for (int i = 0; i < (int)ch.size(); i++) childrenOrder[u][i] = tmp[i].second;\n        }\n\n        // build base route\n        vector<int> basePos;\n        string baseMoves;\n        basePos.reserve(L0);\n        baseMoves.reserve(L0);\n\n        buildBase(parent, childrenOrder, basePos, baseMoves);\n        if ((int)basePos.size() != L0) continue; // safety\n\n        auto getPos = [&](int k) -> int { return basePos[k]; };\n        auto val = evalByPos(getPos, L0);\n\n        if (betterAvg(val, bestBase)) {\n            bestBase = val;\n            bestBasePos = std::move(basePos);\n            bestBaseMoves = std::move(baseMoves);\n            bestParent = parent;\n            bestChildrenOrder = childrenOrder;\n        }\n    }\n\n    // Extension search on top edges with consistent evaluation/output\n    int maxLen = 100000;\n    int baseL = L0;\n\n    // compute depth in best base tree\n    vector<int> depthTree(V, 0);\n    vector<int> byDistAsc = verts;\n    sort(byDistAsc.begin(), byDistAsc.end(), [&](int a, int b){ return dist[a] < dist[b]; });\n    depthTree[root] = 0;\n    for (int x : byDistAsc) {\n        if (x == root) continue;\n        depthTree[x] = depthTree[bestParent[x]] + 1;\n    }\n\n    // list undirected edges\n    vector<pair<int,int>> edges;\n    edges.reserve(V * 2);\n    for (int u = 0; u < V; u++) for (int w : g[u]) if (u < w) edges.push_back({u,w});\n\n    // edge ranking by potential shuttle value / overhead\n    struct EdgeCand { double score; int u,v; };\n    vector<EdgeCand> edgeC;\n    edgeC.reserve(edges.size());\n    for (auto [a,b] : edges) {\n        double best = max(\n            (double)(d[a] + d[b]) / (double)(depthTree[a] + depthTree[b] + 1),\n            (double)(d[a] + d[b]) / (double)(depthTree[a] + depthTree[b] + 1)\n        );\n        edgeC.push_back({best, a, b});\n    }\n    sort(edgeC.begin(), edgeC.end(), [&](auto &A, auto &B){ return A.score > B.score; });\n    int TOP_E = min<int>(30, edgeC.size());\n\n    EvalState bestAll = bestBase;\n    string bestAllRoute = bestBaseMoves;\n\n    auto buildChainRootTo = [&](int x) {\n        vector<int> chain;\n        int cur = x;\n        while (cur != root) {\n            chain.push_back(cur);\n            cur = bestParent[cur];\n        }\n        reverse(chain.begin(), chain.end());\n        return chain; // excludes root\n    };\n\n    // Build segment pos for a given s,t,m where:\n    // - start at root, go along tree to s\n    // - shuttle along edge (s,t) for m moves\n    // - then return from current end (depends on parity of m) to root along the tree\n    auto buildSegmentPos = [&](int s, int t, int m, vector<int>& segPos) {\n        segPos.clear();\n        segPos.reserve(depthTree[s] + m + max(depthTree[s], depthTree[t]));\n\n        // root -> s\n        int cur = root;\n        auto chainS = buildChainRootTo(s);\n        for (int nxt : chainS) {\n            segPos.push_back(nxt); // moved into nxt\n            cur = nxt;\n        }\n        // now at s\n        int curV = s;\n        for (int i = 0; i < m; i++) {\n            int nxt = (curV == s ? t : s);\n            segPos.push_back(nxt);\n            curV = nxt;\n        }\n        // return curV -> root via tree parents\n        while (curV != root) {\n            int nxt = bestParent[curV];\n            segPos.push_back(nxt);\n            curV = nxt;\n        }\n    };\n\n    // Evaluate full route consisting of basePos + segPos without allocating combined array.\n    auto evalFull = [&](const vector<int>& segPos) -> EvalState {\n        int segL = (int)segPos.size();\n        int L = baseL + segL;\n\n        auto getPos = [&](int k) -> int {\n            if (k < baseL) return bestBasePos[k];\n            return segPos[k - baseL];\n        };\n        return evalByPos(getPos, L);\n    };\n\n    auto buildSegmentMoves = [&](int s, int t, int m) -> string {\n        string seg;\n        int cur = root;\n\n        auto chainS = buildChainRootTo(s);\n        for (int nxt : chainS) {\n            seg.push_back(dirChar(N, cur, nxt));\n            cur = nxt;\n        }\n        int curV = s;\n        for (int i = 0; i < m; i++) {\n            int nxt = (curV == s ? t : s);\n            seg.push_back(dirChar(N, curV, nxt));\n            curV = nxt;\n        }\n        while (curV != root) {\n            int nxt = bestParent[curV];\n            seg.push_back(dirChar(N, curV, nxt));\n            curV = nxt;\n        }\n        return seg;\n    };\n\n    vector<int> segPos;\n    auto extStart = chrono::steady_clock::now();\n    double TIME_EXT = 0.70;\n\n    // Also consider k=0 already included as bestAll = bestBase\n    for (int ei = 0; ei < TOP_E; ei++) {\n        double elapsed = chrono::duration<double>(chrono::steady_clock::now() - extStart).count();\n        if (elapsed > TIME_EXT) break;\n\n        int u = edgeC[ei].u, vtx = edgeC[ei].v;\n        for (int ori = 0; ori < 2; ori++) {\n            int s = (ori == 0 ? u : vtx);\n            int t = (ori == 0 ? vtx : u);\n\n            // derive max m for even/odd end:\n            // - if m odd => end=t => total segLen = depth[s] + m + depth[t]\n            // - if m even => end=s => total segLen = depth[s] + m + depth[s] = 2*depth[s] + m\n            int oddMax = maxLen - baseL - depthTree[s] - depthTree[t]; // m must be odd and >=1\n            int evenMax = maxLen - baseL - 2 * depthTree[s];            // m must be even and >=2\n\n            vector<int> candidates;\n            auto addIf = [&](int m) {\n                if (m <= 0) return;\n                int end = (m % 2 ? t : s);\n                int segLen = depthTree[s] + m + depthTree[end];\n                if (baseL + segLen <= maxLen) candidates.push_back(m);\n            };\n\n            // near maxima\n            if (oddMax >= 1) {\n                int m = oddMax;\n                if (m % 2 == 0) m--;\n                if (m >= 1) {\n                    addIf(m);\n                    if (m - 2 >= 1) addIf(m - 2);\n                    if (m / 2 >= 1) addIf((m / 2) | 1); // make odd\n                }\n            }\n            if (evenMax >= 2) {\n                int m = evenMax;\n                if (m % 2 == 1) m--;\n                if (m >= 2) {\n                    addIf(m);\n                    if (m - 2 >= 2) addIf(m - 2);\n                    if (m / 2 >= 2) addIf((m / 2) & ~1); // make even\n                }\n            }\n\n            // small shuttles sometimes help\n            addIf(1);\n            addIf(2);\n            addIf(3);\n            addIf(4);\n\n            sort(candidates.begin(), candidates.end());\n            candidates.erase(unique(candidates.begin(), candidates.end()), candidates.end());\n\n            for (int m : candidates) {\n                // build segment pos\n                buildSegmentPos(s, t, m, segPos);\n                if ((int)segPos.size() + baseL > maxLen) continue;\n\n                auto val = evalFull(segPos);\n                if (betterAvg(val, bestAll)) {\n                    bestAll = val;\n                    bestAllRoute = bestBaseMoves + buildSegmentMoves(s, t, m);\n                }\n            }\n        }\n    }\n\n    // Output best route\n    cout << bestAllRoute << \"\\n\";\n    return 0;\n}","ahc028":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M;\n    cin >> N >> M;\n\n    int si, sj;\n    cin >> si >> sj;\n\n    vector<string> grid(N);\n    for (int i = 0; i < N; i++) cin >> grid[i];\n\n    vector<string> t(M);\n    for (int k = 0; k < M; k++) cin >> t[k];\n\n    auto idxOf = [N](int r, int c) { return r * N + c; };\n    auto coordOf = [N](int id) { return pair<int,int>{id / N, id % N}; };\n\n    int C = N * N;\n    int startCell = idxOf(si, sj);\n\n    vector<vector<int>> posByLetter(26);\n    for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) {\n        int a = grid[i][j] - 'A';\n        posByLetter[a].push_back(idxOf(i, j));\n    }\n\n    // dist between any two cells\n    vector<vector<int>> distCell(C, vector<int>(C, 0));\n    for (int a = 0; a < C; a++) {\n        auto [ar, ac] = coordOf(a);\n        for (int b = a; b < C; b++) {\n            auto [br, bc] = coordOf(b);\n            int d = abs(ar - br) + abs(ac - bc);\n            distCell[a][b] = distCell[b][a] = d;\n        }\n    }\n\n    // min dist from a cell to ANY cell containing given letter\n    vector<vector<int>> distCellToLetter(C, vector<int>(26, INT_MAX/4));\n    for (int p = 0; p < C; p++) {\n        for (int l = 0; l < 26; l++) {\n            int best = INT_MAX/4;\n            for (int q : posByLetter[l]) best = min(best, distCell[p][q]);\n            distCellToLetter[p][l] = best;\n        }\n    }\n\n    // min distance between any cell containing letter x and any cell containing y\n    vector<vector<int>> distLetter(26, vector<int>(26, INT_MAX/4));\n    for (int x = 0; x < 26; x++) for (int y = 0; y < 26; y++) {\n        int best = INT_MAX/4;\n        for (int p : posByLetter[x]) {\n            for (int q : posByLetter[y]) best = min(best, distCell[p][q]);\n        }\n        distLetter[x][y] = best;\n    }\n\n    vector<int> st(M), en(M);\n    for (int i = 0; i < M; i++) {\n        st[i] = t[i][0] - 'A';\n        en[i] = t[i][4] - 'A';\n    }\n\n    // overlapLen[i][j]: maximum r (0..4) such that suffix(t[i], r) == prefix(t[j], r)\n    vector<vector<uint8_t>> overlapLen(M, vector<uint8_t>(M, 0));\n    for (int i = 0; i < M; i++) for (int j = 0; j < M; j++) if (i != j) {\n        uint8_t best = 0;\n        for (int r = 4; r >= 0; r--) {\n            bool ok = true;\n            for (int k = 0; k < r; k++) {\n                if (t[i][5 - r + k] != t[j][k]) { ok = false; break; }\n            }\n            if (ok) { best = (uint8_t)r; break; }\n        }\n        overlapLen[i][j] = best;\n    }\n\n    vector<uint8_t> maxOverlapFrom(M, 0);\n    for (int i = 0; i < M; i++) {\n        uint8_t mx = 0;\n        for (int j = 0; j < M; j++) if (i != j) mx = max(mx, overlapLen[i][j]);\n        maxOverlapFrom[i] = mx;\n    }\n\n    // Build merged letter sequence from an order using overlaps.\n    auto buildSeq = [&](const vector<int>& order) -> vector<char> {\n        vector<char> seq;\n        seq.reserve(5 * M);\n        auto addStringFrom = [&](int idx, int fromPos) {\n            for (int p = fromPos; p < 5; p++) seq.push_back(t[idx][p]);\n        };\n        addStringFrom(order[0], 0);\n        for (int i = 1; i < M; i++) {\n            int prev = order[i-1], cur = order[i];\n            int r = overlapLen[prev][cur];\n            addStringFrom(cur, r);\n        }\n        return seq;\n    };\n\n    // Beam search simulation: minimize cost for the fixed letter sequence.\n    auto simulateBeam = [&](const vector<int>& order) -> pair<ll, vector<pair<int,int>>> {\n        vector<char> seq = buildSeq(order);\n        int L = (int)seq.size();\n\n        // beam width (small enough for speed, large enough to improve)\n        const int BEAM = 28;\n\n        vector<vector<int>> cellsAt(L);\n        vector<vector<int>> parentAt(L);\n        vector<vector<ll>> costAt(L);\n\n        // position 0\n        int l0 = seq[0] - 'A';\n        const vector<int>& cand0 = posByLetter[l0];\n\n        vector<tuple<ll,int,int>> vec; // cost, cell, parentIdx(-1)\n        vec.reserve(cand0.size());\n        for (int c : cand0) {\n            ll cost = (ll)distCell[startCell][c] + 1;\n            vec.emplace_back(cost, c, -1);\n        }\n        nth_element(vec.begin(), vec.begin() + min((int)vec.size(), BEAM) - 1, vec.end(),\n                    [](auto &a, auto &b){ return get<0>(a) < get<0>(b); });\n        int take0 = min((int)vec.size(), BEAM);\n        vec.resize(take0);\n        sort(vec.begin(), vec.end(), [](auto &a, auto &b){ return get<0>(a) < get<0>(b); });\n\n        cellsAt[0].resize(take0);\n        parentAt[0].assign(take0, -1);\n        costAt[0].resize(take0);\n        for (int i = 0; i < take0; i++) {\n            cellsAt[0][i] = get<1>(vec[i]);\n            costAt[0][i] = get<0>(vec[i]);\n        }\n\n        // forward DP\n        for (int pos = 1; pos < L; pos++) {\n            int l = seq[pos] - 'A';\n            const vector<int>& cand = posByLetter[l];\n\n            const auto &prevCells = cellsAt[pos-1];\n            const auto &prevCosts = costAt[pos-1];\n            int prevSz = (int)prevCells.size();\n\n            // compute best transition into each candidate cell\n            vector<tuple<ll,int,int>> bestForCand; // cost, cell, parentIdx\n            bestForCand.reserve(cand.size());\n\n            for (int c : cand) {\n                ll best = (1LL<<62);\n                int bestParent = -1;\n                // min over beam states\n                for (int pi = 0; pi < prevSz; pi++) {\n                    ll v = prevCosts[pi] + (ll)distCell[prevCells[pi]][c] + 1;\n                    if (v < best) {\n                        best = v;\n                        bestParent = pi;\n                    }\n                }\n                bestForCand.emplace_back(best, c, bestParent);\n            }\n\n            int take = min((int)bestForCand.size(), BEAM);\n            // select top-k by cost\n            nth_element(bestForCand.begin(), bestForCand.begin() + take - 1, bestForCand.end(),\n                        [](auto &a, auto &b){ return get<0>(a) < get<0>(b); });\n            bestForCand.resize(take);\n            sort(bestForCand.begin(), bestForCand.end(), [](auto &a, auto &b){ return get<0>(a) < get<0>(b); });\n\n            cellsAt[pos].resize(take);\n            parentAt[pos].resize(take);\n            costAt[pos].resize(take);\n            for (int i = 0; i < take; i++) {\n                cellsAt[pos][i] = get<1>(bestForCand[i]);\n                parentAt[pos][i] = get<2>(bestForCand[i]);\n                costAt[pos][i] = get<0>(bestForCand[i]);\n            }\n        }\n\n        // choose best end\n        int idx = (int)(min_element(costAt[L-1].begin(), costAt[L-1].end()) - costAt[L-1].begin());\n        ll bestCost = costAt[L-1][idx];\n\n        // reconstruct chosen cells\n        vector<int> chosenCells(L);\n        int curIdx = idx;\n        for (int pos = L-1; pos >= 0; pos--) {\n            chosenCells[pos] = cellsAt[pos][curIdx];\n            curIdx = parentAt[pos][curIdx];\n            if (pos == 0) break;\n        }\n\n        vector<pair<int,int>> ops;\n        ops.reserve(L);\n        for (int pos = 0; pos < L; pos++) ops.push_back(coordOf(chosenCells[pos]));\n        return {bestCost, ops};\n    };\n\n    // Candidate starting strings: use a slightly deeper proxy (first+second letter)\n    vector<pair<int,int>> startCand; // (proxy, idx)\n    startCand.reserve(M);\n    for (int i = 0; i < M; i++) {\n        int lStart = st[i];\n        int lSecond = t[i][1] - 'A';\n\n        ll proxy = (1LL<<62);\n        for (int c : posByLetter[lStart]) {\n            // move to c for first char, then minimal move to any cell of second char\n            ll v = distCell[startCell][c] + (ll)distCellToLetter[c][lSecond] + 1;\n            proxy = min(proxy, v);\n        }\n        startCand.push_back({(int)min<ll>(proxy, INT_MAX), i});\n    }\n    sort(startCand.begin(), startCand.end());\n\n    // More restarts but still bounded by time\n    int RESTARTS = 10;\n\n    // Random tie-breaking helper\n    std::mt19937 rng(712367);\n\n    ll bestCost = (1LL<<62);\n    vector<pair<int,int>> bestOps;\n\n    for (int rep = 0; rep < RESTARTS; rep++) {\n        int startIdx = startCand[rep].second;\n\n        vector<int> order;\n        order.reserve(M);\n\n        vector<char> used(M, 0);\n        order.push_back(startIdx);\n        used[startIdx] = 1;\n\n        int cur = startIdx;\n\n        for (int step = 1; step < M; step++) {\n            int bestR = -1;\n            int bestMx = -1;\n            int bestD = INT_MAX;\n\n            // First gather best by lexicographic-like criteria:\n            // 1) overlapLen[cur][j] (higher better)\n            // 2) dist between letters en[cur] -> st[j] (lower better)\n            // 3) maxOverlapFrom[j] (higher better)\n            vector<int> cand;\n            for (int j = 0; j < M; j++) if (!used[j]) {\n                int r = overlapLen[cur][j];\n                int d = distLetter[en[cur]][st[j]];\n                int mx = (int)maxOverlapFrom[j];\n                if (r > bestR ||\n                    (r == bestR && d < bestD) ||\n                    (r == bestR && d == bestD && mx > bestMx)) {\n                    bestR = r; bestD = d; bestMx = mx;\n                    cand.clear();\n                    cand.push_back(j);\n                } else if (r == bestR && d == bestD && mx == bestMx) {\n                    cand.push_back(j);\n                }\n            }\n\n            // Randomly pick among equally good candidates to diversify\n            int pick = cand.empty() ? -1 : cand[rng() % cand.size()];\n            used[pick] = 1;\n            order.push_back(pick);\n            cur = pick;\n        }\n\n        auto [cost, ops] = simulateBeam(order);\n        if ((int)ops.size() > 5000) continue; // safety\n        if (cost < bestCost) {\n            bestCost = cost;\n            bestOps = std::move(ops);\n        }\n    }\n\n    for (auto [i, j] : bestOps) cout << i << ' ' << j << '\\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    long double eps;\n    if (!(cin >> N >> M >> eps)) return 0;\n\n    long long totalOil = 0;\n    for (int k = 0; k < M; k++) {\n        int d;\n        cin >> d;\n        totalOil += d;\n        for (int t = 0; t < d; t++) {\n            int i, j;\n            cin >> i >> j; // shape coords, ignore\n        }\n    }\n\n    auto drill_query = [&](int i, int j) -> long long {\n        cout << \"q 1 \" << i << \" \" << j << \"\\n\";\n        cout.flush();\n        long long v;\n        cin >> v;\n        return v;\n    };\n\n    auto div_query_2x2 = [&](int i0, int j0) -> long long {\n        cout << \"q 4 \"\n             << i0 << \" \" << j0 << \" \"\n             << i0 + 1 << \" \" << j0 << \" \"\n             << i0 << \" \" << j0 + 1 << \" \"\n             << i0 + 1 << \" \" << j0 + 1 << \"\\n\";\n        cout.flush();\n        long long r;\n        cin >> r;\n        return r;\n    };\n\n    const long long NN = 1LL * N * N;\n    long double lambdaCell = (long double)totalOil / (long double)NN;\n\n    // If dense enough, just drill all (avoids divination overhead).\n    if (lambdaCell >= 0.72L) {\n        vector<vector<long long>> val(N, vector<long long>(N, 0));\n        long long sumDrilled = 0;\n        for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) {\n            long long v = drill_query(i, j);\n            val[i][j] = v;\n            sumDrilled += v;\n        }\n        vector<pair<int,int>> ans;\n        for (int i = 0; i < N; i++) for (int j = 0; j < N; j++)\n            if (val[i][j] > 0) ans.push_back({i, j});\n        cout << \"a \" << ans.size();\n        for (auto [i,j] : ans) cout << \" \" << i << \" \" << j;\n        cout << \"\\n\";\n        cout.flush();\n        int ok; cin >> ok;\n        return 0;\n    }\n\n    // Choose offsets for 2x2 tilings (adaptive to reduce divination cost).\n    vector<pair<int,int>> offsets;\n\n    if (N % 2 == 0) {\n        // Even N: one tiling already covers all cells.\n        offsets.push_back({0, 0});\n        // Add second tiling only if fairly sparse (to improve ordering).\n        if (lambdaCell < 0.50L) offsets.push_back({1, 1});\n    } else {\n        // Odd N: use 3 offsets to cover borders more robustly.\n        offsets.push_back({0, 0});\n        offsets.push_back({1, 0});\n        offsets.push_back({0, 1});\n        // Optional 4th only when very sparse.\n        if (lambdaCell < 0.35L) offsets.push_back({1, 1});\n    }\n\n    const int k = 4;\n    const long double den = 1.0L - 2.0L * eps; // > 0 for eps <= 0.2\n\n    auto decode_block_sum_linear = [&](long long r) -> long double {\n        // v_block \u2248 (r - k*eps)/den, then clamp\n        long double v_est = ((long double)r - (long double)k * eps) / den;\n        if (v_est < 0) v_est = 0;\n        long double vmax = (long double)k * (long double)M;\n        if (v_est > vmax) v_est = vmax;\n        return v_est;\n    };\n\n    vector<long double> score(NN, 0.0L);\n    vector<int> coverCnt(NN, 0);\n\n    for (auto [si, sj] : offsets) {\n        for (int i0 = si; i0 + 1 < N; i0 += 2) {\n            for (int j0 = sj; j0 + 1 < N; j0 += 2) {\n                long long r = div_query_2x2(i0, j0);\n                long double v_est = decode_block_sum_linear(r);\n                long double perCell = v_est / 4.0L;\n\n                int id00 = i0 * N + j0;\n                int id10 = (i0 + 1) * N + j0;\n                int id01 = i0 * N + (j0 + 1);\n                int id11 = (i0 + 1) * N + (j0 + 1);\n\n                score[id00] += perCell; coverCnt[id00]++;\n                score[id10] += perCell; coverCnt[id10]++;\n                score[id01] += perCell; coverCnt[id01]++;\n                score[id11] += perCell; coverCnt[id11]++;\n            }\n        }\n    }\n\n    // Normalize scores by number of blocks covering each cell.\n    for (int id = 0; id < (int)NN; id++) {\n        if (coverCnt[id] > 0) score[id] /= (long double)coverCnt[id];\n        else score[id] = lambdaCell; // safety fallback\n    }\n\n    // Drill in descending estimated value order.\n    vector<int> order(NN);\n    iota(order.begin(), order.end(), 0);\n    sort(order.begin(), order.end(), [&](int a, int b) {\n        if (score[a] != score[b]) return score[a] > score[b];\n        return a < b;\n    });\n\n    vector<vector<long long>> val(N, vector<long long>(N, -1));\n    long long sumDrilled = 0;\n\n    for (int id : order) {\n        int i = id / N;\n        int j = id % N;\n        if (val[i][j] != -1) continue;\n\n        long long v = drill_query(i, j);\n        val[i][j] = v;\n        sumDrilled += v;\n\n        // Correctness guarantee:\n        // sum of remaining unrevealed cells must be 0 when sumDrilled == totalOil.\n        if (sumDrilled == totalOil) break;\n    }\n\n    vector<pair<int,int>> ans;\n    for (int i = 0; i < N; i++) for (int j = 0; j < N; j++)\n        if (val[i][j] > 0) ans.push_back({i, j});\n\n    cout << \"a \" << ans.size();\n    for (auto [i,j] : ans) cout << \" \" << i << \" \" << j;\n    cout << \"\\n\";\n    cout.flush();\n\n    int ok; cin >> ok;\n    return 0;\n}","ahc031":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const long long INFLL = (1LL << 60);\n\n// Hungarian algorithm (min cost) for square n<=50\n// cost[i][j] : row i -> col j\n// returns minimal total cost\nstatic long long hungarianMinCost(const vector<vector<long long>>& cost) {\n    int n = (int)cost.size();\n    // 1-indexed potentials, p stores matched row for each column\n    vector<long long> u(n + 1, 0), v(n + 1, 0);\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        vector<long long> minv(n + 1, INFLL);\n        vector<char> used(n + 1, false);\n\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 = 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        // augment\n        do {\n            int j1 = way[j0];\n            p[j0] = p[j1];\n            j0 = j1;\n        } while (j0 != 0);\n    }\n\n    // p[j] = row matched to column j. Build min cost.\n    vector<int> matchRow(n, -1);\n    for (int j = 1; j <= n; j++) {\n        int i = p[j];\n        if (i >= 1 && i <= n) matchRow[i - 1] = j - 1;\n    }\n    long long res = 0;\n    for (int i = 0; i < n; i++) res += cost[i][matchRow[i]];\n    return res;\n}\n\n// Hungarian assignment for final output.\n// returns matchRow[k] = strip index for reservation k.\nstatic vector<int> hungarianAssign(const vector<vector<long long>>& cost) {\n    int n = (int)cost.size();\n    vector<long long> u(n + 1, 0), v(n + 1, 0);\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        vector<long long> minv(n + 1, INFLL);\n        vector<char> used(n + 1, false);\n\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 = 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 != 0);\n    }\n\n    vector<int> matchRow(n, -1);\n    for (int j = 1; j <= n; j++) {\n        int i = p[j];\n        matchRow[i - 1] = j - 1;\n    }\n    return matchRow;\n}\n\n// boundaries: prefix sums after each strip except last, strictly increasing\nstatic vector<int> internalBoundaries(const vector<int>& w) {\n    int N = (int)w.size();\n    vector<int> b;\n    b.reserve(N - 1);\n    int pref = 0;\n    for (int i = 0; i < N - 1; i++) {\n        pref += w[i];\n        b.push_back(pref);\n    }\n    return b;\n}\n\nstatic int countCommonSorted(const vector<int>& a, const vector<int>& b) {\n    int i = 0, j = 0, t = 0;\n    while (i < (int)a.size() && j < (int)b.size()) {\n        if (a[i] == b[j]) { t++; i++; j++; }\n        else if (a[i] < b[j]) i++;\n        else j++;\n    }\n    return t;\n}\n\nstatic long long Ld_from_prev_curr(int W, const vector<int>& wPrev, const vector<int>& wCur) {\n    // L_d = W * | symmetric difference of boundary sets |\n    // boundary set size is N-1 each; symmetric diff size = 2((N-1)-|intersection|)\n    vector<int> bPrev = internalBoundaries(wPrev);\n    vector<int> bCur = internalBoundaries(wCur);\n    int t = countCommonSorted(bPrev, bCur);\n    int N = (int)wPrev.size();\n    int diffLines = (N - 1) - t;\n    return 2LL * W * diffLines;\n}\n\n// Greedy suffix widths builder for fixed identity mapping objective.\n// This produces a width vector summing to W, with prefix [0..c-1] fixed to wPrev.\nstatic vector<int> buildCandidateSuffixGreedy(\n    int W, const vector<vector<int>>& a, int d,\n    const vector<int>& wPrev, int c\n) {\n    int N = (int)wPrev.size();\n    vector<int> w(N, 1);\n\n    // fixed prefix\n    int used = 0;\n    for (int i = 0; i < c; i++) {\n        w[i] = wPrev[i];\n        used += w[i];\n    }\n    // suffix initially all 1, so total currently = used + (N-c)\n    int cur = used + (N - c);\n    int S = W - cur; // number of +1 increments to distribute\n    if (S == 0) return w;\n\n    // w0[k] = max w such that a > w*W  <=> w <= (a-1)/W\n    vector<int> w0(N, 0), rem(N, 0);\n    for (int k = 0; k < N; k++) {\n        int ak = a[d][k];\n        w0[k] = (ak - 1) / W; // can be 0..W-? (ak sum <= W^2)\n        if (w0[k] >= 1) rem[k] = ak - w0[k] * W; // in [1..W]\n    }\n\n    const long long NEG_FULL = -100LL * W;\n    const long long INF = (1LL << 60);\n\n    auto deltaOf = [&](int k) -> long long {\n        if (w[k] >= W) return INF; // shouldn't happen\n        if (w0[k] == 0) return 0LL;\n        if (w[k] < w0[k]) return NEG_FULL;\n        if (w[k] == w0[k]) return -100LL * rem[k];\n        return 0LL; // beyond -> already zero cost\n    };\n\n    priority_queue<pair<long long,int>, vector<pair<long long,int>>, greater<pair<long long,int>>> pq;\n    for (int k = c; k < N; k++) pq.push({deltaOf(k), k});\n\n    for (int step = 0; step < S; step++) {\n        auto [del, k] = pq.top(); pq.pop();\n        (void)del;\n        w[k]++; // feasible due to sum constraint\n        pq.push({deltaOf(k), k});\n    }\n    return w;\n}\n\nstatic vector<int> equalWidths(int W, int N) {\n    int base = W / N;\n    int rem = W % N;\n    vector<int> w(N, base);\n    for (int i = 0; i < rem; i++) w[i]++; // all >=1 since N<=50 and W=1000\n    return w;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int W, D, N;\n    cin >> W >> D >> N;\n    vector<vector<int>> a(D, vector<int>(N));\n    for (int d = 0; d < D; d++)\n        for (int k = 0; k < N; k++)\n            cin >> a[d][k];\n\n    vector<vector<int>> widths(D, vector<int>(N, 1));\n\n    // ---- Day 0: try a few candidate geometries, choose by exact assignment cost ----\n    vector<vector<int>> day0Cands;\n\n    // (1) equal\n    day0Cands.push_back(equalWidths(W, N));\n\n    // (2) greedy identity mapping (via greedy suffix builder with c=0, prefix empty)\n    {\n        vector<int> dummyPrev(N, 1);\n        int d = 0;\n        vector<int> w0 = buildCandidateSuffixGreedy(W, a, d, dummyPrev, 0);\n        day0Cands.push_back(w0);\n    }\n\n    // (3) greedy with reversed reservation indexing to alter strip width order/multiset\n    {\n        int d = 0;\n        vector<int> dummyPrev(N, 1);\n        // create reversed aRev for selection only by running greedy internally\n        // easiest: temporarily copy and compute w0 thresholds by using aRev values:\n        // We'll build greedy ourselves by using aRev on the same builder logic.\n        vector<vector<int>> aRev = a;\n        reverse(aRev[d].begin(), aRev[d].end());\n        vector<int> wrev = buildCandidateSuffixGreedy(W, aRev, d, dummyPrev, 0);\n        day0Cands.push_back(wrev);\n    }\n\n    long long bestDay0 = (1LL<<62);\n    vector<int> bestW0 = day0Cands[0];\n    {\n        int d = 0;\n        for (auto &w : day0Cands) {\n            vector<long long> b(N);\n            for (int s = 0; s < N; s++) b[s] = 1LL * w[s] * W;\n\n            vector<vector<long long>> cost(N, vector<long long>(N));\n            for (int k = 0; k < N; k++) {\n                for (int s = 0; s < N; s++) {\n                    long long diff = (long long)a[d][k] - b[s];\n                    cost[k][s] = (diff > 0) ? 100LL * diff : 0LL;\n                }\n            }\n            long long area = hungarianMinCost(cost);\n            if (area < bestDay0) {\n                bestDay0 = area;\n                bestW0 = w;\n            }\n        }\n    }\n    widths[0] = bestW0;\n\n    // ---- Days d>=1: choose best candidate among c=0..N with exact area cost + exact Ld ----\n    for (int d = 1; d < D; d++) {\n        const vector<int>& wPrev = widths[d-1];\n        long long bestTotal = (1LL<<62);\n        vector<int> bestW = wPrev;\n\n        for (int c = 0; c <= N; c++) {\n            vector<int> wCand;\n            if (c == N) wCand = wPrev;\n            else wCand = buildCandidateSuffixGreedy(W, a, d, wPrev, c);\n\n            // area shortfall min via assignment\n            vector<long long> b(N);\n            for (int s = 0; s < N; s++) b[s] = 1LL * wCand[s] * W;\n\n            vector<vector<long long>> cost(N, vector<long long>(N));\n            for (int k = 0; k < N; k++) {\n                for (int s = 0; s < N; s++) {\n                    long long diff = (long long)a[d][k] - b[s];\n                    cost[k][s] = (diff > 0) ? 100LL * diff : 0LL;\n                }\n            }\n            long long area = hungarianMinCost(cost);\n\n            // partition-change cost\n            long long Ld = Ld_from_prev_curr(W, wPrev, wCand);\n\n            long long total = area + Ld;\n            if (total < bestTotal) {\n                bestTotal = total;\n                bestW = std::move(wCand);\n            }\n        }\n        widths[d] = std::move(bestW);\n    }\n\n    // ---- Output: for each day, assign reservations to strips via Hungarian for exact minimal area term ----\n    for (int d = 0; d < D; d++) {\n        const vector<int>& w = widths[d];\n        vector<long long> pref(N + 1, 0);\n        for (int i = 0; i < N; i++) pref[i+1] = pref[i] + w[i];\n\n        vector<long long> b(N);\n        for (int s = 0; s < N; s++) b[s] = 1LL * w[s] * W;\n\n        vector<vector<long long>> cost(N, vector<long long>(N));\n        for (int k = 0; k < N; k++) {\n            for (int s = 0; s < N; s++) {\n                long long diff = (long long)a[d][k] - b[s];\n                cost[k][s] = (diff > 0) ? 100LL * diff : 0LL;\n            }\n        }\n\n        vector<int> match = hungarianAssign(cost); // reservation k -> strip match[k]\n\n        for (int k = 0; k < N; k++) {\n            int s = match[k];\n            long long x0 = pref[s];\n            long long x1 = pref[s+1];\n            // rectangle: (x0,0) to (x1,W)\n            cout << x0 << ' ' << 0 << ' ' << x1 << ' ' << W << '\\n';\n        }\n    }\n    return 0;\n}","ahc032":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int MOD = 998244353;\n\nstruct OpInfo {\n    array<uint8_t, 9> idx; // 9 affected cells in [0..80]\n    array<int, 9> add;     // add for each of those cells mod MOD\n    uint64_t lo = 0, hi = 0; // mask membership: cells 0..63 in lo, 64..80 in hi\n};\n\nstatic inline bool maskHas(const OpInfo& op, int cell) {\n    if (cell < 64) return (op.lo >> cell) & 1ULL;\n    return (op.hi >> (cell - 64)) & 1ULL;\n}\nstatic inline void maskSet(OpInfo& op, int cell) {\n    if (cell < 64) op.lo |= (1ULL << cell);\n    else op.hi |= (1ULL << (cell - 64));\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, K;\n    cin >> N >> M >> K;\n\n    vector<vector<int>> a(N, vector<int>(N));\n    for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) cin >> a[i][j];\n\n    vector<vector<vector<int>>> s(M, vector<vector<int>>(3, vector<int>(3)));\n    for (int m = 0; m < M; m++)\n        for (int i = 0; i < 3; i++)\n            for (int j = 0; j < 3; j++)\n                cin >> s[m][i][j];\n\n    const int NN = N * N;\n    if (N != 9 || NN != 81) { // per statement N=9\n        cout << 0 << \"\\n\";\n        return 0;\n    }\n\n    // Enumerate all possible stamp placements (m, p, q) without rotation.\n    vector<OpInfo> ops;\n    vector<array<uint8_t, 3>> meta; // {m,p,q}\n    ops.reserve(M * (N - 2) * (N - 2));\n    meta.reserve(M * (N - 2) * (N - 2));\n\n    for (int m = 0; m < M; m++) {\n        for (int p = 0; p <= N - 3; p++) {\n            for (int q = 0; q <= N - 3; q++) {\n                OpInfo op;\n                int t = 0;\n                for (int di = 0; di < 3; di++) {\n                    for (int dj = 0; dj < 3; dj++) {\n                        int ii = p + di, jj = q + dj;\n                        int cell = ii * N + jj;\n                        op.idx[t] = (uint8_t)cell;\n                        op.add[t] = s[m][di][dj] % MOD;\n                        maskSet(op, cell);\n                        t++;\n                    }\n                }\n                ops.push_back(op);\n                meta.push_back({(uint8_t)m, (uint8_t)p, (uint8_t)q});\n            }\n        }\n    }\n    const int numOps = (int)ops.size(); // 980\n\n    // opAddCell[opId][cell] = add value if op touches the cell, else 0\n    vector<array<int, 81>> opAddCell(numOps);\n    for (int opId = 0; opId < numOps; opId++) {\n        opAddCell[opId].fill(0);\n        for (int t = 0; t < 9; t++) {\n            int cell = ops[opId].idx[t];\n            opAddCell[opId][cell] = ops[opId].add[t];\n        }\n    }\n\n    // For overlap-aware candidate sampling: overlapOps[oldOp] = all ops touching any cell of oldOp.\n    vector<vector<int>> touchOps(81);\n    for (int opId = 0; opId < numOps; opId++) {\n        for (int t = 0; t < 9; t++) {\n            int cell = ops[opId].idx[t];\n            touchOps[cell].push_back(opId);\n        }\n    }\n    vector<vector<int>> overlapOps(numOps);\n    {\n        vector<int> mark(numOps, -1);\n        int stamp = 0;\n        for (int oldOp = 0; oldOp < numOps; oldOp++) {\n            stamp++;\n            vector<int> cand;\n            cand.reserve(500);\n            for (int t = 0; t < 9; t++) {\n                int cell = ops[oldOp].idx[t];\n                for (int op2 : touchOps[cell]) {\n                    if (mark[op2] != stamp) {\n                        mark[op2] = stamp;\n                        cand.push_back(op2);\n                    }\n                }\n            }\n            overlapOps[oldOp] = std::move(cand);\n        }\n    }\n\n    array<int, 81> initX{};\n    for (int i = 0; i < N; i++)\n        for (int j = 0; j < N; j++)\n            initX[i * N + j] = a[i][j] % MOD;\n\n    auto sumScore = [&](const array<int, 81>& x) -> long long {\n        long long sc = 0;\n        for (int i = 0; i < 81; i++) sc += x[i];\n        return sc;\n    };\n\n    auto deltaInsert = [&](int opId, const array<int, 81>& x) -> long long {\n        const auto& op = ops[opId];\n        long long d = 0;\n        for (int t = 0; t < 9; t++) {\n            int cell = op.idx[t];\n            int oldv = x[cell];\n            int nv = oldv + op.add[t];\n            if (nv >= MOD) nv -= MOD;\n            d += (long long)nv - oldv;\n        }\n        return d;\n    };\n\n    auto deltaReplace = [&](int oldOpId, int newOpId, const array<int, 81>& x) -> long long {\n        const auto& oldOp = ops[oldOpId];\n        const auto& newOp = ops[newOpId];\n\n        long long d = 0;\n\n        // Cells in oldOp\n        for (int t = 0; t < 9; t++) {\n            int cell = oldOp.idx[t];\n            int oldv = x[cell];\n            int oldAdd = oldOp.add[t];\n            int newAdd = opAddCell[newOpId][cell]; // 0 if not touched\n            int tmp = oldv + newAdd - oldAdd;\n            if (tmp < 0) tmp += MOD;\n            else if (tmp >= MOD) tmp -= MOD;\n            d += (long long)tmp - oldv;\n        }\n\n        // Cells in newOp but not in oldOp\n        for (int t = 0; t < 9; t++) {\n            int cell = newOp.idx[t];\n            if (maskHas(oldOp, cell)) continue;\n            int oldv = x[cell];\n            int nv = oldv + newOp.add[t];\n            if (nv >= MOD) nv -= MOD;\n            d += (long long)nv - oldv;\n        }\n\n        return d;\n    };\n\n    auto applyAdd = [&](int opId, array<int, 81>& x) {\n        const auto& op = ops[opId];\n        for (int t = 0; t < 9; t++) {\n            int cell = op.idx[t];\n            int nv = x[cell] + op.add[t];\n            if (nv >= MOD) nv -= MOD;\n            x[cell] = nv;\n        }\n    };\n\n    auto applyRemove = [&](int opId, array<int, 81>& x) {\n        const auto& op = ops[opId];\n        for (int t = 0; t < 9; t++) {\n            int cell = op.idx[t];\n            int nv = x[cell] - op.add[t];\n            if (nv < 0) nv += MOD;\n            x[cell] = nv;\n        }\n    };\n\n    auto nowMs = []() -> int {\n        using namespace std::chrono;\n        static auto st = steady_clock::now();\n        return (int)duration_cast<milliseconds>(steady_clock::now() - st).count();\n    };\n\n    // Greedy init for fixed K: exact TOPS selection each step (still fast enough).\n    auto greedyInitFixedK = [&](uint64_t seed) -> vector<int> {\n        mt19937_64 rng(seed);\n        array<int, 81> x = initX;\n        vector<int> opsVec;\n        opsVec.reserve(K);\n\n        const int TOPS = 28;\n\n        for (int step = 0; step < K; step++) {\n            // compute all deltas and take top TOPS\n            vector<pair<long long,int>> v;\n            v.reserve(numOps);\n            for (int opId = 0; opId < numOps; opId++) {\n                v.push_back({deltaInsert(opId, x), opId});\n            }\n\n            int B = min(TOPS, numOps);\n            nth_element(v.begin(), v.begin() + B, v.end(),\n                        [](const auto& a, const auto& b){ return a.first > b.first; });\n            v.resize(B);\n            sort(v.begin(), v.end(), [](const auto& a, const auto& b){ return a.first > b.first; });\n\n            // Weighted choice among TOPS by (max(d,0)+1) to diversify\n            long long sumw = 0;\n            vector<long long> w(B);\n            for (int i = 0; i < B; i++) {\n                long long wi = v[i].first;\n                if (wi < 0) wi = 0;\n                wi += 1;\n                w[i] = wi;\n                sumw += wi;\n            }\n            unsigned long long r = (unsigned long long)rng() % (unsigned long long)sumw;\n            int pick = 0;\n            long long acc = 0;\n            for (int i = 0; i < B; i++) {\n                acc += w[i];\n                if ((long long)r < acc) { pick = i; break; }\n            }\n\n            int chosen = v[pick].second;\n            opsVec.push_back(chosen);\n            applyAdd(chosen, x);\n        }\n        return opsVec;\n    };\n\n    auto annealFixedK = [&](vector<int> opsVec, uint64_t seed, int timeBudgetMs) -> pair<long long, vector<int>> {\n        mt19937_64 rng(seed);\n\n        array<int, 81> x = initX;\n        for (int opId : opsVec) applyAdd(opId, x);\n\n        long long curScore = sumScore(x);\n        long long bestScore = curScore;\n        vector<int> bestOps = opsVec;\n\n        // Refresh global bias list from deltaInsert periodically (cheap enough).\n        vector<int> topInsert;\n        topInsert.reserve(250);\n        int lastRefresh = nowMs();\n\n        auto refreshTopInsert = [&]() {\n            vector<pair<long long,int>> v;\n            v.reserve(numOps);\n            for (int opId = 0; opId < numOps; opId++) v.push_back({deltaInsert(opId, x), opId});\n            int B = 220;\n            nth_element(v.begin(), v.begin() + B, v.end(),\n                        [](const auto& a, const auto& b){ return a.first > b.first; });\n            v.resize(B);\n            sort(v.begin(), v.end(), [](const auto& a, const auto& b){ return a.first > b.first; });\n            topInsert.clear();\n            for (auto &p : v) topInsert.push_back(p.second);\n        };\n\n        refreshTopInsert();\n\n        int start = nowMs();\n        while (true) {\n            int elapsed = nowMs() - start;\n            if (elapsed >= timeBudgetMs) break;\n\n            // temperature schedule\n            double prog = (double)elapsed / (double)timeBudgetMs;\n            double T = 2.8e9 + (1.0e6 - 2.8e9) * prog;\n\n            if (nowMs() - lastRefresh >= 120) {\n                refreshTopInsert();\n                lastRefresh = nowMs();\n            }\n\n            int pos = (int)(rng() % (unsigned)K);\n            int oldOp = opsVec[pos];\n\n            // sample candidates and keep top few deltas\n            const int SAMPLE = 26;\n            const int TOPP = 4;\n\n            array<long long, TOPP> topD{};\n            array<int, TOPP> topId{};\n            int tcnt = 0;\n\n            auto pickCand = [&]() -> int {\n                int r = (int)(rng() % 100);\n                if (r < 75) {\n                    auto &ov = overlapOps[oldOp];\n                    return ov[(int)(rng() % (unsigned)ov.size())];\n                } else if (r < 90) {\n                    if (!topInsert.empty()) return topInsert[(int)(rng() % (unsigned)topInsert.size())];\n                }\n                return (int)(rng() % (unsigned)numOps);\n            };\n\n            for (int it = 0; it < SAMPLE; it++) {\n                int cand = pickCand();\n                if (cand == oldOp) continue;\n\n                long long d = deltaReplace(oldOp, cand, x);\n\n                if (tcnt < TOPP) {\n                    topD[tcnt] = d;\n                    topId[tcnt] = cand;\n                    tcnt++;\n                    for (int i = tcnt - 1; i > 0; i--) {\n                        if (topD[i] > topD[i - 1]) {\n                            swap(topD[i], topD[i - 1]);\n                            swap(topId[i], topId[i - 1]);\n                        }\n                    }\n                } else if (d > topD[TOPP - 1]) {\n                    topD[TOPP - 1] = d;\n                    topId[TOPP - 1] = cand;\n                    for (int i = TOPP - 1; i > 0; i--) {\n                        if (topD[i] > topD[i - 1]) {\n                            swap(topD[i], topD[i - 1]);\n                            swap(topId[i], topId[i - 1]);\n                        }\n                    }\n                }\n            }\n            if (tcnt == 0) continue;\n\n            // choose among topD stochastically: weights = (d+1) clipped\n            long long sumw = 0;\n            array<long long, TOPP> w{};\n            for (int i = 0; i < tcnt; i++) {\n                long long wi = topD[i] + 1;\n                if (wi < 1) wi = 1;\n                w[i] = wi;\n                sumw += wi;\n            }\n            long long rr = (long long)(rng() % (unsigned long long)sumw);\n            int pick = 0;\n            long long accw = 0;\n            for (int i = 0; i < tcnt; i++) {\n                accw += w[i];\n                if (rr < accw) { pick = i; break; }\n            }\n\n            int newOp = topId[pick];\n            long long d = topD[pick];\n            if (newOp == oldOp) continue;\n\n            bool ok = false;\n            if (d >= 0) ok = true;\n            else {\n                // Metropolis acceptance\n                double z = (double)d / T; // negative\n                if (z < -50) ok = false;\n                else {\n                    double p = exp(z);\n                    double u = (double)rng() / (double)rng.max();\n                    ok = (u < p);\n                }\n            }\n            if (!ok) continue;\n\n            applyRemove(oldOp, x);\n            applyAdd(newOp, x);\n            opsVec[pos] = newOp;\n            curScore += d;\n\n            if (curScore > bestScore) {\n                bestScore = curScore;\n                bestOps = opsVec;\n            }\n        }\n\n        return {bestScore, bestOps};\n    };\n\n    // Global restarts\n    int globalStart = nowMs();\n    const int TIME = 1880;\n\n    long long bestScore = -1;\n    vector<int> bestOps;\n\n    int restarts = 4;\n    for (int r = 0; r < restarts; r++) {\n        if (nowMs() - globalStart > TIME - 100) break;\n\n        int elapsed = nowMs() - globalStart;\n        int budget = (TIME - elapsed) / (restarts - r);\n        budget = max(180, budget);\n\n        uint64_t seed = 123456789ULL + 10007ULL * (r + 1) * 1009ULL;\n        vector<int> initOps = greedyInitFixedK(seed ^ 0x9e377b97f4a7c15ULL);\n\n        auto [sc, opsBest] = annealFixedK(std::move(initOps), seed + 424242ULL, budget);\n        if (sc > bestScore) {\n            bestScore = sc;\n            bestOps = std::move(opsBest);\n        }\n    }\n\n    // Output exactly K operations\n    cout << K << \"\\n\";\n    for (int i = 0; i < K; i++) {\n        auto mm = meta[bestOps[i]];\n        cout << (int)mm[0] << \" \" << (int)mm[1] << \" \" << (int)mm[2] << \"\\n\";\n    }\n    return 0;\n}","ahc033":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic inline int manhattan(int x1,int y1,int x2,int y2){\n    return abs(x1-x2)+abs(y1-y2);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    cin >> N;\n    vector<vector<int>> A(N, vector<int>(N));\n    for(int i=0;i<N;i++) for(int j=0;j<N;j++) cin >> A[i][j];\n\n    const int TOTAL = N*N;\n    const int MAX_T = 10000;\n\n    // grid[x][y] = container id or -1\n    vector<vector<int>> grid(N, vector<int>(N, -1));\n\n    // position tracking for each container id\n    vector<int> px(TOTAL, -3), py(TOTAL, -3);\n\n    // receiving placement counters per row\n    vector<int> recvNext(N, 0);\n\n    // disp[g][k] means container (g*N+k) has been dispatched from gate g\n    vector<vector<bool>> disp(N, vector<bool>(N, false));\n    vector<int> nextK(N, 0); // smallest k not yet dispatched in each gate\n\n    // crane0 state\n    int cx = 0, cy = 0;\n    bool holding = false;\n    int heldId = -1;\n\n    // current plan while not holding\n    bool planned = false;\n    int pickX = -1, pickY = -1;\n    int relX = -1, relY = -1;\n    bool pickAfterIsDispatch = false; // if true => release to correct dispatch gate immediately\n\n    auto moveNotHolding = [&](int x,int y,int tx,int ty)->char{\n        if (x < tx) return 'D';\n        if (x > tx) return 'U';\n        if (y < ty) return 'R';\n        if (y > ty) return 'L';\n        return '.';\n    };\n    auto moveHolding = [&](int x,int y,int tx,int ty)->char{\n        // right-first helps freeing (row,0) quickly after picking\n        if (y < ty) return 'R';\n        if (y > ty) return 'L';\n        if (x < tx) return 'D';\n        if (x > tx) return 'U';\n        return '.';\n    };\n\n    // buffer cells: rows 0..N-1, columns 1..N-2\n    vector<pair<int,int>> bufferCells;\n    for(int x=0;x<N;x++) for(int y=1;y<=N-2;y++) bufferCells.push_back({x,y});\n    int bestBufCol = N - 2;\n\n    vector<char> ops0;\n    ops0.reserve(MAX_T);\n\n    int dispatchedTotal = 0;\n\n    auto isExpectedMinAvailable = [&](int &outPickX, int &outPickY, int &outGate)->bool{\n        long long bestCost = (1LL<<60);\n        outPickX = outPickY = outGate = -1;\n\n        for(int g=0; g<N; g++){\n            int k = nextK[g];\n            if(k >= N) continue;\n            int id = g*N + k;\n            int x = px[id], y = py[id];\n            if(x < 0) continue;\n            if(grid[x][y] != id) continue;\n\n            // should never be at dispatch gate because step3 clears it, but keep safe:\n            if(!(y==0 || (1<=y && y<=N-2))) continue;\n\n            long long cost = (long long)manhattan(cx,cy,x,y) + (long long)manhattan(x,y,g,N-1);\n            if(cost < bestCost){\n                bestCost = cost;\n                outPickX = x; outPickY = y; outGate = g;\n            }\n        }\n        return outPickX != -1;\n    };\n\n    auto findNearestOccupied = [&]()->pair<int,int>{\n        long long best = (1LL<<60);\n        pair<int,int> ans = {-1,-1};\n\n        // search receiving and buffers\n        for(int i=0;i<N;i++){\n            if(grid[i][0] != -1){\n                long long d = manhattan(cx,cy,i,0);\n                if(d < best){ best = d; ans = {i,0}; }\n            }\n        }\n        for(auto [bx,by]: bufferCells){\n            if(grid[bx][by] != -1){\n                long long d = manhattan(cx,cy,bx,by);\n                if(d < best){ best = d; ans = {bx,by}; }\n            }\n        }\n        return ans;\n    };\n\n    for (int t = 0; t < MAX_T; t++) {\n        // ---- step1: place arriving containers at receiving gates (i,0) ----\n        for (int i = 0; i < N; i++) {\n            if (recvNext[i] >= N) continue;\n            if (grid[i][0] != -1) continue;\n\n            // blocked only if crane0 is holding at that exact square\n            if (holding && cx == i && cy == 0) continue;\n\n            int id = A[i][recvNext[i]];\n            grid[i][0] = id;\n            px[id] = i; py[id] = 0;\n            recvNext[i]++;\n        }\n\n        // ---- step2: decide action for crane0 ----\n        char act0 = '.';\n\n        if (holding) {\n            // release at planned target\n            if (cx == relX && cy == relY) {\n                act0 = 'Q';\n            } else {\n                act0 = moveHolding(cx,cy,relX,relY);\n            }\n        } else {\n            // if holding just ended earlier, clear plan status already.\n            // recompute plan only when not holding.\n            if (!planned) {\n                // 1) try dispatching expected-min container if available\n                int pX, pY, gate;\n                bool ok = isExpectedMinAvailable(pX,pY,gate);\n                if(ok){\n                    planned = true;\n                    pickX = pX; pickY = pY;\n                    pickAfterIsDispatch = true;\n                    relX = gate; relY = N-1;\n                } else {\n                    // 2) buffer not full? => store some receiving container into an empty buffer\n                    int bufSize = (int)bufferCells.size();\n                    int bufCount = 0;\n                    for(auto [bx,by]: bufferCells) if(grid[bx][by] != -1) bufCount++;\n                    bool bufferFull = (bufCount == bufSize);\n\n                    if(!bufferFull){\n                        // Choose which receiving container to store and where.\n                        // We'll prefer storing into column bestBufCol, and prefer row = gate of that container.\n                        long long bestScore = (1LL<<60);\n                        int selPickX=-1, selPickY=-1;\n                        int selRelX=-1, selRelY=-1;\n\n                        for(int r=0;r<N;r++){\n                            if(grid[r][0] == -1) continue; // receiving occupied required\n                            int id = grid[r][0];\n                            int g = id / N;\n                            int k = id % N;\n\n                            // must ensure we won't \"lose\" correctness: storing is staging only.\n                            // (M1 handled later by dispatching expected-min when possible.)\n\n                            // find best empty buffer cell for this g, with preference col bestBufCol\n                            vector<pair<int,int>> candidates;\n                            // first try (g, bestBufCol)\n                            if(bestBufCol >= 1 && bestBufCol <= N-2 && grid[g][bestBufCol]==-1){\n                                candidates.push_back({g,bestBufCol});\n                            }\n                            // otherwise try other columns in same row g\n                            for(int y=1;y<=N-2;y++){\n                                if(grid[g][y]==-1 && (g!=g || y!=bestBufCol)) candidates.push_back({g,y});\n                            }\n                            // if still none, try any empty buffer\n                            if(candidates.empty()){\n                                for(auto [bx,by]: bufferCells){\n                                    if(grid[bx][by]==-1) candidates.push_back({bx,by});\n                                }\n                            }\n\n                            // Choose candidate release cell that minimizes distance from current crane to store later.\n                            // We'll incorporate current position for time: cost = dist(cx->(r,0)) + dist((r,0)->(rel))\n                            long long bestCandScore = (1LL<<60);\n                            int candRelX=-1, candRelY=-1;\n                            for(auto [bx,by]: candidates){\n                                // prefer rightmost column slightly (ties will be decided here)\n                                long long storeCost = (long long)manhattan(cx,cy,r,0) + (long long)manhattan(r,0,bx,by);\n                                long long gateGap = (long long)k - nextK[g]; // smaller means closer to being expected-min\n                                // Weighted comparison: prioritize low storeCost, then low gateGap, then prefer rightmost buffer\n                                long long score = storeCost * 10 + gateGap;\n                                if(score < bestCandScore){\n                                    bestCandScore = score;\n                                    candRelX = bx; candRelY = by;\n                                }\n                            }\n\n                            if(candRelX == -1) continue;\n\n                            long long finalScore = bestCandScore;\n                            if(finalScore < bestScore){\n                                bestScore = finalScore;\n                                selPickX = r; selPickY = 0;\n                                selRelX = candRelX; selRelY = candRelY;\n                            }\n                        }\n\n                        if(selPickX != -1){\n                            planned = true;\n                            pickX = selPickX; pickY = selPickY;\n                            pickAfterIsDispatch = false; // store\n                            relX = selRelX; relY = selRelY;\n                        }\n                    } else {\n                        // buffer full: dispatch something from buffer (may cause M1, but prevents deadlock)\n                        // Choose the best (lowest gap to expected-min), and with good cost.\n                        long long bestDispScore = (1LL<<60);\n                        int selPickX=-1, selPickY=-1, selGate=-1;\n\n                        for(auto [bx,by]: bufferCells){\n                            if(grid[bx][by] == -1) continue;\n                            int id = grid[bx][by];\n                            int g = id / N;\n                            int k = id % N;\n\n                            long long gap = (long long)k - nextK[g]; // >= 0 ideally if nextK not passed\n                            long long dispCost = (long long)manhattan(cx,cy,bx,by) + (long long)manhattan(bx,by,g,N-1);\n                            // prioritize expected correctness (small gap), then cost\n                            long long score = gap * 100 + dispCost;\n                            if(score < bestDispScore){\n                                bestDispScore = score;\n                                selPickX = bx; selPickY = by; selGate = g;\n                            }\n                        }\n\n                        if(selPickX != -1){\n                            planned = true;\n                            pickX = selPickX; pickY = selPickY;\n                            pickAfterIsDispatch = true;\n                            relX = selGate; relY = N-1;\n                        }\n                    }\n                }\n\n                // 3) Fallback: if still no plan, move toward nearest occupied cell (avoid idle turns)\n                if(!planned){\n                    auto nearest = findNearestOccupied();\n                    if(nearest.first != -1){\n                        act0 = moveNotHolding(cx,cy,nearest.first,nearest.second);\n                    } else {\n                        act0 = '.'; // nothing on board\n                    }\n                } else {\n                    // we have plan: move toward pick or pick if at location\n                    if (cx == pickX && cy == pickY) act0 = 'P';\n                    else act0 = moveNotHolding(cx,cy,pickX,pickY);\n                }\n            } else {\n                // already have plan\n                if (cx == pickX && cy == pickY) act0 = 'P';\n                else act0 = moveNotHolding(cx,cy,pickX,pickY);\n            }\n        }\n\n        ops0.push_back(act0);\n\n        // ---- apply crane0 action (step2 effects) ----\n        if (holding) {\n            if (act0 == 'Q') {\n                // release into target\n                if (grid[cx][cy] != -1) return 0; // illegal\n                grid[cx][cy] = heldId;\n                px[heldId] = cx; py[heldId] = cy;\n                holding = false;\n                heldId = -1;\n                planned = false; // force replanning next iteration\n                pickAfterIsDispatch = false;\n            } else if (act0=='U' || act0=='D' || act0=='L' || act0=='R') {\n                int nx=cx, ny=cy;\n                if(act0=='U') nx--;\n                if(act0=='D') nx++;\n                if(act0=='L') ny--;\n                if(act0=='R') ny++;\n                if(!(0<=nx && nx<N && 0<=ny && ny<N)) return 0;\n                cx=nx; cy=ny;\n            } else if (act0=='.') {\n                // ok\n            } else {\n                return 0;\n            }\n        } else {\n            if (act0 == 'P') {\n                if (grid[cx][cy] == -1) return 0;\n                heldId = grid[cx][cy];\n                grid[cx][cy] = -1;\n                px[heldId] = -1; py[heldId] = -1;\n                holding = true;\n\n                // keep relX/relY from the plan\n            } else if (act0=='U' || act0=='D' || act0=='L' || act0=='R') {\n                int nx=cx, ny=cy;\n                if(act0=='U') nx--;\n                if(act0=='D') nx++;\n                if(act0=='L') ny--;\n                if(act0=='R') ny++;\n                if(!(0<=nx && nx<N && 0<=ny && ny<N)) return 0;\n                cx=nx; cy=ny;\n            } else if (act0=='.') {\n                // ok\n            } else {\n                return 0;\n            }\n        }\n\n        // ---- step3: dispatch at dispatch gates ----\n        for(int i=0;i<N;i++){\n            if(grid[i][N-1] != -1){\n                int id = grid[i][N-1];\n                grid[i][N-1] = -1;\n                px[id] = -2; py[id] = -2;\n                dispatchedTotal++;\n\n                int g = id / N;\n                int k = id % N;\n                if(!disp[g][k]){\n                    disp[g][k] = true;\n                    while(nextK[g] < N && disp[g][nextK[g]]) nextK[g]++;\n                }\n            }\n        }\n\n        if(dispatchedTotal == TOTAL) break;\n    }\n\n    int L = (int)ops0.size();\n    if(L == 0){ // extremely unlikely\n        cout << \".\\n\";\n        cout << \".\\n\";\n        cout << \".\\n\";\n        cout << \".\\n\";\n        cout << \".\\n\";\n        return 0;\n    }\n\n    vector<string> out(N);\n    out[0].assign(ops0.begin(), ops0.end());\n    for(int i=1;i<N;i++){\n        out[i].clear();\n        out[i].push_back('B');\n        if(L > 1) out[i] += string(L-1, '.');\n    }\n\n    for(int i=0;i<N;i++) cout << out[i] << \"\\n\";\n    return 0;\n}","ahc034":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic inline int manhattan(int r1, int c1, int r2, int c2) {\n    return abs(r1 - r2) + abs(c1 - c2);\n}\nstatic inline int cellId(int r, int c, int N) { return r * N + c; }\nstatic inline pair<int,int> cellRC(int id, int N) { return {id / N, id % N}; }\n\nstatic inline void movePath(int &r, int &c, int nr, int nc, vector<string> &ops) {\n    while (r < nr) { ops.push_back(\"D\"); r++; }\n    while (r > nr) { ops.push_back(\"U\"); r--; }\n    while (c < nc) { ops.push_back(\"R\"); c++; }\n    while (c > nc) { ops.push_back(\"L\"); c--; }\n}\n\nstruct Job {\n    int startId = -1;\n    int endId = -1;\n    int totalLoad = 0;\n    vector<int> targetIds;   // in planned visit order\n    vector<int> amounts;     // aligned with targetIds\n\n    long long internalCost = 0; // exact job cost excluding empty move from previous end/start\n    int internalSteps = 0;      // exact number of loaded move steps inside job\n    int targetCount = 0;\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++) for (int j = 0; j < N; j++) cin >> h[i][j];\n\n    vector<int> sources, sinks;\n    vector<int> posAmt(N*N, 0), negAmt(N*N, 0);\n    for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) {\n        int id = cellId(i, j, N);\n        if (h[i][j] > 0) { sources.push_back(id); posAmt[id] = h[i][j]; }\n        else if (h[i][j] < 0) { sinks.push_back(id); negAmt[id] = -h[i][j]; }\n    }\n    if (sources.empty()) return 0;\n\n    const int V = N*N;\n    vector<vector<int>> dist(V, vector<int>(V, 0));\n    for (int a = 0; a < V; a++) {\n        auto [ra, ca] = cellRC(a, N);\n        for (int b = 0; b < V; b++) {\n            auto [rb, cb] = cellRC(b, N);\n            dist[a][b] = abs(ra - rb) + abs(ca - cb);\n        }\n    }\n\n    vector<double> avgDist(V, 0.0);\n    for (int a = 0; a < V; a++) {\n        long long sum = 0;\n        for (int b = 0; b < V; b++) if (b != a) sum += dist[a][b];\n        avgDist[a] = (double)sum / (double)(V - 1);\n    }\n\n    // ---- Allocation: distance-sorted greedy (robust; matches your earlier best trend) ----\n    int S = (int)sources.size();\n    int D = (int)sinks.size();\n    vector<int> remS(S), remD(D);\n    for (int i = 0; i < S; i++) remS[i] = posAmt[sources[i]];\n    for (int j = 0; j < D; j++) remD[j] = negAmt[sinks[j]];\n\n    vector<vector<int>> alloc(S, vector<int>(D, 0));\n    struct Edge { int c; int i; int j; };\n    vector<Edge> edges;\n    edges.reserve((size_t)S * (size_t)D);\n    for (int i = 0; i < S; i++) for (int j = 0; j < D; j++) {\n        edges.push_back({dist[sources[i]][sinks[j]], i, j});\n    }\n    sort(edges.begin(), edges.end(), [](const Edge& a, const Edge& b){\n        if (a.c != b.c) return a.c < b.c;\n        if (a.i != b.i) return a.i < b.i;\n        return a.j < b.j;\n    });\n\n    for (auto &e : edges) {\n        if (remS[e.i] == 0 || remD[e.j] == 0) continue;\n        int x = min(remS[e.i], remD[e.j]);\n        alloc[e.i][e.j] += x;\n        remS[e.i] -= x;\n        remD[e.j] -= x;\n    }\n\n    // ---- Build jobs per source (one job per source, load all its supply) ----\n    vector<Job> jobs;\n    jobs.reserve(S);\n    for (int i = 0; i < S; i++) {\n        int load = posAmt[sources[i]];\n        if (load == 0) continue;\n        Job jb;\n        jb.startId = sources[i];\n        jb.totalLoad = load;\n        for (int j = 0; j < D; j++) if (alloc[i][j] > 0) {\n            jb.targetIds.push_back(sinks[j]);\n            jb.amounts.push_back(alloc[i][j]);\n        }\n        jb.targetCount = (int)jb.targetIds.size();\n        jobs.push_back(std::move(jb));\n    }\n\n    int M = (int)jobs.size();\n    mt19937 rng(123456789);\n\n    // ---- Internal ordering per job (exact cost eval + randomized greedy + insertion + 2-opt) ----\n    auto computeInternalCostAndSteps = [&](const Job &jb,\n                                            const vector<int> &ordT,\n                                            const vector<int> &ordA,\n                                            int &stepsOut) -> long long {\n        int cur = jb.startId;\n        int load = jb.totalLoad;\n        long long moveCost = 0;\n        int steps = 0;\n        for (int t = 0; t < (int)ordT.size(); t++) {\n            int tid = ordT[t];\n            int amt = ordA[t];\n            int d = dist[cur][tid];\n            steps += d;\n            moveCost += 1LL * d * (100LL + load);\n            load -= amt;\n            cur = tid;\n        }\n        stepsOut = steps;\n        // +totalLoad cost once, and -amt sum = totalLoad cost once => 2*totalLoad\n        return moveCost + 2LL * jb.totalLoad;\n    };\n\n    for (auto &jb : jobs) {\n        int k = (int)jb.targetIds.size();\n        if (k == 0) {\n            jb.endId = jb.startId;\n            jb.internalCost = 0;\n            jb.internalSteps = 0;\n            continue;\n        }\n        if (k == 1) {\n            jb.endId = jb.targetIds[0];\n            int steps = dist[jb.startId][jb.endId];\n            jb.internalSteps = steps;\n            jb.internalCost = 1LL * steps * (100LL + jb.totalLoad) + 2LL * jb.totalLoad;\n            continue;\n        }\n\n        vector<int> tids = jb.targetIds;\n        vector<int> amts = jb.amounts;\n\n        auto evalOrderIdx = [&](const vector<int> &ordIdx, int &stepsOut) -> long long {\n            vector<int> ordT(k), ordA(k);\n            for (int i = 0; i < k; i++) {\n                ordT[i] = tids[ordIdx[i]];\n                ordA[i] = amts[ordIdx[i]];\n            }\n            return computeInternalCostAndSteps(jb, ordT, ordA, stepsOut);\n        };\n\n        long long bestCost = (1LL<<62);\n        int bestSteps = 0;\n        vector<int> bestOrdIdx;\n\n        int trials = (k <= 35 ? 22 : (k <= 90 ? 14 : 10));\n        int topK = (k <= 35 ? 6 : 4);\n        double alpha = 1.12;\n\n        for (int tt = 0; tt < trials; tt++) {\n            vector<char> used(k, 0);\n            vector<int> ordIdx;\n            ordIdx.reserve(k);\n\n            int cur = jb.startId;\n            int load = jb.totalLoad;\n\n            while ((int)ordIdx.size() < k) {\n                int rem = k - (int)ordIdx.size();\n                vector<pair<double,int>> cand;\n                cand.reserve(rem);\n\n                for (int i = 0; i < k; i++) if (!used[i]) {\n                    int tid = tids[i];\n                    int amt = amts[i];\n\n                    double imm = 1.0 * dist[cur][tid] * (100.0 + (double)load);\n                    double futureDistEst = (double)(rem - 1) * avgDist[tid];\n                    double save = alpha * (double)amt * futureDistEst;\n                    double score = imm - save;\n\n                    cand.push_back({score, i});\n                }\n\n                int take = min(topK, (int)cand.size());\n                nth_element(cand.begin(), cand.begin() + take, cand.end(),\n                            [](auto &a, auto &b){ return a.first < b.first; });\n                cand.resize(take);\n                sort(cand.begin(), cand.end(), [](auto &a, auto &b){ return a.first < b.first; });\n\n                int pick = (take == 1 ? 0 : (int)(rng() % take));\n                int idx = cand[pick].second;\n\n                used[idx] = 1;\n                ordIdx.push_back(idx);\n                cur = tids[idx];\n                load -= amts[idx];\n            }\n\n            int steps = 0;\n            long long cost = evalOrderIdx(ordIdx, steps);\n            if (cost < bestCost) {\n                bestCost = cost;\n                bestSteps = steps;\n                bestOrdIdx = std::move(ordIdx);\n            }\n        }\n\n        // insertion + 2-opt local search (exact eval)\n        vector<int> curIdx = bestOrdIdx;\n        long long curBest = bestCost;\n        int curSteps = bestSteps;\n\n        int itIns = (k <= 45 ? 300 : (k <= 120 ? 220 : 160));\n        for (int it = 0; it < itIns; it++) {\n            int a = rng() % k;\n            int b = rng() % k;\n            if (a == b) continue;\n\n            vector<int> nxt = curIdx;\n            int val = nxt[a];\n            nxt.erase(nxt.begin() + a);\n            int bb = b;\n            if (bb > a) bb--;\n            nxt.insert(nxt.begin() + bb, val);\n\n            int steps = 0;\n            long long cost = evalOrderIdx(nxt, steps);\n            if (cost < curBest) {\n                curBest = cost;\n                curSteps = steps;\n                curIdx = std::move(nxt);\n            }\n        }\n\n        if (k <= 90) {\n            int it2 = 200;\n            for (int it = 0; it < it2; it++) {\n                int l = rng() % k;\n                int r = rng() % k;\n                if (l == r) continue;\n                if (l > r) swap(l, r);\n                if (r - l < 2) continue;\n\n                vector<int> nxt = curIdx;\n                reverse(nxt.begin() + l, nxt.begin() + r + 1);\n\n                int steps = 0;\n                long long cost = evalOrderIdx(nxt, steps);\n                if (cost < curBest) {\n                    curBest = cost;\n                    curSteps = steps;\n                    curIdx = std::move(nxt);\n                }\n            }\n        }\n\n        jb.internalCost = curBest;\n        jb.internalSteps = curSteps;\n        jb.targetIds.clear();\n        jb.amounts.clear();\n        jb.targetIds.reserve(k);\n        jb.amounts.reserve(k);\n        for (int idx : curIdx) {\n            jb.targetIds.push_back(tids[idx]);\n            jb.amounts.push_back(amts[idx]);\n        }\n        jb.endId = jb.targetIds.back();\n    }\n\n    // ---- Outer ordering: multi-start greedy + swap-based SA with O(1) delta ----\n    // Empty move edges:\n    // cost edge: 100 * dist(end_u, start_v)\n    // ops edge:  dist(end_u, start_v)\n    // Origin (0,0) is the initial empty truck position.\n    int originId = cellId(0,0,N);\n\n    vector<long long> originCost(M, 0);\n    vector<int> originSteps(M, 0);\n    for (int i = 0; i < M; i++) {\n        originSteps[i] = dist[originId][jobs[i].startId];\n        originCost[i] = 100LL * originSteps[i];\n    }\n\n    vector<vector<long long>> edgeCost(M, vector<long long>(M, 0));\n    vector<vector<int>> edgeSteps(M, vector<int>(M, 0));\n    for (int i = 0; i < M; i++) for (int j = 0; j < M; j++) if (i != j) {\n        edgeSteps[i][j] = dist[jobs[i].endId][jobs[j].startId];\n        edgeCost[i][j] = 100LL * edgeSteps[i][j];\n    }\n\n    long long internalCostSum = 0;\n    int internalStepsSum = 0;\n    int opsConstSum = 0; // +totalLoad op (1) and -amt ops per target (=targetCount)\n    for (int i = 0; i < M; i++) {\n        internalCostSum += jobs[i].internalCost;\n        internalStepsSum += jobs[i].internalSteps;\n        opsConstSum += 1 + jobs[i].targetCount;\n    }\n\n    const int OP_LIMIT = 100000;\n\n    auto totalOuterCost = [&](const vector<int> &order) -> long long {\n        long long emptyCost = originCost[order[0]];\n        for (int t = 0; t + 1 < (int)order.size(); t++) {\n            emptyCost += edgeCost[order[t]][order[t+1]];\n        }\n        return internalCostSum + emptyCost;\n    };\n\n    auto totalOps = [&](const vector<int> &order) -> int {\n        int ops = originSteps[order[0]] + internalStepsSum + opsConstSum;\n        for (int t = 0; t + 1 < (int)order.size(); t++) {\n            ops += edgeSteps[order[t]][order[t+1]];\n        }\n        return ops;\n    };\n\n    auto makeGreedy = [&](int seedVariant) -> vector<int> {\n        mt19937 rg(seedVariant * 1000003 + 17);\n        vector<int> order;\n        order.reserve(M);\n        vector<char> used(M, 0);\n\n        // pick first: minimum originCost with random tie among top candidates\n        vector<pair<long long,int>> firstCand;\n        firstCand.reserve(M);\n        for (int i = 0; i < M; i++) firstCand.push_back({originCost[i], i});\n        nth_element(firstCand.begin(), firstCand.begin() + min(3, M), firstCand.end(),\n                    [](auto &a, auto &b){ return a.first < b.first; });\n        sort(firstCand.begin(), firstCand.begin() + min(3, M),\n             [](auto &a, auto &b){ return a.first < b.first; });\n        int pick0 = (min(3, M) == 1 ? 0 : (int)(rg() % min(3, M)));\n        int cur = firstCand[pick0].second;\n        used[cur] = 1;\n        order.push_back(cur);\n\n        while ((int)order.size() < M) {\n            int last = order.back();\n            vector<pair<long long,int>> cand;\n            cand.reserve(M - (int)order.size());\n            for (int j = 0; j < M; j++) if (!used[j]) {\n                cand.push_back({edgeCost[last][j], j});\n            }\n            sort(cand.begin(), cand.end(), [](auto &a, auto &b){ return a.first < b.first; });\n            int take = min(4, (int)cand.size());\n            int pick = (take == 1 ? 0 : (int)(rg() % take));\n            int nxt = cand[pick].second;\n            used[nxt] = 1;\n            order.push_back(nxt);\n        }\n        return order;\n    };\n\n    auto swapDelta = [&](const vector<int> &order, int p, int q,\n                         long long &deltaCost, int &deltaOps) {\n        // Compute delta for swapping positions p<q in O(1)\n        if (p > q) swap(p,q);\n        int x = order[p], y = order[q];\n\n        // old origin\n        long long oldOrigin = 0, newOrigin = 0;\n        if (p == 0) {\n            oldOrigin = originCost[x];\n            newOrigin = originCost[y];\n        } else if (q == 0) {\n            oldOrigin = originCost[x];\n            newOrigin = originCost[y]; // since order[0]=x still; but if q==0 implies p<q impossible since p<q and q==0 => p<0, can't\n        } else {\n            oldOrigin = originCost[order[0]];\n            newOrigin = oldOrigin;\n        }\n\n        long long oldEdges = 0, newEdges = 0;\n        int oldOpsEdges = 0, newOpsEdges = 0;\n\n        auto getEndpoint = [&](int pos, bool useSwap) -> int {\n            // pos is position index in order, and endpoints after swap are:\n            // if pos==p -> y, if pos==q -> x else unchanged\n            if (pos == p) return y;\n            if (pos == q) return x;\n            return order[pos];\n        };\n\n        // affected edge indices in [0..M-2]:\n        int a1 = p-1, a2 = p, b1 = q-1, b2 = q;\n        // use a small set\n        int idxs[4] = {a1,a2,b1,b2};\n        for (int z = 0; z < 4; z++) {\n            int i = idxs[z];\n            if (i < 0 || i >= M-1) continue; // edge between i and i+1 exists\n            int u_old = order[i];\n            int v_old = order[i+1];\n            oldEdges += edgeCost[u_old][v_old];\n            oldOpsEdges += edgeSteps[u_old][v_old];\n\n            int u_new = getEndpoint(i, true);\n            int v_new = getEndpoint(i+1, true);\n            newEdges += edgeCost[u_new][v_new];\n            newOpsEdges += edgeSteps[u_new][v_new];\n        }\n\n        // Important: if the same edge index appears twice in idxs, we'd double count.\n        // Here indices are distinct enough, but p and q adjacency can cause duplicates (e.g., p-1==q-1).\n        // Fix by subtracting duplicates via recomputation with a boolean mark.\n        // Since M<=400, we can do a safe approach: recompute using boolean marker in O(1).\n        // We'll overwrite with a safe marker approach:\n\n        // Recompute safely:\n        oldEdges = newEdges = 0;\n        oldOpsEdges = newOpsEdges = 0;\n        bool seen[405] = {false};\n        for (int z = 0; z < 4; z++) {\n            int i = idxs[z];\n            if (i < 0 || i >= M-1) continue;\n            if (seen[i]) continue;\n            seen[i] = true;\n\n            int u_old = order[i];\n            int v_old = order[i+1];\n            oldEdges += edgeCost[u_old][v_old];\n            oldOpsEdges += edgeSteps[u_old][v_old];\n\n            int u_new = getEndpoint(i, true);\n            int v_new = getEndpoint(i+1, true);\n            newEdges += edgeCost[u_new][v_new];\n            newOpsEdges += edgeSteps[u_new][v_new];\n        }\n\n        deltaCost = (newOrigin - oldOrigin) + (newEdges - oldEdges);\n        deltaOps = (newOpsEdges - oldOpsEdges); // origin ops unchanged; include origin delta if p==0 similarly:\n        // If p==0, origin steps changed too:\n        if (p == 0) deltaOps += (originSteps[y] - originSteps[x]);\n    };\n\n    vector<int> bestFeasible;\n    long long bestFeasibleCost = (1LL<<62);\n\n    // Multi-start\n    int RESTARTS = 4;\n    int OUT_ITERS = 160000; // fast due to O(1) delta\n    for (int rs = 0; rs < RESTARTS; rs++) {\n        vector<int> order = makeGreedy(rs+1);\n        long long curCost = totalOuterCost(order);\n        int curOps = totalOps(order);\n\n        vector<int> curOrder = order;\n\n        long long bestLocalFeasCost = (1LL<<62);\n        vector<int> bestLocalFeasOrder;\n\n        // SA schedule\n        double T = 3.0e7;\n        for (int it = 0; it < OUT_ITERS; it++) {\n            int p = rng() % M;\n            int q = rng() % M;\n            if (p == q) continue;\n            if (p > q) swap(p,q);\n\n            long long dCost = 0;\n            int dOps = 0;\n            swapDelta(curOrder, p, q, dCost, dOps);\n\n            long long newCost = curCost + dCost;\n            int newOps = curOps + dOps;\n\n            bool accept = false;\n            if (newCost < curCost) accept = true;\n            else {\n                double prob = exp((double)(curCost - newCost) / T);\n                if ((double)(rng() % 1000000) / 1000000.0 < prob) accept = true;\n            }\n\n            if (accept) {\n                swap(curOrder[p], curOrder[q]);\n                curCost = newCost;\n                curOps = newOps;\n\n                if (curOps <= OP_LIMIT && curCost < bestLocalFeasCost) {\n                    bestLocalFeasCost = curCost;\n                    bestLocalFeasOrder = curOrder;\n                }\n            }\n\n            T *= 0.99997;\n        }\n\n        if (!bestLocalFeasOrder.empty() && bestLocalFeasCost < bestFeasibleCost) {\n            bestFeasibleCost = bestLocalFeasCost;\n            bestFeasible = bestLocalFeasOrder;\n        }\n    }\n\n    // Fallback (should be feasible in practice)\n    if (bestFeasible.empty()) {\n        bestFeasible = makeGreedy(999);\n    }\n\n    // ---- Output operations for bestFeasible ----\n    vector<string> ops;\n    ops.reserve(100000);\n\n    int r = 0, c = 0;\n    for (int idx : bestFeasible) {\n        const Job &jb = jobs[idx];\n\n        auto [sr, sc] = cellRC(jb.startId, N);\n        movePath(r, c, sr, sc, ops);\n\n        ops.push_back(\"+\" + to_string(jb.totalLoad));\n\n        int rr = r, cc = c;\n        for (int t = 0; t < (int)jb.targetIds.size(); t++) {\n            int tid = jb.targetIds[t];\n            int amt = jb.amounts[t];\n            auto [tr, tc] = cellRC(tid, N);\n            movePath(rr, cc, tr, tc, ops);\n            ops.push_back(\"-\" + to_string(amt));\n        }\n        r = rr; c = cc;\n\n        if ((int)ops.size() > 100000) {\n            // As a last resort, output order from greedy restart 0\n            // (still should usually be within limit; otherwise any attempt will likely be illegal).\n            // To avoid WA by illegal output, we just stop.\n            return 0;\n        }\n    }\n\n    for (auto &s : ops) cout << s << \"\\n\";\n    return 0;\n}","ahc035":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\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    int N, M, T;\n    cin >> N >> M >> T;\n\n    const int seed_count = 2 * N * (N - 1);\n    const int C = N * N;\n\n    vector<vector<int>> X(seed_count, vector<int>(M));\n    for (int k = 0; k < seed_count; k++) {\n        for (int l = 0; l < M; l++) cin >> X[k][l];\n    }\n\n    auto posId = [&](int i, int j) { return i * N + j; };\n\n    // Edges (right + down)\n    vector<pair<int,int>> edges;\n    edges.reserve(seed_count);\n    for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) {\n        if (i + 1 < N) edges.push_back({posId(i, j), posId(i + 1, j)});\n        if (j + 1 < N) edges.push_back({posId(i, j), posId(i, j + 1)});\n    }\n    const int E = (int)edges.size(); // 60\n\n    // 4-neighborhood positions + degrees\n    vector<vector<int>> adjPos(C);\n    vector<int> degPos(C, 0);\n    for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) {\n        int u = posId(i, j);\n        auto addNb = [&](int ni, int nj) {\n            if (0 <= ni && ni < N && 0 <= nj && nj < N)\n                adjPos[u].push_back(posId(ni, nj));\n        };\n        addNb(i - 1, j);\n        addNb(i + 1, j);\n        addNb(i, j - 1);\n        addNb(i, j + 1);\n        degPos[u] = (int)adjPos[u].size();\n    }\n\n    // incident edge bitmask per position (E<=60)\n    vector<uint64_t> incMask(C, 0);\n    for (int ei = 0; ei < E; ei++) {\n        auto [u, v] = edges[ei];\n        incMask[u] |= (1ULL << ei);\n        incMask[v] |= (1ULL << ei);\n    }\n\n    // aff[p][q] = edge indices affected by swapping positions p and q\n    vector<vector<vector<int>>> aff(C, vector<vector<int>>(C));\n    for (int p = 0; p < C; p++) for (int q = 0; q < C; q++) if (p != q) {\n        uint64_t m = incMask[p] | incMask[q];\n        vector<int> lst;\n        while (m) {\n            int b = __builtin_ctzll(m);\n            lst.push_back(b);\n            m &= (m - 1);\n        }\n        aff[p][q] = std::move(lst);\n    }\n\n    mt19937_64 rng((uint64_t)chrono::high_resolution_clock::now().time_since_epoch().count());\n\n    auto solve_one_turn = [&]() -> vector<int> {\n        // V_k\n        vector<int> V(seed_count, 0);\n        for (int k = 0; k < seed_count; k++) {\n            int s = 0;\n            for (int l = 0; l < M; l++) s += X[k][l];\n            V[k] = s;\n        }\n\n        // argmax per component\n        vector<int> argMax(M, 0);\n        for (int l = 0; l < M; l++) {\n            int bestk = 0;\n            for (int k = 1; k < seed_count; k++) if (X[k][l] > X[bestk][l]) bestk = k;\n            argMax[l] = bestk;\n        }\n\n        // Score proxy between seeds (60x60) for edges\n        const double Z = 2.0;\n        const double alphaUB = 0.8;\n\n        vector<vector<ll>> score(seed_count, vector<ll>(seed_count, 0));\n\n        for (int a = 0; a < seed_count; a++) {\n            for (int b = a; b < seed_count; b++) {\n                int ub = 0;\n                double EV = (V[a] + V[b]) / 2.0;\n                double varSum = 0.0;\n                for (int l = 0; l < M; l++) {\n                    int xa = X[a][l], xb = X[b][l];\n                    ub += max(xa, xb);\n                    double d = (double)xa - (double)xb;\n                    varSum += (d * d) / 4.0;\n                }\n                double sd = sqrt(max(0.0, varSum));\n                double tail = EV + Z * sd;\n                if (tail > (double)ub) tail = (double)ub;\n\n                ll ub2 = 1LL * ub * ub;\n                ll tail2 = (ll)(tail * tail + 0.5);\n\n                ll sc = (ll)(alphaUB * (double)ub2 + (1.0 - alphaUB) * (double)tail2 + 0.5);\n                score[a][b] = score[b][a] = sc;\n            }\n        }\n\n        // Candidate seeds for (bestA,bestB)\n        vector<int> byV(seed_count);\n        iota(byV.begin(), byV.end(), 0);\n        sort(byV.begin(), byV.end(), [&](int a, int b){ return V[a] > V[b]; });\n\n        vector<int> cand;\n        int topV = min(seed_count, 28);\n        for (int i = 0; i < topV; i++) cand.push_back(byV[i]);\n        for (int l = 0; l < M; l++) cand.push_back(argMax[l]);\n        sort(cand.begin(), cand.end());\n        cand.erase(unique(cand.begin(), cand.end()), cand.end());\n\n        // Best adjacent seed pair under proxy score\n        ll bestPairScore = -1;\n        int bestA = cand[0], bestB = cand[0];\n        for (int i = 0; i < (int)cand.size(); i++) {\n            for (int j = i + 1; j < (int)cand.size(); j++) {\n                int a = cand[i], b = cand[j];\n                ll sc = score[a][b];\n                if (sc > bestPairScore || (sc == bestPairScore && V[a] + V[b] > V[bestA] + V[bestB])) {\n                    bestPairScore = sc;\n                    bestA = a; bestB = b;\n                }\n            }\n        }\n        if (bestA == bestB) bestB = byV[1];\n\n        // -------- Improved seed subset selection (key change) --------\n        // Build a strong core S, then greedily add seeds that pair well with S_top (not just bestA/bestB).\n        vector<char> used(seed_count, 0);\n        vector<int> chosen;\n        chosen.reserve(C);\n\n        auto addSeed = [&](int k) {\n            if (!used[k]) {\n                used[k] = 1;\n                chosen.push_back(k);\n            }\n        };\n\n        addSeed(bestA);\n        addSeed(bestB);\n        for (int l = 0; l < M; l++) addSeed(argMax[l]);\n\n        // function to compute quality of candidate k given chosen\n        auto quality = [&](int k, const vector<int>& S) -> ll {\n            // take top subset by V among S\n            static int Sidx[60];\n            (void)Sidx;\n            vector<int> tmp = S;\n            sort(tmp.begin(), tmp.end(), [&](int a, int b){ return V[a] > V[b]; });\n\n            int take = min<int>(10, tmp.size());\n            ll sumPair = 0;\n            for (int i = 0; i < take; i++) sumPair += score[k][tmp[i]];\n            // small bias toward high total V\n            ll biasV = (ll)V[k] * 500; \n            return sumPair + biasV;\n        };\n\n        while ((int)chosen.size() < C) {\n            // current core S for quality evaluation\n            const vector<int>& S = chosen;\n\n            vector<pair<ll,int>> qlist;\n            qlist.reserve(seed_count - chosen.size());\n            for (int k = 0; k < seed_count; k++) if (!used[k]) {\n                ll q = quality(k, S);\n                qlist.push_back({q, k});\n            }\n\n            // pick among top few to reduce variance\n            int pickTop = min<int>(5, (int)qlist.size());\n            nth_element(qlist.begin(), qlist.begin() + pickTop, qlist.end(),\n                        [&](auto &a, auto &b){ return a.first > b.first; });\n            qlist.resize(pickTop);\n            sort(qlist.begin(), qlist.end(), [&](auto &a, auto &b){ return a.first > b.first; });\n\n            int idx = (pickTop == 1 ? 0 : (int)(rng() % pickTop));\n            addSeed(qlist[idx].second);\n        }\n\n        // Calculate objective for a placement\n        auto calcObj = [&](const vector<int>& Apos) -> ll {\n            ll obj = 0;\n            for (int ei = 0; ei < E; ei++) {\n                auto [u, v] = edges[ei];\n                obj += score[Apos[u]][Apos[v]];\n            }\n            return obj;\n        };\n\n        // placement candidates for (bestA,bestB): top-degree-sum edges (moderate diversity)\n        vector<pair<int,int>> edgeList = edges;\n        sort(edgeList.begin(), edgeList.end(), [&](auto &p, auto &q){\n            int sp = degPos[p.first] + degPos[p.second];\n            int sq = degPos[q.first] + degPos[q.second];\n            return sp > sq;\n        });\n\n        const int topPairEdges = 3; // keep moderate\n        vector<pair<int,int>> placements;\n        for (int i = 0; i < min(topPairEdges, (int)edgeList.size()); i++) {\n            auto [u,v] = edgeList[i];\n            placements.push_back({u,v});\n            if (u != v) placements.push_back({v,u});\n        }\n        sort(placements.begin(), placements.end());\n        placements.erase(unique(placements.begin(), placements.end()), placements.end());\n        if (placements.empty()) placements.push_back({0,1});\n\n        // SA + greedy fill\n        int restarts = 4;\n        int iters = 12000;\n\n        vector<int> globalBestApos(C, 0);\n        ll globalBestObj = LLONG_MIN;\n\n        for (auto [pA0, pB0] : placements) {\n            for (int r = 0; r < restarts; r++) {\n                uint64_t seedR = splitmix64(rng() + (uint64_t)pA0 * 1315423911ULL\n                                                + (uint64_t)pB0 * 2654435761ULL\n                                                + (uint64_t)r * 1013904223ULL);\n                mt19937_64 rg(seedR);\n\n                vector<int> Apos(C, -1);\n                vector<int> remaining = chosen;\n\n                auto takeSeed = [&](int k) {\n                    auto it = find(remaining.begin(), remaining.end(), k);\n                    if (it != remaining.end()) remaining.erase(it);\n                };\n\n                Apos[pA0] = bestA; takeSeed(bestA);\n                if (pB0 == pA0) {\n                    // guard: choose any other cell (should not happen)\n                    for (int pos = 0; pos < C; pos++) if (pos != pA0) { pB0 = pos; break; }\n                }\n                Apos[pB0] = bestB; takeSeed(bestB);\n\n                // filled neighbor counts\n                vector<int> filledCnt(C, 0);\n                vector<char> isFilled(C, 0), isUnfilled(C, 1);\n                int filled = 0;\n                for (int p = 0; p < C; p++) if (Apos[p] != -1) {\n                    isFilled[p] = 1;\n                    isUnfilled[p] = 0;\n                    filled++;\n                }\n                for (int p = 0; p < C; p++) if (isFilled[p]) {\n                    for (int nb : adjPos[p]) filledCnt[nb]++;\n                }\n\n                auto pickNextPos = [&]() -> int {\n                    int bestCnt = -1, bestDeg = -1;\n                    vector<int> ties;\n                    for (int p = 0; p < C; p++) if (isUnfilled[p]) {\n                        int cnt = filledCnt[p];\n                        int dg = degPos[p];\n                        if (cnt > bestCnt || (cnt == bestCnt && dg > bestDeg)) {\n                            bestCnt = cnt;\n                            bestDeg = dg;\n                            ties.clear();\n                            ties.push_back(p);\n                        } else if (cnt == bestCnt && dg == bestDeg) {\n                            ties.push_back(p);\n                        }\n                    }\n                    if (!ties.empty()) return ties[(size_t)(rg() % ties.size())];\n                    for (int p = 0; p < C; p++) if (isUnfilled[p]) return p;\n                    return 0;\n                };\n\n                // Fill remaining cells\n                vector<pair<ll,int>> candGain;\n                candGain.reserve(remaining.size());\n\n                while (filled < C) {\n                    int p = pickNextPos();\n                    candGain.clear();\n\n                    for (int s : remaining) {\n                        ll gsum = 0;\n                        for (int nb : adjPos[p]) {\n                            if (Apos[nb] != -1) gsum += score[s][Apos[nb]];\n                        }\n                        // slight V bias to reduce unlucky picks\n                        gsum += (ll)V[s] * 5;\n                        candGain.push_back({gsum, s});\n                    }\n\n                    int topK = min<int>(7, (int)candGain.size());\n                    nth_element(candGain.begin(), candGain.begin() + topK, candGain.end(),\n                                [&](auto &a, auto &b){ return a.first > b.first; });\n                    candGain.resize(topK);\n                    sort(candGain.begin(), candGain.end(),\n                         [&](auto &a, auto &b){ return a.first > b.first; });\n\n                    int pickIdx = (topK == 1 ? 0 : (int)(rg() % topK));\n                    int seedSel = candGain[pickIdx].second;\n\n                    Apos[p] = seedSel;\n                    takeSeed(seedSel);\n\n                    isUnfilled[p] = 0;\n                    isFilled[p] = 1;\n                    filled++;\n                    for (int nb : adjPos[p]) filledCnt[nb]++;\n                }\n\n                ll curObj = calcObj(Apos);\n                if (curObj > globalBestObj) {\n                    globalBestObj = curObj;\n                    globalBestApos = Apos;\n                }\n\n                double avgEdge = (double)curObj / (double)E;\n                double temp0 = max(1.0, avgEdge * 0.9);\n\n                // SA swaps\n                for (int it = 0; it < iters; it++) {\n                    int p = (int)(rg() % C);\n                    int q = (int)(rg() % C);\n                    if (p == q) continue;\n                    int sp = Apos[p], sq = Apos[q];\n                    if (sp == sq) continue;\n\n                    ll delta = 0;\n                    for (int ei : aff[p][q]) {\n                        auto [u, v] = edges[ei];\n\n                        int su_old = (u == p ? sp : (u == q ? sq : Apos[u]));\n                        int sv_old = (v == p ? sp : (v == q ? sq : Apos[v]));\n                        ll oldTerm = score[su_old][sv_old];\n\n                        int su_new = (u == p ? sq : (u == q ? sp : Apos[u]));\n                        int sv_new = (v == p ? sq : (v == q ? sp : Apos[v]));\n                        ll newTerm = score[su_new][sv_new];\n\n                        delta += newTerm - oldTerm;\n                    }\n\n                    if (delta >= 0) {\n                        swap(Apos[p], Apos[q]);\n                        curObj += delta;\n                    } else {\n                        double frac = (double)it / (double)iters;\n                        double temp = temp0 * (1.0 - frac) * (1.0 - frac) + 1e-6;\n                        double pr = exp((double)delta / temp);\n                        if (uniform_real_distribution<double>(0.0, 1.0)(rg) < pr) {\n                            swap(Apos[p], Apos[q]);\n                            curObj += delta;\n                        }\n                    }\n\n                    if (curObj > globalBestObj) {\n                        globalBestObj = curObj;\n                        globalBestApos = Apos;\n                    }\n                }\n            }\n        }\n\n        return globalBestApos;\n    };\n\n    for (int tt = 0; tt < T; tt++) {\n        vector<int> A = solve_one_turn();\n\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                if (j) cout << ' ';\n                cout << A[posId(i,j)];\n            }\n            cout << '\\n';\n        }\n        cout.flush();\n\n        for (int k = 0; k < seed_count; k++) {\n            for (int l = 0; l < M; l++) cin >> X[k][l];\n        }\n    }\n    return 0;\n}","ahc038":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Pt { int x, y; };\n\nstatic inline char mvChar(uint8_t mv) {\n    static const char MCH[5] = {'.','U','D','L','R'};\n    return MCH[mv];\n}\nstatic inline char rotChar(uint8_t rot) {\n    static const char RCH[3] = {'.','L','R'}; // L=CCW, R=CW\n    return RCH[rot];\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, V;\n    cin >> N >> M >> V;\n    vector<string> s(N), t(N);\n    for (int i = 0; i < N; i++) cin >> s[i];\n    for (int i = 0; i < N; i++) cin >> t[i];\n\n    vector<vector<int>> occ(N, vector<int>(N, 0));\n    for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) occ[i][j] = (s[i][j] == '1');\n\n    // A: cells that currently have takoyaki but are not targets => need pickup\n    // B: cells that are targets but currently empty => need release\n    vector<Pt> A, B;\n    A.reserve(M); B.reserve(M);\n    for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) {\n        bool si = (s[i][j] == '1');\n        bool ti = (t[i][j] == '1');\n        if (si && !ti) A.push_back({i,j});\n        if (!si && ti) B.push_back({i,j});\n    }\n    if (A.empty()) {\n        // If M=0 impossible by constraints, but safe.\n        // Output minimal legal arm with no operations.\n        cout << 2 << \"\\n\";\n        cout << 0 << \" \" << 1 << \"\\n\";\n        cout << 0 << \" \" << 0 << \"\\n\";\n        return 0;\n    }\n\n    // Arm design: V' = 2, edge length L\n    int Vp = 2;\n    int L = (N - 1) / 2;\n    if (L < 1) L = 1;\n    if (L > N - 1) L = N - 1;\n\n    auto inRange = [&](int x, int y) {\n        return 0 <= x && x < N && 0 <= y && y < N;\n    };\n\n    // State: (root_x, root_y, dir), dir = 0:R,1:D,2:L,3:U\n    array<int,4> dx{0, 1, 0, -1};\n    array<int,4> dy{1, 0, -1, 0};\n\n    int S = N * N * 4;\n    auto encode = [&](int rx, int ry, int dir) {\n        return ((rx * N + ry) * 4 + dir);\n    };\n\n    vector<int> rootX(S), rootY(S), dirOf(S);\n    for (int rx = 0; rx < N; rx++) for (int ry = 0; ry < N; ry++) {\n        for (int d = 0; d < 4; d++) {\n            int id = encode(rx, ry, d);\n            rootX[id] = rx;\n            rootY[id] = ry;\n            dirOf[id] = d;\n        }\n    }\n\n    struct Edge {\n        int to;\n        uint8_t mv;   // 0='.',1='U',2='D',3='L',4='R'\n        uint8_t rot;  // 0='.',1='L'(CCW),2='R'(CW)\n    };\n\n    // Operation 1 move root: '.' U D L R (only if new root in range)\n    // Operation 2 rotate at vertex 1 (fingertip leaf): '.' L R\n    array<pair<int,int>,5> mvDelta{{\n        {0,0},{-1,0},{+1,0},{0,-1},{0,+1}\n    }};\n\n    auto applyRotDir = [&](int d, uint8_t rot) -> int {\n        // CCW 'L' => dir-1. CW 'R' => dir+1\n        if (rot == 1) return (d + 3) & 3;\n        if (rot == 2) return (d + 1) & 3;\n        return d;\n    };\n\n    vector<vector<Edge>> adj(S);\n    for (int st = 0; st < S; st++) {\n        int rx = rootX[st], ry = rootY[st], d = dirOf[st];\n        adj[st].clear();\n        for (uint8_t mv = 0; mv < 5; mv++) {\n            int nrx = rx + mvDelta[mv].first;\n            int nry = ry + mvDelta[mv].second;\n            if (!inRange(nrx, nry)) continue;\n            for (uint8_t rot = 0; rot < 3; rot++) {\n                int nd = applyRotDir(d, rot);\n                int to = encode(nrx, nry, nd);\n                adj[st].push_back({to, mv, rot});\n            }\n        }\n    }\n\n    // Precompute all-pairs shortest distances on state graph and predecessor for reconstruction.\n    const uint16_t INF = 65535;\n    vector<uint16_t> distAll((size_t)S * S, INF);\n    vector<uint16_t> prevStateAll((size_t)S * S, INF);\n    vector<uint8_t> prevMvAll((size_t)S * S, 0);\n    vector<uint8_t> prevRotAll((size_t)S * S, 0);\n\n    vector<int> distRow(S);\n    vector<int> prevRow(S);\n    vector<uint8_t> prevMvRow(S), prevRotRow(S);\n    queue<int> q;\n\n    for (int st = 0; st < S; st++) {\n        fill(distRow.begin(), distRow.end(), -1);\n        fill(prevRow.begin(), prevRow.end(), -1);\n\n        while (!q.empty()) q.pop();\n        distRow[st] = 0;\n        prevRow[st] = st;\n        prevMvRow[st] = 0;\n        prevRotRow[st] = 0;\n        q.push(st);\n\n        while (!q.empty()) {\n            int v = q.front(); q.pop();\n            for (auto &e : adj[v]) {\n                int u = e.to;\n                if (distRow[u] != -1) continue;\n                distRow[u] = distRow[v] + 1;\n                prevRow[u] = v;\n                prevMvRow[u] = e.mv;\n                prevRotRow[u] = e.rot;\n                q.push(u);\n            }\n        }\n\n        size_t base = (size_t)st * S;\n        for (int to = 0; to < S; to++) {\n            if (distRow[to] == -1) continue;\n            distAll[base + to] = (uint16_t)distRow[to];\n            prevStateAll[base + to] = (uint16_t)prevRow[to];\n            prevMvAll[base + to] = prevMvRow[to];\n            prevRotAll[base + to] = prevRotRow[to];\n        }\n    }\n\n    // Precompute states where fingertip equals a given cell (cx,cy).\n    // Fingertip = (root_x + dx[dir]*L, root_y + dy[dir]*L).\n    // => root = (cx - dx[dir]*L, cy - dy[dir]*L)\n    int NN = N * N;\n    vector<array<int,4>> statesForCell(NN);\n    vector<int> cntForCell(NN, 0);\n\n    for (int cx = 0; cx < N; cx++) for (int cy = 0; cy < N; cy++) {\n        int cid = cx * N + cy;\n        int cnt = 0;\n        for (int dir = 0; dir < 4; dir++) {\n            int rx = cx - dx[dir] * L;\n            int ry = cy - dy[dir] * L;\n            if (!inRange(rx, ry)) continue;\n            statesForCell[cid][cnt++] = encode(rx, ry, dir);\n            if (cnt == 4) break;\n        }\n        cntForCell[cid] = cnt;\n    }\n\n    // Precompute best release cost from pState to any qState whose fingertip==dstCell.\n    // Release segment cost includes 'P':\n    //   if dist(pState,qState)==0 => 1 turn, else => dist turns.\n    vector<uint16_t> bestRelCost((size_t)S * NN, INF);\n    vector<uint16_t> bestRelChoice((size_t)S * NN, INF);\n\n    for (int p = 0; p < S; p++) {\n        for (int dstCell = 0; dstCell < NN; dstCell++) {\n            uint16_t best = INF;\n            uint16_t bestQ = INF;\n            int cntQ = cntForCell[dstCell];\n            for (int i = 0; i < cntQ; i++) {\n                int qState = statesForCell[dstCell][i];\n                uint16_t d2 = distAll[(size_t)p * S + qState];\n                if (d2 == INF) continue;\n                uint16_t relTurns = (d2 == 0 ? 1 : d2);\n                if (relTurns < best || (relTurns == best && qState < bestQ)) {\n                    best = relTurns;\n                    bestQ = (uint16_t)qState;\n                }\n            }\n            bestRelCost[(size_t)p * NN + dstCell] = best;\n            bestRelChoice[(size_t)p * NN + dstCell] = bestQ;\n        }\n    }\n\n    auto pickupMinToCell = [&](int curState, int cellId, int &bestP) -> uint16_t {\n        uint16_t best = INF;\n        int chooseP = -1;\n        int cntP = cntForCell[cellId];\n        for (int i = 0; i < cntP; i++) {\n            int pState = statesForCell[cellId][i];\n            uint16_t d1 = distAll[(size_t)curState * S + pState];\n            if (d1 == INF) continue;\n            uint16_t pickTurns = (d1 == 0 ? 1 : d1);\n            if (pickTurns < best || (pickTurns == best && pState < chooseP)) {\n                best = pickTurns;\n                chooseP = pState;\n            }\n        }\n        bestP = chooseP;\n        return best;\n    };\n\n    // Choose initial root (printed) with dir=0 (edge extends right).\n    // We'll consider roots that make fingertip coincide with a few source cells.\n    int startDir = 0;\n    int bestRx = 0, bestRy = 0;\n    uint64_t bestInitScore = (1ull<<60);\n\n    // Watch sources sorted by distance to centroid\n    vector<Pt> watch = A;\n    {\n        double cx = 0, cy = 0;\n        for (auto &p : watch) { cx += p.x; cy += p.y; }\n        cx /= watch.size(); cy /= watch.size();\n        sort(watch.begin(), watch.end(), [&](const Pt& a, const Pt& b){\n            double da = (a.x-cx)*(a.x-cx) + (a.y-cy)*(a.y-cy);\n            double db = (b.x-cx)*(b.x-cx) + (b.y-cy)*(b.y-cy);\n            return da < db;\n        });\n        if ((int)watch.size() > 15) watch.resize(15);\n    }\n\n    // Candidate roots: derived from watch sources (fingertip aligned to that cell) plus (0,0)\n    vector<Pt> candRoots;\n    candRoots.reserve(50);\n    candRoots.push_back({0,0});\n    for (auto &src : watch) {\n        int rx = src.x;\n        int ry = src.y - dy[startDir] * L; // dir=0 => dy=1 => ry=src.y-L\n        if (inRange(rx, ry)) candRoots.push_back({rx, ry});\n    }\n    // Deduplicate\n    sort(candRoots.begin(), candRoots.end(), [&](const Pt& a, const Pt& b){\n        if (a.x != b.x) return a.x < b.x;\n        return a.y < b.y;\n    });\n    candRoots.erase(unique(candRoots.begin(), candRoots.end(), [&](const Pt& a, const Pt& b){\n        return a.x == b.x && a.y == b.y;\n    }), candRoots.end());\n\n    for (auto &rc : candRoots) {\n        int curState = encode(rc.x, rc.y, startDir);\n        uint64_t score = 0;\n        bool ok = true;\n        int k = min<int>(10, (int)watch.size());\n        for (int i = 0; i < k; i++) {\n            int cellId = watch[i].x * N + watch[i].y;\n            int dummyP = -1;\n            uint16_t c = pickupMinToCell(curState, cellId, dummyP);\n            if (c == INF) { ok = false; break; }\n            score += c;\n        }\n        if (ok && score < bestInitScore) {\n            bestInitScore = score;\n            bestRx = rc.x; bestRy = rc.y;\n        }\n    }\n\n    int curState = encode(bestRx, bestRy, startDir);\n\n    // Segment execution: append shortest transitions from startState->goalState and put 'P' on last turn.\n    vector<string> ops;\n    ops.reserve(100000);\n\n    auto appendSegmentWithP = [&](int st, int goal) {\n        if (ops.size() >= 100000) return;\n\n        if (st == goal) {\n            ops.push_back(\"...P\"); // no move/rot, finger does P\n            return;\n        }\n        uint16_t d = distAll[(size_t)st * S + goal];\n        if (d == INF) exit(0);\n        int steps = (int)d;\n\n        vector<pair<uint8_t,uint8_t>> edges;\n        edges.reserve(steps);\n\n        int cur = goal;\n        for (int i = 0; i < steps; i++) {\n            size_t idx = (size_t)st * S + cur;\n            uint16_t pre = prevStateAll[idx];\n            if (pre == INF) exit(0);\n            uint8_t mv = prevMvAll[idx];\n            uint8_t rot = prevRotAll[idx];\n            edges.push_back({mv, rot});\n            cur = (int)pre;\n        }\n        reverse(edges.begin(), edges.end());\n\n        // Output steps turns\n        for (int i = 0; i < steps; i++) {\n            bool last = (i == steps - 1);\n            string stg;\n            stg.push_back(mvChar(edges[i].first));\n            stg.push_back(rotChar(edges[i].second));\n            stg.push_back('.');\n            stg.push_back(last ? 'P' : '.');\n            ops.push_back(stg);\n        }\n    };\n\n    // Main greedy matching:\n    // Pick a source from A and a destination from B that minimize exact (pickup turns + release turns).\n    // Use candidate restriction by minimal pickup cost.\n    const int Ksrc = 30;\n\n    while (!A.empty() && !B.empty()) {\n        if ((int)ops.size() >= 100000) break;\n\n        // Candidate sources: smallest pickupMinToCell from current state\n        vector<pair<uint16_t,int>> srcCand; // (pickupCost, index in A)\n        srcCand.reserve(A.size());\n        for (int i = 0; i < (int)A.size(); i++) {\n            int cellId = A[i].x * N + A[i].y;\n            int bestPtmp = -1;\n            uint16_t c = pickupMinToCell(curState, cellId, bestPtmp);\n            if (c != INF) srcCand.push_back({c, i});\n        }\n        if (srcCand.empty()) break;\n        sort(srcCand.begin(), srcCand.end());\n        if ((int)srcCand.size() > Ksrc) srcCand.resize(Ksrc);\n\n        struct BestPair {\n            uint32_t total;\n            int ai, bj;\n            int pState, qState;\n        } best{UINT32_MAX, -1, -1, -1, -1};\n\n        // Evaluate all dst for each candidate src\n        for (auto [pickLB, ai] : srcCand) {\n            Pt src = A[ai];\n            int srcCell = src.x * N + src.y;\n            int cntP = cntForCell[srcCell];\n            if (cntP == 0) continue;\n\n            for (int bj = 0; bj < (int)B.size(); bj++) {\n                Pt dst = B[bj];\n                int dstCell = dst.x * N + dst.y;\n\n                uint32_t localBest = UINT32_MAX;\n                int localP = -1, localQ = -1;\n\n                // min over pStates\n                for (int k = 0; k < cntP; k++) {\n                    int pState = statesForCell[srcCell][k];\n                    uint16_t d1 = distAll[(size_t)curState * S + pState];\n                    if (d1 == INF) continue;\n                    uint16_t pickTurns = (d1 == 0 ? 1 : d1);\n\n                    uint16_t rel = bestRelCost[(size_t)pState * NN + dstCell];\n                    if (rel == INF) continue;\n\n                    uint32_t total = (uint32_t)pickTurns + (uint32_t)rel;\n                    if (total < localBest || (total == localBest && pState < localP)) {\n                        localBest = total;\n                        localP = pState;\n                        localQ = (int)bestRelChoice[(size_t)pState * NN + dstCell];\n                    }\n                }\n\n                if (localP == -1) continue;\n\n                // Feasibility wrt remaining turn limit\n                if ((int)ops.size() + (int)localBest > 100000) continue;\n\n                if (localBest < best.total) {\n                    best = {localBest, ai, bj, localP, localQ};\n                }\n            }\n        }\n\n        if (best.ai == -1) break; // can't fit within limit\n\n        // Execute: curState -> pState (pickup) -> qState (release)\n        Pt src = A[best.ai];\n        Pt dst = B[best.bj];\n        int pState = best.pState;\n        int qState = best.qState;\n\n        // Sanity checks for legality\n        // pickup on src\n        if (occ[src.x][src.y] != 1) exit(0);\n        // release on dst\n        if (occ[dst.x][dst.y] != 0) exit(0);\n\n        appendSegmentWithP(curState, pState);\n        occ[src.x][src.y] = 0;\n\n        appendSegmentWithP(pState, qState);\n        occ[dst.x][dst.y] = 1;\n\n        curState = qState;\n\n        // Remove used endpoints\n        A[best.ai] = A.back(); A.pop_back();\n        B[best.bj] = B.back(); B.pop_back();\n    }\n\n    // Output arm + root + operations\n    cout << Vp << \"\\n\";\n    cout << 0 << \" \" << L << \"\\n\";\n    cout << bestRx << \" \" << bestRy << \"\\n\";\n    for (auto &st : ops) cout << st << \"\\n\";\n    return 0;\n}","ahc039":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int MAXC = 100000;\n\nstruct Pt {\n    int x, y;\n    int w; // +1 mackerel, -1 sardine\n};\n\n// Fenwick tree over x-values storing sorted y with prefix sums of weights.\n// Supports sumRect over inclusive integer coordinates: [xL..xR] x [yB..yT].\nstruct RangeSum2D {\n    int nx = 0;\n    vector<int> xvals;\n    vector<vector<int>> yList;          // sorted y in each BIT node\n    vector<vector<long long>> pref;    // prefix sum of weights aligned with yList\n\n    RangeSum2D() = default;\n    explicit RangeSum2D(const vector<Pt>& pts) { build(pts); }\n\n    void build(const vector<Pt>& pts) {\n        xvals.clear();\n        xvals.reserve(pts.size());\n        for (auto &p : pts) xvals.push_back(p.x);\n        sort(xvals.begin(), xvals.end());\n        xvals.erase(unique(xvals.begin(), xvals.end()), xvals.end());\n        nx = (int)xvals.size();\n\n        vector<vector<pair<int,int>>> tmp(nx + 1); // (y, w)\n\n        for (auto &p : pts) {\n            int xi = (int)(lower_bound(xvals.begin(), xvals.end(), p.x) - xvals.begin()) + 1; // 1-indexed\n            for (int i = xi; i <= nx; i += i & -i) tmp[i].push_back({p.y, p.w});\n        }\n\n        yList.assign(nx + 1, {});\n        pref.assign(nx + 1, {});\n        for (int i = 1; i <= nx; i++) {\n            auto &v = tmp[i];\n            sort(v.begin(), v.end(), [](auto &a, auto &b){ return a.first < b.first; });\n            yList[i].resize(v.size());\n            pref[i].resize(v.size());\n            long long run = 0;\n            for (size_t j = 0; j < v.size(); j++) {\n                yList[i][j] = v[j].first;\n                run += (long long)v[j].second;\n                pref[i][j] = run;\n            }\n        }\n    }\n\n    long long prefSum(int X, int Y) const {\n        if (X < 0 || Y < 0) return 0;\n        int xi = (int)(upper_bound(xvals.begin(), xvals.end(), X) - xvals.begin()); // 0..nx\n        long long res = 0;\n        for (int i = xi; i > 0; i -= i & -i) {\n            if (yList[i].empty()) continue;\n            int k = (int)(upper_bound(yList[i].begin(), yList[i].end(), Y) - yList[i].begin());\n            if (k > 0) res += pref[i][k - 1];\n        }\n        return res;\n    }\n\n    long long sumRect(int xL, int xR, int yB, int yT) const {\n        if (xL > xR || yB > yT) return 0;\n        xL = max(xL, 0); xR = min(xR, MAXC);\n        yB = max(yB, 0); yT = min(yT, MAXC);\n        if (xL > xR || yB > yT) return 0;\n        long long A = prefSum(xR, yT);\n        long long B = prefSum(xL - 1, yT);\n        long long C = prefSum(xR, yB - 1);\n        long long D = prefSum(xL - 1, yB - 1);\n        return A - B - C + D;\n    }\n};\n\nstatic inline void normalizeRect(int &xL, int &xR, int &yB, int &yT) {\n    xL = max(0, min(MAXC, xL));\n    xR = max(0, min(MAXC, xR));\n    yB = max(0, min(MAXC, yB));\n    yT = max(0, min(MAXC, yT));\n    if (xL > xR) swap(xL, xR);\n    if (yB > yT) swap(yB, yT);\n\n    if (xL == xR) {\n        if (xR < MAXC) xR = xL + 1;\n        else xL = xR - 1;\n    }\n    if (yB == yT) {\n        if (yT < MAXC) yT = yB + 1;\n        else yB = yT - 1;\n    }\n\n    xL = max(0, min(MAXC, xL));\n    xR = max(0, min(MAXC, xR));\n    yB = max(0, min(MAXC, yB));\n    yT = max(0, min(MAXC, yT));\n    if (xL > xR) swap(xL, xR);\n    if (yB > yT) swap(yB, yT);\n}\n\n// L-shape score = union of two rectangles for one missing quadrant.\n// type:\n// 0: bottom-left quadrant removed (keeps bottom band + right-upper band)\n//    polygon vertices: (xR,yB)->(xL,yB)->(xL,yM)->(xM,yM)->(xM,yT)->(xR,yT)\n// 1: bottom-right removed\n// 2: top-left removed\n// 3: top-right removed\nstatic inline long long exactLScore(const RangeSum2D &ds,\n                                     int xL, int xR, int yB, int yT,\n                                     int xM, int yM, int type) {\n    if (!(xL < xM && xM < xR && yB < yM && yM < yT)) return LLONG_MIN / 4;\n\n    auto rect = [&](int a, int b, int c, int d)->long long {\n        if (a > b || c > d) return 0LL;\n        return ds.sumRect(a, b, c, d);\n    };\n\n    if (type == 0) {\n        // [xL..xR]x[yB..yM] U [xM..xR]x[yM..yT]\n        long long s1 = rect(xL, xR, yB, yM);\n        long long s2 = rect(xM, xR, yM, yT);\n        long long ov = rect(xM, xR, yM, yM);\n        return s1 + s2 - ov;\n    } else if (type == 1) {\n        // [xL..xR]x[yB..yM] U [xL..xM]x[yM..yT]\n        long long s1 = rect(xL, xR, yB, yM);\n        long long s2 = rect(xL, xM, yM, yT);\n        long long ov = rect(xL, xM, yM, yM);\n        return s1 + s2 - ov;\n    } else if (type == 2) {\n        // [xL..xR]x[yM..yT] U [xM..xR]x[yB..yM]\n        long long s1 = rect(xL, xR, yM, yT);\n        long long s2 = rect(xM, xR, yB, yM);\n        long long ov = rect(xM, xR, yM, yM);\n        return s1 + s2 - ov;\n    } else {\n        // type == 3\n        // [xL..xR]x[yM..yT] U [xL..xM]x[yB..yM]\n        long long s1 = rect(xL, xR, yM, yT);\n        long long s2 = rect(xL, xM, yB, yM);\n        long long ov = rect(xL, xM, yM, yM);\n        return s1 + s2 - ov;\n    }\n}\n\nstatic inline vector<int> sampleInRange(const vector<int> &sortedUniq,\n                                        int L, int R,\n                                        int cap, bool strictInside) {\n    if (L > R) swap(L, R);\n    int lo = strictInside ? L + 1 : L;\n    int hi = strictInside ? R - 1 : R;\n    lo = max(lo, 0);\n    hi = min(hi, MAXC);\n    if (lo > hi) return {};\n\n    auto itL = lower_bound(sortedUniq.begin(), sortedUniq.end(), lo);\n    auto itR = upper_bound(sortedUniq.begin(), sortedUniq.end(), hi);\n    vector<int> cand(itL, itR);\n    if ((int)cand.size() <= cap) return cand;\n\n    // Quantile sampling\n    vector<int> out;\n    out.reserve(cap);\n    int n = (int)cand.size();\n    for (int i = 0; i < cap; i++) {\n        out.push_back(cand[(long long)i * n / cap]);\n    }\n    sort(out.begin(), out.end());\n    out.erase(unique(out.begin(), out.end()), out.end());\n    return out;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    cin >> N;\n    vector<Pt> pts;\n    pts.reserve(2 * N);\n\n    for (int i = 0; i < N; i++) {\n        int x, y; cin >> x >> y;\n        pts.push_back({x, y, +1});\n    }\n    for (int i = 0; i < N; i++) {\n        int x, y; cin >> x >> y;\n        pts.push_back({x, y, -1});\n    }\n\n    RangeSum2D ds(pts);\n\n    vector<int> xs, ys;\n    xs.reserve(2 * N);\n    ys.reserve(2 * N);\n    for (auto &p : pts) { xs.push_back(p.x); ys.push_back(p.y); }\n    sort(xs.begin(), xs.end());\n    xs.erase(unique(xs.begin(), xs.end()), xs.end());\n    sort(ys.begin(), ys.end());\n    ys.erase(unique(ys.begin(), ys.end()), ys.end());\n\n    // Coarse grid for rectangle candidate discovery\n    const int G = 170;\n    const int SZ = MAXC + 1;\n\n    auto cellOf = [&](int v) -> int {\n        return (int)((long long)v * G / SZ); // 0..G-1\n    };\n    auto lowerBoundCell = [&](int c) -> int { // inclusive\n        return (int)((long long)c * SZ / G);\n    };\n    auto upperBoundCell = [&](int c) -> int { // inclusive\n        long long ub = (long long)(c + 1) * SZ / G - 1;\n        ub = max(0LL, min((long long)MAXC, ub));\n        return (int)ub;\n    };\n\n    vector<vector<int>> A(G, vector<int>(G, 0));\n    for (auto &p : pts) {\n        int cx = cellOf(p.x);\n        int cy = cellOf(p.y);\n        A[cx][cy] += p.w;\n    }\n\n    auto kadane = [&](const vector<long long> &arr) -> tuple<long long,int,int> {\n        long long cur = arr[0], best = arr[0];\n        int curL = 0, bestL = 0, bestR = 0;\n        for (int i = 1; i < G; i++) {\n            if (cur < 0) { cur = arr[i]; curL = i; }\n            else cur += arr[i];\n            if (cur > best) { best = cur; bestL = curL; bestR = i; }\n        }\n        return {best, bestL, bestR};\n    };\n\n    struct CellRect { long long sum; int x0,x1,y0,y1; };\n    struct MinCmp { bool operator()(const CellRect& a, const CellRect& b) const { return a.sum > b.sum; } };\n\n    const int TOPK = 18;\n    priority_queue<CellRect, vector<CellRect>, MinCmp> minpq;\n    vector<long long> temp(G);\n\n    for (int x0 = 0; x0 < G; x0++) {\n        fill(temp.begin(), temp.end(), 0LL);\n        for (int x1 = x0; x1 < G; x1++) {\n            for (int y = 0; y < G; y++) temp[y] += A[x1][y];\n            auto [s, yl, yr] = kadane(temp);\n            CellRect cr{s, x0, x1, yl, yr};\n            if ((int)minpq.size() < TOPK) minpq.push(cr);\n            else if (cr.sum > minpq.top().sum) { minpq.pop(); minpq.push(cr); }\n        }\n    }\n\n    vector<CellRect> candCells;\n    while (!minpq.empty()) { candCells.push_back(minpq.top()); minpq.pop(); }\n    sort(candCells.begin(), candCells.end(), [](auto &a, auto &b){ return a.sum > b.sum; });\n\n    mt19937_64 rng((uint64_t)chrono::high_resolution_clock::now().time_since_epoch().count());\n\n    enum Kind { RECT=0, L=1 };\n    Kind bestKind = RECT;\n    long long bestScore = LLONG_MIN;\n\n    int best_xL=0, best_xR=0, best_yB=0, best_yT=0;\n    int best_xM=0, best_yM=0, best_type=0;\n\n    auto considerRect = [&](int xL,int xR,int yB,int yT){\n        normalizeRect(xL,xR,yB,yT);\n        long long d = ds.sumRect(xL,xR,yB,yT);\n        if (d > bestScore) {\n            bestScore = d;\n            bestKind = RECT;\n            best_xL=xL; best_xR=xR; best_yB=yB; best_yT=yT;\n        }\n    };\n\n    auto considerL = [&](int xL,int xR,int yB,int yT,int xM,int yM,int type){\n        long long d = exactLScore(ds, xL,xR,yB,yT,xM,yM,type);\n        if (d > bestScore) {\n            bestScore = d;\n            bestKind = L;\n            best_xL=xL; best_xR=xR; best_yB=yB; best_yT=yT;\n            best_xM=xM; best_yM=yM; best_type=type;\n        }\n    };\n\n    auto localImproveRect = [&](int xL,int xR,int yB,int yT){\n        normalizeRect(xL,xR,yB,yT);\n        long long curBest = ds.sumRect(xL,xR,yB,yT);\n\n        const int RANGE = 8000;\n        const int CAP = 230;\n\n        vector<int> candX = sampleInRange(xs, xL - RANGE, xR + RANGE, CAP, false);\n        vector<int> candY = sampleInRange(ys, yB - RANGE, yT + RANGE, CAP, false);\n\n        candX.push_back(xL); candX.push_back(xR);\n        candY.push_back(yB); candY.push_back(yT);\n        sort(candX.begin(), candX.end());\n        candX.erase(unique(candX.begin(), candX.end()), candX.end());\n        sort(candY.begin(), candY.end());\n        candY.erase(unique(candY.begin(), candY.end()), candY.end());\n\n        if (candX.size() < 2 || candY.size() < 2) {\n            considerRect(xL,xR,yB,yT);\n            return array<int,4>{xL,xR,yB,yT};\n        }\n\n        auto rndIdx = [&](int sz)->int { return (int)(rng() % (uint64_t)sz); };\n\n        // Random perturbation\n        int RND_TRIES = 520;\n        for (int it = 0; it < RND_TRIES; it++) {\n            int a = candX[rndIdx((int)candX.size())];\n            int b = candX[rndIdx((int)candX.size())];\n            int c = candY[rndIdx((int)candY.size())];\n            int d = candY[rndIdx((int)candY.size())];\n            int nL=min(a,b), nR=max(a,b), nB=min(c,d), nT=max(c,d);\n            if (nR - nL < 1 || nT - nB < 1) continue;\n            long long val = ds.sumRect(nL,nR,nB,nT);\n            if (val > curBest) {\n                curBest = val;\n                xL=nL; xR=nR; yB=nB; yT=nT;\n            }\n        }\n\n        // Coordinate descent\n        int sweeps = 5;\n        for (int sw = 0; sw < sweeps; sw++) {\n            bool improved = false;\n\n            // xL\n            {\n                long long bestV = curBest;\n                int bestX = xL;\n                for (int nxL : candX) {\n                    if (nxL >= xR) continue;\n                    long long val = ds.sumRect(nxL, xR, yB, yT);\n                    if (val > bestV) { bestV = val; bestX = nxL; }\n                }\n                if (bestX != xL) { xL = bestX; curBest = bestV; improved = true; }\n            }\n            // xR\n            {\n                long long bestV = curBest;\n                int bestX = xR;\n                for (int nxR : candX) {\n                    if (nxR <= xL) continue;\n                    long long val = ds.sumRect(xL, nxR, yB, yT);\n                    if (val > bestV) { bestV = val; bestX = nxR; }\n                }\n                if (bestX != xR) { xR = bestX; curBest = bestV; improved = true; }\n            }\n            // yB\n            {\n                long long bestV = curBest;\n                int bestY = yB;\n                for (int nyB : candY) {\n                    if (nyB >= yT) continue;\n                    long long val = ds.sumRect(xL, xR, nyB, yT);\n                    if (val > bestV) { bestV = val; bestY = nyB; }\n                }\n                if (bestY != yB) { yB = bestY; curBest = bestV; improved = true; }\n            }\n            // yT\n            {\n                long long bestV = curBest;\n                int bestY = yT;\n                for (int nyT : candY) {\n                    if (nyT <= yB) continue;\n                    long long val = ds.sumRect(xL, xR, yB, nyT);\n                    if (val > bestV) { bestV = val; bestY = nyT; }\n                }\n                if (bestY != yT) { yT = bestY; curBest = bestV; improved = true; }\n            }\n\n            if (!improved) break;\n        }\n\n        considerRect(xL,xR,yB,yT);\n        return array<int,4>{xL,xR,yB,yT};\n    };\n\n    // Improve top rectangles\n    vector<array<int,4>> improvedRects;\n    improvedRects.reserve(min(30, (int)candCells.size()));\n\n    int rectCandidatesToImprove = min(25, (int)candCells.size());\n    for (int i = 0; i < rectCandidatesToImprove; i++) {\n        auto &cc = candCells[i];\n        int xL = lowerBoundCell(cc.x0);\n        int xR = upperBoundCell(cc.x1);\n        int yB = lowerBoundCell(cc.y0);\n        int yT = upperBoundCell(cc.y1);\n        improvedRects.push_back(localImproveRect(xL,xR,yB,yT));\n    }\n\n    // Sort by exact rectangle score and keep best few\n    sort(improvedRects.begin(), improvedRects.end(), [&](auto &a, auto &b){\n        long long sa = ds.sumRect(a[0],a[1],a[2],a[3]);\n        long long sb = ds.sumRect(b[0],b[1],b[2],b[3]);\n        return sa > sb;\n    });\n    int keepRects = min(8, (int)improvedRects.size());\n\n    // L-shape search\n    for (int ri = 0; ri < keepRects; ri++) {\n        auto r = improvedRects[ri];\n        int xL=r[0], xR=r[1], yB=r[2], yT=r[3];\n        if (!(xL + 1 < xR && yB + 1 < yT)) continue;\n\n        const int CAPX = 95, CAPY = 95;\n        vector<int> innerX = sampleInRange(xs, xL, xR, CAPX, true);\n        vector<int> innerY = sampleInRange(ys, yB, yT, CAPY, true);\n        if (innerX.empty() || innerY.empty()) continue;\n\n        // Cap semi-exhaustive pair count\n        // If too large, downsample one dimension.\n        long long pairs = 1LL * innerX.size() * innerY.size();\n        if (pairs > 9000) {\n            // downsample Y to keep pairs <= 9000\n            int targetY = (int)(9000 / max<size_t>(1, innerX.size()));\n            targetY = max(targetY, 1);\n            if ((int)innerY.size() > targetY) {\n                shuffle(innerY.begin(), innerY.end(), rng);\n                innerY.resize(targetY);\n                sort(innerY.begin(), innerY.end());\n                innerY.erase(unique(innerY.begin(), innerY.end()), innerY.end());\n            }\n        }\n\n        // Semi-exhaustive over inner points\n        for (int type = 0; type < 4; type++) {\n            for (int xM : innerX) {\n                if (!(xL < xM && xM < xR)) continue;\n                for (int yM : innerY) {\n                    if (!(yB < yM && yM < yT)) continue;\n                    considerL(xL,xR,yB,yT,xM,yM,type);\n                }\n            }\n        }\n\n        // Additional random L trials\n        int TRIES = 900;\n        uniform_int_distribution<int> dx(0, (int)innerX.size() - 1);\n        uniform_int_distribution<int> dy(0, (int)innerY.size() - 1);\n        uniform_int_distribution<int> dt(0, 3);\n\n        for (int it = 0; it < TRIES; it++) {\n            int xM = innerX[dx(rng)];\n            int yM = innerY[dy(rng)];\n            int type = dt(rng);\n            considerL(xL,xR,yB,yT,xM,yM,type);\n        }\n    }\n\n    // Output polygon\n    if (bestKind == RECT) {\n        cout << 4 << \"\\n\";\n        cout << best_xL << \" \" << best_yB << \"\\n\";\n        cout << best_xR << \" \" << best_yB << \"\\n\";\n        cout << best_xR << \" \" << best_yT << \"\\n\";\n        cout << best_xL << \" \" << best_yT << \"\\n\";\n    } else {\n        int xL=best_xL, xR=best_xR, yB=best_yB, yT=best_yT, xM=best_xM, yM=best_yM, type=best_type;\n        vector<pair<int,int>> v;\n        // CCW\n        if (type == 0) { // missing top-left\n            v = {{xR,yB},{xL,yB},{xL,yM},{xM,yM},{xM,yT},{xR,yT}};\n        } else if (type == 1) { // missing top-right\n            v = {{xL,yB},{xR,yB},{xR,yM},{xM,yM},{xM,yT},{xL,yT}};\n        } else if (type == 2) { // missing bottom-left\n            v = {{xM,yM},{xL,yM},{xL,yT},{xR,yT},{xR,yB},{xM,yB}};\n        } else { // type == 3, missing bottom-right\n            v = {{xM,yM},{xR,yM},{xR,yT},{xL,yT},{xL,yB},{xM,yB}};\n        }\n        cout << 6 << \"\\n\";\n        for (auto &p: v) cout << p.first << \" \" << p.second << \"\\n\";\n    }\n\n    return 0;\n}","ahc040":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct SplitMix64 {\n    uint64_t x;\n    explicit SplitMix64(uint64_t seed) : x(seed) {}\n    uint64_t next_u64() {\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 next_int(int l, int r) { // inclusive\n        return l + (int)(next_u64() % (uint64_t)(r - l + 1));\n    }\n    double next_double() { // [0,1)\n        return (next_u64() >> 11) * (1.0 / 9007199254740992.0);\n    }\n};\n\nstatic inline long long choosePrefRotU(int i, const vector<long long>& wp, const vector<long long>& hp) {\n    // dir U: x step uses width -> minimize width\n    // rot=0 => width=wp, rot=1 => width=hp\n    return (hp[i] < wp[i]) ? 1LL : 0LL;\n}\nstatic inline long long choosePrefRotL(int i, const vector<long long>& wp, const vector<long long>& hp) {\n    // dir L: y step uses height -> minimize height\n    // rot=0 => height=hp, rot=1 => height=wp\n    return (wp[i] < hp[i]) ? 1LL : 0LL;\n}\n\nstruct Layout {\n    vector<int> rot;      // 0/1\n    vector<char> dir;     // 'U' or 'L'\n};\n\nstatic long long simulateObjBprev(const Layout& lay,\n                                   const vector<long long>& wp,\n                                   const vector<long long>& hp,\n                                   int N) {\n    // b_i = i-1 (and b_0 = -1), overlap-free guaranteed by slide simulation.\n    vector<long long> x(N), y(N), w(N), h(N);\n\n    long long W = 0, H = 0;\n    for (int i = 0; i < N; i++) {\n        if (lay.rot[i] == 0) { w[i] = wp[i]; h[i] = hp[i]; }\n        else { w[i] = hp[i]; h[i] = wp[i]; }\n\n        if (lay.dir[i] == 'U') {\n            if (i == 0) x[i] = 0;\n            else x[i] = x[i-1] + w[i-1]; // align with right edge of b=i-1\n            long long yy = 0;\n            for (int j = 0; j < i; j++) {\n                // x intervals overlap?\n                if (x[i] < x[j] + w[j] && x[j] < x[i] + w[i]) {\n                    yy = max(yy, y[j] + h[j]);\n                }\n            }\n            y[i] = yy;\n        } else { // 'L'\n            if (i == 0) y[i] = 0;\n            else y[i] = y[i-1] + h[i-1]; // align with bottom edge of b=i-1\n            long long xx = 0;\n            for (int j = 0; j < i; j++) {\n                // y intervals overlap?\n                if (y[i] < y[j] + h[j] && y[j] < y[i] + h[i]) {\n                    xx = max(xx, x[j] + w[j]);\n                }\n            }\n            x[i] = xx;\n        }\n        W = max(W, x[i] + w[i]);\n        H = max(H, y[i] + h[i]);\n    }\n    return W + H;\n}\n\nstatic long long simulateWHEvalBprev(const Layout& lay,\n                                      const vector<long long>& wp,\n                                      const vector<long long>& hp,\n                                      int N,\n                                      long long &Wout, long long &Hout) {\n    vector<long long> x(N), y(N), w(N), h(N);\n    long long W = 0, H = 0;\n\n    for (int i = 0; i < N; i++) {\n        if (lay.rot[i] == 0) { w[i] = wp[i]; h[i] = hp[i]; }\n        else { w[i] = hp[i]; h[i] = wp[i]; }\n\n        if (lay.dir[i] == 'U') {\n            if (i == 0) x[i] = 0;\n            else x[i] = x[i-1] + w[i-1];\n            long long yy = 0;\n            for (int j = 0; j < i; j++) {\n                if (x[i] < x[j] + w[j] && x[j] < x[i] + w[i]) {\n                    yy = max(yy, y[j] + h[j]);\n                }\n            }\n            y[i] = yy;\n        } else {\n            if (i == 0) y[i] = 0;\n            else y[i] = y[i-1] + h[i-1];\n            long long xx = 0;\n            for (int j = 0; j < i; j++) {\n                if (y[i] < y[j] + h[j] && y[j] < y[i] + h[i]) {\n                    xx = max(xx, x[j] + w[j]);\n                }\n            }\n            x[i] = xx;\n        }\n        W = max(W, x[i] + w[i]);\n        H = max(H, y[i] + h[i]);\n    }\n    Wout = W; Hout = H;\n    return W + H;\n}\n\n// Exact rotation optimization for the all-U chain:\n// objective = sum(width_i) + max(height_i), with width/height depend on rot.\nstatic vector<int> bestRotAllU(const vector<long long>& wp, const vector<long long>& hp) {\n    int N = (int)wp.size();\n    vector<long long> cand;\n    cand.reserve(2*N);\n    for(int i=0;i<N;i++){ cand.push_back(hp[i]); cand.push_back(wp[i]); }\n    sort(cand.begin(), cand.end());\n    cand.erase(unique(cand.begin(), cand.end()), cand.end());\n\n    const long long INF = (1LL<<62);\n    long long bestObj = INF;\n    long long bestH = cand[0];\n    vector<int> bestRot(N,0);\n\n    for(long long Hcap: cand) {\n        bool ok = true;\n        long long sumW = 0;\n        vector<int> rot(N,0);\n        for(int i=0;i<N;i++){\n            bool can0 = (hp[i] <= Hcap); // rot=0 => height=hp\n            bool can1 = (wp[i] <= Hcap); // rot=1 => height=wp\n            if(!can0 && !can1){ ok=false; break; }\n            int r;\n            long long w0 = wp[i], w1 = hp[i];\n            if(can0 && can1){\n                r = (w0 < w1) ? 0 : 1; // minimize width\n                if(w0==w1) r=0;\n            } else r = can0 ? 0 : 1;\n            rot[i]=r;\n            long long wi = (rot[i]==0 ? wp[i] : hp[i]);\n            sumW += wi;\n        }\n        if(!ok) continue;\n        long long obj = sumW + Hcap;\n        if(obj < bestObj){\n            bestObj = obj;\n            bestH = Hcap;\n            bestRot = rot;\n        }\n    }\n    (void)bestH;\n    return bestRot;\n}\n\n// Exact rotation optimization for the all-L chain:\n// objective = max(width_i) + sum(height_i)\nstatic vector<int> bestRotAllL(const vector<long long>& wp, const vector<long long>& hp) {\n    int N = (int)wp.size();\n    vector<long long> cand;\n    cand.reserve(2*N);\n    for(int i=0;i<N;i++){ cand.push_back(wp[i]); cand.push_back(hp[i]); }\n    sort(cand.begin(), cand.end());\n    cand.erase(unique(cand.begin(), cand.end()), cand.end());\n\n    const long long INF = (1LL<<62);\n    long long bestObj = INF;\n    long long bestW = cand[0];\n    vector<int> bestRot(N,0);\n\n    for(long long Wcap: cand) {\n        bool ok = true;\n        long long sumH = 0;\n        vector<int> rot(N,0);\n        for(int i=0;i<N;i++){\n            bool can0 = (wp[i] <= Wcap); // rot=0 => width=wp\n            bool can1 = (hp[i] <= Wcap); // rot=1 => width=hp\n            if(!can0 && !can1){ ok=false; break; }\n            int r;\n            long long h0 = hp[i], h1 = wp[i]; // height contributed\n            if(can0 && can1){\n                r = (h0 < h1) ? 0 : 1; // minimize height\n                if(h0==h1) r=0;\n            } else r = can0 ? 0 : 1;\n            rot[i]=r;\n            long long hi = (rot[i]==0 ? hp[i] : wp[i]);\n            sumH += hi;\n        }\n        if(!ok) continue;\n        long long obj = Wcap + sumH;\n        if(obj < bestObj){\n            bestObj = obj;\n            bestW = Wcap;\n            bestRot = rot;\n        }\n    }\n    (void)bestW;\n    return bestRot;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, T;\n    long long sigma;\n    cin >> N >> T >> sigma;\n    vector<long long> wp(N), hp(N);\n    for(int i=0;i<N;i++) cin >> wp[i] >> hp[i];\n\n    // Seed\n    uint64_t seed = 0x123456789abcdef0ULL;\n    seed ^= (uint64_t)N * 1000003ULL;\n    seed ^= (uint64_t)T * 10007ULL;\n    seed ^= (uint64_t)sigma * 911382323ULL;\n    for(int i=0;i<N;i++){\n        seed ^= (uint64_t)(wp[i] + 1000003LL*hp[i] + (i+1)*10007LL);\n        seed *= 1099511628211ULL;\n    }\n    SplitMix64 rng(seed);\n\n    // Baselines\n    Layout allU, allL;\n    allU.dir.assign(N,'U');\n    allL.dir.assign(N,'L');\n    allU.rot = bestRotAllU(wp,hp);\n    allL.rot = bestRotAllL(wp,hp);\n\n    vector<Layout> init;\n    init.push_back(allU);\n    init.push_back(allL);\n\n    // Split patterns\n    vector<int> splits = {N/4, N/2, 3*N/4};\n    for(int s: splits){\n        s = max(0, min(N, s));\n        Layout lay;\n        lay.dir.resize(N);\n        lay.rot.resize(N);\n        for(int i=0;i<N;i++){\n            lay.dir[i] = (i < s ? 'U' : 'L');\n            if(lay.dir[i]=='U') lay.rot[i] = (int)choosePrefRotU(i, wp, hp);\n            else lay.rot[i] = (int)choosePrefRotL(i, wp, hp);\n        }\n        init.push_back(lay);\n        // also reverse\n        Layout lay2 = lay;\n        for(int i=0;i<N;i++) lay2.dir[i] = (lay2.dir[i]=='U'?'L':'U');\n        for(int i=0;i<N;i++){\n            lay2.rot[i] = (lay2.dir[i]=='U' ? (int)choosePrefRotU(i,wp,hp) : (int)choosePrefRotL(i,wp,hp));\n        }\n        init.push_back(lay2);\n    }\n\n    // Alternating\n    for(int start=0; start<2; start++){\n        Layout lay;\n        lay.dir.resize(N);\n        lay.rot.resize(N);\n        for(int i=0;i<N;i++){\n            lay.dir[i] = ((i+start)%2==0 ? 'U' : 'L');\n            lay.rot[i] = (lay.dir[i]=='U' ? (int)choosePrefRotU(i,wp,hp) : (int)choosePrefRotL(i,wp,hp));\n        }\n        init.push_back(lay);\n    }\n\n    // Random initial\n    for(int k=0;k<4;k++){\n        Layout lay;\n        lay.dir.resize(N);\n        lay.rot.resize(N);\n        for(int i=0;i<N;i++){\n            lay.dir[i] = (rng.next_int(0,1)==0 ? 'U' : 'L');\n            // correlate rotation with dir preference, with some randomness\n            int pref = (lay.dir[i]=='U' ? (int)choosePrefRotU(i,wp,hp) : (int)choosePrefRotL(i,wp,hp));\n            lay.rot[i] = (rng.next_double() < 0.85 ? pref : pref^1);\n        }\n        init.push_back(lay);\n    }\n\n    // Rank init by predicted objective and pick top few to try\n    vector<pair<long long,int>> order;\n    order.reserve(init.size());\n    for(int i=0;i<(int)init.size();i++){\n        long long pred = simulateObjBprev(init[i], wp, hp, N);\n        order.push_back({pred,i});\n    }\n    sort(order.begin(), order.end());\n\n    int K = min(T, 10);\n    vector<Layout> tried;\n    tried.reserve(K);\n\n    Layout cur = init[order[0].second];\n    long long curMeas = (1LL<<62);\n\n    Layout bestLay = cur;\n    long long bestMeas = (1LL<<62);\n\n    auto outputLayout = [&](const Layout& lay){\n        cout << N << \"\\n\";\n        for(int i=0;i<N;i++){\n            int p = i;\n            int r = lay.rot[i];\n            char d = lay.dir[i];\n            int b = (i==0 ? -1 : i-1); // fixed b=i-1 for legality\n            cout << p << \" \" << r << \" \" << d << \" \" << b << \"\\n\";\n        }\n        cout << flush;\n    };\n\n    for(int ti=0; ti<K; ti++){\n        int idx = order[ti].second;\n        Layout cand = init[idx];\n        outputLayout(cand);\n        long long Wp,Hp;\n        cin >> Wp >> Hp;\n        long long meas = Wp + Hp;\n\n        tried.push_back(cand);\n\n        if(meas < bestMeas){\n            bestMeas = meas;\n            bestLay = cand;\n        }\n        if(meas < curMeas){\n            curMeas = meas;\n            cur = cand;\n        }\n    }\n\n    // For critical-index bias, compute from current best layout\n    auto computeCritical = [&](const Layout& lay, vector<int>& critical){\n        // run full simulation with arrays to identify indices reaching max W or max H (in predicted world).\n        vector<long long> x(N), y(N), w(N), h(N);\n        long long W=0,H=0;\n        for(int i=0;i<N;i++){\n            if(lay.rot[i]==0){ w[i]=wp[i]; h[i]=hp[i]; }\n            else { w[i]=hp[i]; h[i]=wp[i]; }\n            if(lay.dir[i]=='U'){\n                x[i] = (i==0?0:x[i-1]+w[i-1]);\n                long long yy=0;\n                for(int j=0;j<i;j++){\n                    if(x[i] < x[j]+w[j] && x[j] < x[i]+w[i]) yy=max(yy, y[j]+h[j]);\n                }\n                y[i]=yy;\n            } else {\n                y[i] = (i==0?0:y[i-1]+h[i-1]);\n                long long xx=0;\n                for(int j=0;j<i;j++){\n                    if(y[i] < y[j]+h[j] && y[j] < y[i]+h[i]) xx=max(xx, x[j]+w[j]);\n                }\n                x[i]=xx;\n            }\n            W=max(W, x[i]+w[i]);\n            H=max(H, y[i]+h[i]);\n        }\n        critical.clear();\n        for(int i=0;i<N;i++){\n            if(x[i]+w[i]==W || y[i]+h[i]==H) critical.push_back(i);\n        }\n        if(critical.empty()) critical.push_back(0);\n    };\n\n    vector<int> critical;\n    computeCritical(bestLay, critical);\n\n    auto mutateCandidate = [&](const Layout& base) {\n        Layout cand = base;\n\n        // sometimes do a global split reset\n        if(rng.next_double() < 0.12){\n            int s = rng.next_int(0, N);\n            for(int i=0;i<N;i++){\n                cand.dir[i] = (i < s ? 'U' : 'L');\n                cand.rot[i] = (cand.dir[i]=='U' ? (int)choosePrefRotU(i,wp,hp) : (int)choosePrefRotL(i,wp,hp));\n            }\n        } else {\n            int k = rng.next_int(1, 4);\n            for(int t=0;t<k;t++){\n                int i;\n                if(rng.next_double() < 0.55) i = critical[rng.next_int(0,(int)critical.size()-1)];\n                else i = rng.next_int(0, N-1);\n\n                int op = rng.next_int(0, 5);\n                if(op <= 1){\n                    // flip dir, maybe re-pick rotation for that dir\n                    cand.dir[i] = (cand.dir[i]=='U' ? 'L' : 'U');\n                    if(rng.next_double() < 0.7){\n                        cand.rot[i] = (cand.dir[i]=='U' ? (int)choosePrefRotU(i,wp,hp) : (int)choosePrefRotL(i,wp,hp));\n                    }\n                } else if(op <= 3){\n                    // flip rotation\n                    cand.rot[i] ^= 1;\n                } else {\n                    // set to preferred rotation for current dir\n                    cand.rot[i] = (cand.dir[i]=='U' ? (int)choosePrefRotU(i,wp,hp) : (int)choosePrefRotL(i,wp,hp));\n                    // sometimes also flip dir\n                    if(rng.next_double() < 0.25) cand.dir[i] = (cand.dir[i]=='U' ? 'L' : 'U');\n                }\n            }\n        }\n\n        return cand;\n    };\n\n    long long dummyW,dummyH;\n    for(int t = K; t < T; t++){\n        // choose base to mutate from\n        const Layout& base = (rng.next_double() < 0.75 ? bestLay : cur);\n\n        // generate several candidates and pick the best predicted\n        const int M = 8;\n        Layout bestCand = base;\n        long long bestPred = (1LL<<62);\n\n        for(int j=0;j<M;j++){\n            Layout cand = mutateCandidate(base);\n            long long pred = simulateObjBprev(cand, wp, hp, N);\n            if(pred < bestPred){\n                bestPred = pred;\n                bestCand = std::move(cand);\n            }\n        }\n\n        // Output best predicted candidate\n        outputLayout(bestCand);\n        cin >> dummyW >> dummyH;\n        long long meas = dummyW + dummyH;\n\n        if(meas < bestMeas){\n            bestMeas = meas;\n            bestLay = bestCand;\n            computeCritical(bestLay, critical);\n        }\n\n        // SA-like update of current using measured objective\n        bool accept = false;\n        if(meas <= curMeas){\n            accept = true;\n        } else {\n            // temperature schedule\n            long double prog = (long double)(t+1) / (long double)T;\n            long double temp = 200000.0L * (1.0L - prog) + 20000.0L; // tuned\n            long double delta = (long double)meas - (long double)curMeas;\n            long double prob = expl(-delta / temp);\n            if(rng.next_double() < prob) accept = true;\n        }\n\n        if(accept){\n            cur = bestCand;\n            curMeas = meas;\n        }\n    }\n\n    return 0;\n}","ahc041":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct RNG {\n    mt19937 rng;\n    RNG() {\n        rng.seed((uint32_t)chrono::steady_clock::now().time_since_epoch().count());\n    }\n    int randint(int l, int r) { // inclusive\n        uniform_int_distribution<int> dist(l, r);\n        return dist(rng);\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, H;\n    cin >> N >> M >> H;\n    vector<long long> A(N);\n    for (int i = 0; i < N; i++) cin >> A[i];\n\n    vector<vector<int>> g(N);\n    for (int i = 0; i < M; i++) {\n        int u, v;\n        cin >> u >> v;\n        g[u].push_back(v);\n        g[v].push_back(u);\n    }\n    for (int i = 0; i < N; i++) {\n        int x, y;\n        cin >> x >> y;\n    }\n\n    // Precompute pot[s] = sum_{u: dist(s,u)<=H} (dist+1)*A[u] on full graph\n    vector<long long> pot(N, 0);\n    vector<int> dist(N, -1);\n    queue<int> q;\n    for (int s = 0; s < N; s++) {\n        fill(dist.begin(), dist.end(), -1);\n        while (!q.empty()) q.pop();\n        dist[s] = 0;\n        q.push(s);\n        long long ps = 0;\n        while (!q.empty()) {\n            int x = q.front(); q.pop();\n            ps += (long long)(dist[x] + 1) * A[x];\n            if (dist[x] == H) continue;\n            for (int y : g[x]) {\n                if (dist[y] != -1) continue;\n                dist[y] = dist[x] + 1;\n                q.push(y);\n            }\n        }\n        pot[s] = ps;\n    }\n\n    vector<int> orderPot(N), orderA(N);\n    iota(orderPot.begin(), orderPot.end(), 0);\n    iota(orderA.begin(), orderA.end(), 0);\n    sort(orderPot.begin(), orderPot.end(), [&](int i, int j) {\n        if (pot[i] != pot[j]) return pot[i] > pot[j];\n        return A[i] > A[j];\n    });\n    sort(orderA.begin(), orderA.end(), [&](int i, int j) {\n        if (A[i] != A[j]) return A[i] > A[j];\n        return pot[i] > pot[j];\n    });\n\n    RNG R;\n    auto startTime = chrono::steady_clock::now();\n    const double TL = 1.93; // close to 2.0s with margin\n\n    vector<int> bestParent(N, -1);\n    long long bestScore = LLONG_MIN;\n\n    vector<char> assigned(N, 0);\n    vector<int> parentOut(N, -1);\n\n    // BFS buffers for evaluation/claim\n    vector<int> seen(N, 0), dtmp(N, 0);\n    int timer = 1;\n\n    // For unassigned set with O(1) deletion\n    vector<int> unass, posInUnass;\n    unass.reserve(N);\n    posInUnass.assign(N, -1);\n\n    auto remove_from_unass = [&](int v) {\n        int p = posInUnass[v];\n        if (p < 0) return;\n        int w = unass.back();\n        unass[p] = w;\n        posInUnass[w] = p;\n        unass.pop_back();\n        posInUnass[v] = -1;\n    };\n\n    // Evaluate attractiveness contribution if we build BFS tree rooted at root\n    // using current remaining-unassigned vertices, with depths = BFS shortest distances.\n    auto eval_root = [&](int root) -> long long {\n        timer++;\n        long long sc = 0;\n\n        vector<int> qv;\n        qv.clear();\n        qv.push_back(root);\n        seen[root] = timer;\n        dtmp[root] = 0;\n\n        sc += A[root];\n\n        for (int head = 0; head < (int)qv.size(); head++) {\n            int x = qv[head];\n            int dx = dtmp[x];\n            if (dx == H) continue;\n            for (int y : g[x]) {\n                if (assigned[y]) continue;\n                if (seen[y] == timer) continue;\n                seen[y] = timer;\n                dtmp[y] = dx + 1;\n                sc += (long long)(dtmp[y] + 1) * A[y];\n                qv.push_back(y);\n            }\n        }\n        return sc;\n    };\n\n    // Reroot optimization inside the claimed BFS-tree component.\n    // Uses:\n    // - compNodes: vertices in component\n    // - bfsParent[v] : parent in the BFS-tree (within component), bfsParent[root]=-1\n    // Updates parentOut[v] to match best feasible root (ecc <= H).\n    auto reroot_component = [&](const vector<int>& compNodes,\n                                const int bfsRoot,\n                                const vector<int>& bfsParent) -> long long {\n        int sz = (int)compNodes.size();\n        if (sz == 1) {\n            int v = compNodes[0];\n            parentOut[v] = -1;\n            return A[v]; // (0+1)*A\n        }\n\n        static vector<int> loc;\n        static int inited = 0;\n        if (!inited) { loc.assign(N, -1); inited = 1; }\n\n        for (int i = 0; i < sz; i++) loc[compNodes[i]] = i;\n\n        vector<vector<int>> adj(sz);\n        for (int v : compNodes) {\n            int p = bfsParent[v];\n            if (p == -1) continue;\n            int lv = loc[v], lp = loc[p];\n            adj[lv].push_back(lp);\n            adj[lp].push_back(lv);\n        }\n\n        auto bfs_farthest = [&](int src, vector<int>& outDist) -> int {\n            outDist.assign(sz, -1);\n            queue<int> qq;\n            qq.push(src);\n            outDist[src] = 0;\n            int far = src;\n            while (!qq.empty()) {\n                int x = qq.front(); qq.pop();\n                if (outDist[x] > outDist[far]) far = x;\n                for (int y : adj[x]) {\n                    if (outDist[y] != -1) continue;\n                    outDist[y] = outDist[x] + 1;\n                    qq.push(y);\n                }\n            }\n            return far;\n        };\n\n        vector<int> dist1, dist2;\n        int any = 0;\n        int end1 = bfs_farthest(any, dist1);\n        int end2 = bfs_farthest(end1, dist1); // dist1 now from end1\n        bfs_farthest(end2, dist2);           // dist2 now from end2\n\n        // Diameter endpoints are end1 and end2 (dist1 is from end1, dist2 from end2)\n        // Feasible roots satisfy ecc(v)=max(dist1[v],dist2[v]) <= H\n        // Compute weighted sum of distances S[v] = sum_u A[u]*dist(v,u) for all v in this tree.\n        // Weighted reroot DP.\n        // Root the tree at local 0.\n        int r0 = 0;\n        vector<int> parentL(sz, -1), order;\n        order.reserve(sz);\n        {\n            stack<int> st;\n            st.push(r0);\n            parentL[r0] = -2;\n            while (!st.empty()) {\n                int x = st.top(); st.pop();\n                order.push_back(x);\n                for (int y : adj[x]) {\n                    if (parentL[y] != -1) continue;\n                    parentL[y] = x;\n                    st.push(y);\n                }\n            }\n            parentL[r0] = -1;\n        }\n\n        // Need postorder: use reverse(order)\n        vector<long long> szW(sz, 0), down(sz, 0);\n        auto weightAtLocal = [&](int li) -> long long {\n            return A[compNodes[li]];\n        };\n\n        for (int i = (int)order.size() - 1; i >= 0; i--) {\n            int u = order[i];\n            szW[u] = weightAtLocal(u);\n            down[u] = 0;\n            for (int v : adj[u]) {\n                if (v == parentL[u]) continue;\n                szW[u] += szW[v];\n                down[u] += down[v] + szW[v];\n            }\n        }\n\n        long long totalW = szW[r0];\n        vector<long long> S(sz, 0);\n        S[r0] = down[r0];\n        for (int u : order) {\n            for (int v : adj[u]) {\n                if (v == parentL[u]) continue;\n                // Move root u -> v:\n                // S[v] = S[u] + totalW - 2*szW[v]\n                S[v] = S[u] + totalW - 2LL * szW[v];\n            }\n        }\n\n        long long sumA = totalW;\n        long long bestS = LLONG_MIN;\n        int bestRootLocal = r0;\n        for (int i = 0; i < sz; i++) {\n            int ecc = max(dist1[i], dist2[i]);\n            if (ecc <= H) {\n                if (S[i] > bestS) {\n                    bestS = S[i];\n                    bestRootLocal = i;\n                }\n            }\n        }\n\n        // Reorient tree from bestRootLocal\n        vector<int> parLocal(sz, -1);\n        queue<int> qq;\n        qq.push(bestRootLocal);\n        parLocal[bestRootLocal] = -2;\n        while (!qq.empty()) {\n            int u = qq.front(); qq.pop();\n            for (int v : adj[u]) {\n                if (parLocal[v] != -1) continue;\n                parLocal[v] = u;\n                qq.push(v);\n            }\n        }\n        for (int i = 0; i < sz; i++) {\n            int gv = compNodes[i];\n            int pLocal = parLocal[i];\n            if (i == bestRootLocal) parentOut[gv] = -1;\n            else parentOut[gv] = compNodes[pLocal];\n        }\n\n        for (int i = 0; i < sz; i++) loc[compNodes[i]] = -1;\n\n        return sumA + bestS;\n    };\n\n    // Claim a component rooted at root using BFS up to depth H (shortest distance tree),\n    // then reroot within that tree to maximize attractiveness under height<=H.\n    auto claim_root = [&](int root) -> long long {\n        timer++;\n        // BFS build component and BFS-tree parent pointers\n        vector<int> qv;\n        qv.clear();\n        vector<int> visited;\n        visited.reserve(256);\n\n        // BFS parent map for component nodes\n        vector<int> bfsParent; // will store for component nodes only via global parentBFS array below\n        // We'll use a global array parentTmpGlobal with enough size, but easiest here is local map:\n        // Since N small, we create a global-like vector and fill only visited nodes.\n        static vector<int> parentTmpGlobal;\n        static bool initTmp = false;\n        if (!initTmp) { parentTmpGlobal.assign(N, -1); initTmp = true; }\n\n        qv.push_back(root);\n        assigned[root] = 1;\n        parentTmpGlobal[root] = -1;\n        dtmp[root] = 0;\n        seen[root] = timer;\n        visited.push_back(root);\n\n        for (int head = 0; head < (int)qv.size(); head++) {\n            int x = qv[head];\n            int dx = dtmp[x];\n            if (dx == H) continue;\n            for (int y : g[x]) {\n                if (assigned[y]) continue;\n                if (seen[y] == timer) continue;\n                seen[y] = timer;\n                dtmp[y] = dx + 1;\n                assigned[y] = 1;\n                parentTmpGlobal[y] = x;\n                qv.push_back(y);\n                visited.push_back(y);\n            }\n        }\n\n        // Remove visited vertices from unassigned structure\n        for (int v : visited) remove_from_unass(v);\n\n        // Reroot within the BFS-tree\n        // Need bfsParent as vector<int> indexed by global vertex (but only values for visited used).\n        // We'll pass a vector<int> bfsParentGlobal of size N? too big per component; instead\n        // reroot_component takes bfsParent by global indexing via a vector<int>&.\n        // We'll create bfsParent by referencing parentTmpGlobal; easiest is to copy values for visited into a vector<int> and use loc mapping,\n        // but our reroot_component expects bfsParent[v] with v global. We'll provide a wrapper vector that is parentTmpGlobal itself.\n        // So: create a view by copying parentTmpGlobal into a vector<int> is expensive; instead modify reroot_component signature would be needed.\n        // We'll implement by building a temporary bfsParentGlobal vector of size N once and reusing parentTmpGlobal content.\n        // Since reroot_component indexes bfsParent[v], we can just pass parentTmpGlobal.\n        long long compScore = reroot_component(visited, root, parentTmpGlobal);\n\n        return compScore;\n    };\n\n    int attempts = 0;\n    while (true) {\n        double elapsed = chrono::duration<double>(chrono::steady_clock::now() - startTime).count();\n        if (elapsed > TL) break;\n        attempts++;\n\n        fill(assigned.begin(), assigned.end(), 0);\n        fill(parentOut.begin(), parentOut.end(), -1);\n\n        unass.clear();\n        unass.reserve(N);\n        posInUnass.assign(N, -1);\n        for (int i = 0; i < N; i++) {\n            unass.push_back(i);\n            posInUnass[i] = i;\n        }\n\n        long long totalScore = 0;\n\n        // temporary candidate marking\n        vector<int> candMark(N, 0);\n        int candTimer = 1;\n\n        while (!unass.empty()) {\n            int remaining = (int)unass.size();\n\n            int K = min(26, remaining);\n            int topPotCnt = min(12, K);\n            int topACnt = min(10, K - topPotCnt);\n            int topKeep = min(6, K);\n\n            // build candidates\n            vector<int> cand;\n            cand.reserve(K);\n\n            candTimer++;\n            // take best by pot\n            for (int v : orderPot) {\n                if ((int)cand.size() >= topPotCnt) break;\n                if (!assigned[v]) {\n                    if (candMark[v] != candTimer) {\n                        candMark[v] = candTimer;\n                        cand.push_back(v);\n                    }\n                }\n            }\n            // take best by A\n            for (int v : orderA) {\n                if ((int)cand.size() >= topPotCnt + topACnt) break;\n                if (!assigned[v]) {\n                    if (candMark[v] != candTimer) {\n                        candMark[v] = candTimer;\n                        cand.push_back(v);\n                    }\n                }\n            }\n\n            // random fill\n            while ((int)cand.size() < K) {\n                int idx = R.randint(0, remaining - 1);\n                int v = unass[idx];\n                if (candMark[v] != candTimer) {\n                    candMark[v] = candTimer;\n                    cand.push_back(v);\n                }\n            }\n\n            // evaluate candidates\n            vector<pair<long long,int>> scored;\n            scored.reserve(K);\n            for (int r : cand) {\n                long long sc = eval_root(r);\n                scored.push_back({sc, r});\n            }\n            sort(scored.begin(), scored.end(), [&](auto &p1, auto &p2) {\n                if (p1.first != p2.first) return p1.first > p2.first;\n                return A[p1.second] > A[p2.second];\n            });\n\n            int pickIdx = (topKeep == 1 ? 0 : R.randint(0, topKeep - 1));\n            int chosenRoot = scored[pickIdx].second;\n\n            totalScore += claim_root(chosenRoot);\n        }\n\n        if (totalScore > bestScore) {\n            bestScore = totalScore;\n            bestParent = parentOut;\n        }\n    }\n\n    for (int i = 0; i < N; i++) {\n        cout << bestParent[i] << (i + 1 == N ? '\\n' : ' ');\n    }\n    return 0;\n}","ahc042":"#include <bits/stdc++.h>\nusing namespace std;\n\nenum Dir { UP = 0, DOWN = 1, LEFT = 2, RIGHT = 3 };\n\nstruct Option {\n    int var; // which line-direction variable\n    int L;   // required shift length for this Oni\n    Dir d;\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<char>> fuku(N, vector<char>(N, 0));\n    vector<pair<int,int>> oni;\n    oni.reserve(2 * N);\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (C[i][j] == 'o') fuku[i][j] = 1;\n            else if (C[i][j] == 'x') oni.push_back({i, j});\n        }\n    }\n\n    const int M = (int)oni.size(); // guaranteed = 2N\n    const int V = 4 * N;          // variables: UP cols, DOWN cols, LEFT rows, RIGHT rows\n    const int64_t Tlimit = 4LL * N * N;\n    const int64_t limitSum = Tlimit / 2; // sum of line lengths (since T=2*sum)\n\n    auto varUp = [&](int col){ return col; };\n    auto varDown = [&](int col){ return N + col; };\n    auto varLeft = [&](int row){ return 2*N + row; };\n    auto varRight = [&](int row){ return 3*N + row; };\n\n    // Precompute maximum safe lengths per line-direction:\n    // UP on column j: remove top L cells [0..L-1], safe iff no fuku in those => L <= firstFukuRow\n    // DOWN on column j: remove bottom L cells [N-L..N-1], safe iff no fuku in those => L <= N-1-lastFukuRow\n    vector<int> maxUp(N), maxDown(N), maxLeft(N), maxRight(N);\n\n    for (int j = 0; j < N; j++) {\n        int first = N, last = -1;\n        for (int i = 0; i < N; i++) if (fuku[i][j]) {\n            first = min(first, i);\n            last = max(last, i);\n        }\n        maxUp[j] = first;\n        maxDown[j] = (last == -1 ? N : (N - 1 - last));\n    }\n    for (int i = 0; i < N; i++) {\n        int first = N, last = -1;\n        for (int j = 0; j < N; j++) if (fuku[i][j]) {\n            first = min(first, j);\n            last = max(last, j);\n        }\n        maxLeft[i] = first;\n        maxRight[i] = (last == -1 ? N : (N - 1 - last));\n    }\n\n    // Build options for each Oni\n    vector<vector<Option>> options(M);\n    for (int id = 0; id < M; id++) {\n        int i = oni[id].first, j = oni[id].second;\n\n        // UP: L = i+1\n        int Lup = i + 1;\n        if (Lup <= maxUp[j]) options[id].push_back({varUp(j), Lup, UP});\n\n        // DOWN: L = N-i\n        int Ldown = N - i;\n        if (Ldown <= maxDown[j]) options[id].push_back({varDown(j), Ldown, DOWN});\n\n        // LEFT: L = j+1\n        int Lleft = j + 1;\n        if (Lleft <= maxLeft[i]) options[id].push_back({varLeft(i), Lleft, LEFT});\n\n        // RIGHT: L = N-j\n        int Lright = N - j;\n        if (Lright <= maxRight[i]) options[id].push_back({varRight(i), Lright, RIGHT});\n\n        // By problem guarantee, at least one option exists.\n        if (options[id].empty()) {\n            // Fallback (should not happen)\n            // choose UP if possible else nothing\n        }\n    }\n\n    auto computeT_from_vals = [&](const vector<int>& val) -> int64_t {\n        int64_t sum = 0;\n        for (int x : val) sum += x;\n        return 2 * sum;\n    };\n\n    mt19937 rng((uint32_t)chrono::steady_clock::now().time_since_epoch().count());\n\n    auto randomInit = [&]() -> void {\n        // assignment arrays in outer scope\n    };\n\n    // Helper: build assignment structures from chosen option indices\n    auto buildFromAssignment = [&](const vector<int>& chosenIdx,\n                                   vector<int>& assignVar,\n                                   vector<int>& assignL,\n                                   vector<vector<int>>& bucket,\n                                   vector<int>& val,\n                                   int64_t& sumVal,\n                                   int64_t& T) {\n        assignVar.assign(M, -1);\n        assignL.assign(M, 0);\n        bucket.assign(V, {});\n        val.assign(V, 0);\n\n        for (int id = 0; id < M; id++) {\n            int idx = chosenIdx[id];\n            auto &op = options[id][idx];\n            assignVar[id] = op.var;\n            assignL[id] = op.L;\n            bucket[op.var].push_back(id);\n        }\n\n        for (int v = 0; v < V; v++) {\n            int mx = 0;\n            for (int id : bucket[v]) mx = max(mx, assignL[id]);\n            val[v] = mx;\n        }\n\n        sumVal = 0;\n        for (int x : val) sumVal += x;\n        T = 2 * sumVal;\n    };\n\n    // Local search step with O(|bucket[oldVar]|) recomputation for oldVar max-after-removal.\n    auto localSearch = [&](vector<int>& assignVar,\n                            vector<int>& assignL,\n                            vector<vector<int>>& bucket,\n                            vector<int>& val,\n                            int64_t& sumVal,\n                            int64_t& bestT,\n                            vector<int>& bestAssignVar,\n                            vector<int>& bestAssignL,\n                            int steps) {\n        // Maintain pos[id] for O(1) deletion from bucket[var]\n        vector<int> pos(M, -1);\n        for (int v = 0; v < V; v++) {\n            for (int k = 0; k < (int)bucket[v].size(); k++) {\n                pos[bucket[v][k]] = k;\n            }\n        }\n\n        auto tryMove = [&](int id, const Option& alt, double temp)->bool{\n            int oldVar = assignVar[id];\n            int newVar = alt.var;\n            if (newVar == oldVar) return false;\n\n            int newL = alt.L;\n\n            // newValOld = max assignL among bucket[oldVar] excluding id\n            int candOld = 0;\n            for (int other : bucket[oldVar]) {\n                if (other == id) continue;\n                candOld = max(candOld, assignL[other]);\n            }\n\n            int candNew = max(val[newVar], newL);\n\n            int deltaSum = (candOld - val[oldVar]) + (candNew - val[newVar]);\n\n            int64_t newSum = sumVal + deltaSum;\n            if (newSum > limitSum) return false;\n\n            if (deltaSum < 0) {\n                // accept\n            } else {\n                // simulated annealing\n                double prob = exp(-(double)deltaSum / temp);\n                uniform_real_distribution<double> U(0.0, 1.0);\n                if (U(rng) >= prob) return false;\n            }\n\n            // Apply move\n            // remove from oldVar\n            int idx = pos[id];\n            int lastId = bucket[oldVar].back();\n            bucket[oldVar][idx] = lastId;\n            pos[lastId] = idx;\n            bucket[oldVar].pop_back();\n\n            // update val oldVar\n            val[oldVar] = candOld;\n\n            // add to newVar\n            pos[id] = (int)bucket[newVar].size();\n            bucket[newVar].push_back(id);\n\n            // update val newVar\n            val[newVar] = candNew;\n\n            // update assignment\n            assignVar[id] = newVar;\n            assignL[id] = newL;\n\n            sumVal = newSum;\n\n            int64_t T = 2 * sumVal;\n            if (T < bestT) {\n                bestT = T;\n                bestAssignVar = assignVar;\n                bestAssignL = assignL;\n            }\n            return true;\n        };\n\n        vector<int> optOrder; optOrder.reserve(M);\n        for (int it = 0; it < steps; it++) {\n            int id = uniform_int_distribution<int>(0, M - 1)(rng);\n            int oldVar = assignVar[id];\n\n            // If there is only 1 option, skip\n            if ((int)options[id].size() <= 1) continue;\n\n            // Compute best alternative among options for this id\n            double temp = 8.0 * (1.0 - (double)it / steps) + 1.0;\n\n            // Evaluate minimal deltaSum option\n            int bestIdx = -1;\n            int bestDelta = INT_MAX;\n            // precompute candOld once (since removing id from oldVar doesn't depend on alt)\n            int candOld = 0;\n            for (int other : bucket[oldVar]) {\n                if (other == id) continue;\n                candOld = max(candOld, assignL[other]);\n            }\n            for (int k = 0; k < (int)options[id].size(); k++) {\n                auto &alt = options[id][k];\n                int newVar = alt.var;\n                if (newVar == oldVar) continue;\n                int newL = alt.L;\n                int candNew = max(val[newVar], newL);\n                int deltaSum = (candOld - val[oldVar]) + (candNew - val[newVar]);\n\n                int64_t newSum = sumVal + deltaSum;\n                if (newSum > limitSum) continue;\n\n                if (deltaSum < bestDelta) {\n                    bestDelta = deltaSum;\n                    bestIdx = k;\n                }\n            }\n\n            if (bestIdx != -1) {\n                // accept best option (annealed inside)\n                tryMove(id, options[id][bestIdx], temp);\n            } else {\n                // random perturbation with small probability\n                if ((it % 20) == 0) {\n                    // choose a random different option\n                    vector<int> diffs;\n                    for (int k = 0; k < (int)options[id].size(); k++) {\n                        if (options[id][k].var != oldVar) diffs.push_back(k);\n                    }\n                    if (!diffs.empty()) {\n                        int kk = diffs[uniform_int_distribution<int>(0, (int)diffs.size()-1)(rng)];\n                        tryMove(id, options[id][kk], temp);\n                    }\n                }\n            }\n        }\n    };\n\n    int64_t bestT = (1LL<<60);\n    vector<int> bestAssignVar, bestAssignL;\n\n    const int RESTARTS = 120;   // increase for more strength\n    const int STEPS = 7000;     // per restart\n\n    // Build initial assignment and run local search repeatedly\n    for (int r = 0; r < RESTARTS; r++) {\n        // choose initial option for each Oni\n        vector<int> chosenIdx(M, 0);\n\n        for (int id = 0; id < M; id++) {\n            auto &opts = options[id];\n            // weighted pick: smaller L more likely, but allow others\n            // weight = (N + 1 - L), at least 1\n            long long total = 0;\n            vector<long long> w(opts.size());\n            for (int k = 0; k < (int)opts.size(); k++) {\n                int L = opts[k].L;\n                long long weight = (long long)(N + 1 - L);\n                if (weight < 1) weight = 1;\n                w[k] = weight;\n                total += weight;\n            }\n            long long rnum = uniform_int_distribution<long long>(0, total - 1)(rng);\n            long long acc = 0;\n            int pick = 0;\n            for (int k = 0; k < (int)opts.size(); k++) {\n                acc += w[k];\n                if (rnum < acc) { pick = k; break; }\n            }\n            // Occasionally force minimal-L for exploitation\n            if ((r % 5) == 0) {\n                int minL = INT_MAX;\n                for (auto &op : opts) minL = min(minL, op.L);\n                vector<int> mins;\n                for (int k = 0; k < (int)opts.size(); k++) if (opts[k].L == minL) mins.push_back(k);\n                pick = mins[uniform_int_distribution<int>(0, (int)mins.size()-1)(rng)];\n            }\n            chosenIdx[id] = pick;\n        }\n\n        vector<int> assignVar, assignL;\n        vector<vector<int>> bucket;\n        vector<int> val;\n        int64_t sumVal = 0, T = 0;\n\n        buildFromAssignment(chosenIdx, assignVar, assignL, bucket, val, sumVal, T);\n\n        if (T > Tlimit) continue;\n\n        // local improvement\n        int64_t curBestT = T;\n        vector<int> curBestVar = assignVar, curBestL = assignL;\n        localSearch(assignVar, assignL, bucket, val, sumVal, curBestT, curBestVar, curBestL, STEPS);\n\n        if (curBestT < bestT) {\n            bestT = curBestT;\n            bestAssignVar = move(curBestVar);\n            bestAssignL = move(curBestL);\n        }\n    }\n\n    // Reconstruct line lengths from best assignment\n    vector<int> val(V, 0);\n    for (int id = 0; id < M; id++) {\n        int v = bestAssignVar[id];\n        val[v] = max(val[v], bestAssignL[id]);\n    }\n\n    // Output operations for each line-direction variable.\n    // UP col j length L: U j L times then D j L times\n    // DOWN col j length L: D j L times then U j L times\n    // LEFT row i length L: L i L times then R i L times\n    // RIGHT row i length L: R i L times then L i L times\n    vector<pair<char,int>> ops;\n    ops.reserve((size_t)bestT);\n\n    for (int j = 0; j < N; j++) {\n        int Lup = val[varUp(j)];\n        for (int k = 0; k < Lup; k++) ops.push_back({'U', j});\n        for (int k = 0; k < Lup; k++) ops.push_back({'D', j});\n\n        int Ldown = val[varDown(j)];\n        for (int k = 0; k < Ldown; k++) ops.push_back({'D', j});\n        for (int k = 0; k < Ldown; k++) ops.push_back({'U', j});\n    }\n    for (int i = 0; i < N; i++) {\n        int Lleft = val[varLeft(i)];\n        for (int k = 0; k < Lleft; k++) ops.push_back({'L', i});\n        for (int k = 0; k < Lleft; k++) ops.push_back({'R', i});\n\n        int Lright = val[varRight(i)];\n        for (int k = 0; k < Lright; k++) ops.push_back({'R', i});\n        for (int k = 0; k < Lright; k++) ops.push_back({'L', i});\n    }\n\n    if ((int64_t)ops.size() > Tlimit) ops.resize((size_t)Tlimit);\n\n    for (auto [ch, p] : ops) {\n        cout << ch << ' ' << p << \"\\n\";\n    }\n    return 0;\n}","ahc044":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int MAXN = 100;\nstatic constexpr int L_CONST = 500000;\n\nstruct State {\n    long long err;\n    array<int, MAXN> cnt{};\n    array<int, MAXN> oddUse{};\n    array<int, MAXN> evenUse{};\n};\n\nstatic inline long long calcErrFromCnt(const array<int, MAXN>& cnt, const array<int, MAXN>& T, int N) {\n    long long e = 0;\n    for (int i = 0; i < N; i++) e += llabs((long long)cnt[i] - (long long)T[i]);\n    return e;\n}\n\nstatic long long simulate(const vector<int>& a, const vector<int>& b,\n                           const array<int, MAXN>& T,\n                           int N, int L,\n                           State &st) {\n    st.cnt.fill(0);\n    st.oddUse.fill(0);\n    st.evenUse.fill(0);\n\n    int x = 0;\n    st.cnt[x] = 1;\n    for (int week = 2; week <= L; week++) {\n        if (st.cnt[x] & 1) {\n            st.oddUse[x]++;\n            x = a[x];\n        } else {\n            st.evenUse[x]++;\n            x = b[x];\n        }\n        st.cnt[x]++;\n    }\n    st.err = calcErrFromCnt(st.cnt, T, N);\n    return st.err;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, L;\n    cin >> N >> L;\n    array<int, MAXN> T{};\n    for (int i = 0; i < N; i++) cin >> T[i];\n\n    // RNG\n    mt19937_64 rng((uint64_t)chrono::high_resolution_clock::now().time_since_epoch().count());\n\n    // Choose destination using residual rem (bigger is more desirable).\n    auto chooseCandidate = [&](const vector<long long>& rem) -> int {\n        const int K = min(25, N);\n        vector<pair<long long,int>> v;\n        v.reserve(N);\n        for (int i = 0; i < N; i++) v.push_back({rem[i], i});\n        nth_element(v.begin(), v.begin() + K, v.end(),\n                    [&](auto &p, auto &q){ return p.first > q.first; });\n        v.resize(K);\n        long long mn = v[0].first, mx = v[0].first;\n        for (auto &p : v) { mn = min(mn, p.first); mx = max(mx, p.first); }\n        long long offset = -mn + 1; // make weights positive\n        vector<long long> w(K);\n        long long sumw = 0;\n        for (int i = 0; i < K; i++) {\n            w[i] = v[i].first + offset;\n            if (w[i] < 1) w[i] = 1;\n            sumw += w[i];\n        }\n        uniform_int_distribution<long long> dist(1, sumw);\n        long long r = dist(rng);\n        for (int i = 0; i < K; i++) {\n            if (r <= w[i]) return v[i].second;\n            r -= w[i];\n        }\n        return v.back().second;\n    };\n\n    // Randomized greedy constructor (similar spirit to yours, but slightly stronger).\n    auto buildMapping = [&](int seedOffset) -> pair<long long, pair<vector<int>, vector<int>>> {\n        // unique seed per build\n        // (We can't reseed rng globally safely; we'll just use it as-is and vary behavior via seedOffset.)\n        vector<int> a(N, -1), b(N, -1);\n        vector<long long> rem(N);\n        for (int i = 0; i < N; i++) rem[i] = T[i];\n\n        array<int, MAXN> cnt{};\n        cnt.fill(0);\n\n        int x = 0;\n        cnt[x] = 1;\n        rem[x]--;\n\n        for (int week = 2; week <= L; week++) {\n            if (cnt[x] & 1) {\n                if (a[x] == -1) {\n                    // small random perturbation by swapping a little preference\n                    int y = chooseCandidate(rem);\n                    if ((seedOffset + week) % 17 == 0) {\n                        // diversify: sometimes pick a random among top 10 by rem\n                        vector<pair<long long,int>> v;\n                        v.reserve(N);\n                        for (int i = 0; i < N; i++) v.push_back({rem[i], i});\n                        sort(v.begin(), v.end(), [&](auto &p, auto &q){ return p.first > q.first; });\n                        int R = min(10, N);\n                        uniform_int_distribution<int> d(0, R-1);\n                        y = v[d(rng)].second;\n                    }\n                    a[x] = y;\n                }\n                x = a[x];\n            } else {\n                if (b[x] == -1) {\n                    int y = chooseCandidate(rem);\n                    if ((seedOffset + week) % 23 == 0) {\n                        vector<pair<long long,int>> v;\n                        v.reserve(N);\n                        for (int i = 0; i < N; i++) v.push_back({rem[i], i});\n                        sort(v.begin(), v.end(), [&](auto &p, auto &q){ return p.first > q.first; });\n                        int R = min(10, N);\n                        uniform_int_distribution<int> d(0, R-1);\n                        y = v[d(rng)].second;\n                    }\n                    b[x] = y;\n                }\n                x = b[x];\n            }\n            cnt[x]++;\n            rem[x]--;\n        }\n\n        for (int i = 0; i < N; i++) {\n            if (a[i] == -1) a[i] = 0;\n            if (b[i] == -1) b[i] = 0;\n        }\n\n        State st;\n        long long err = simulate(a, b, T, N, L, st);\n        return {err, {std::move(a), std::move(b)}};\n    };\n\n    // Time control\n    using Clock = chrono::steady_clock;\n    auto start = Clock::now();\n    auto elapsed = [&]() -> double {\n        return chrono::duration<double>(Clock::now() - start).count();\n    };\n    const double TL = 1.95; // leave a bit of margin\n\n    long long bestErr = (1LL<<62);\n    vector<int> bestA(N, 0), bestB(N, 0);\n\n    // Initial restarts\n    for (int it = 0; it < 40 && elapsed() < TL * 0.35; it++) {\n        auto [err, ab] = buildMapping(it * 100 + 7);\n        if (err < bestErr) {\n            bestErr = err;\n            bestA = std::move(ab.first);\n            bestB = std::move(ab.second);\n        }\n    }\n\n    // Simulated annealing\n    vector<int> curA = bestA, curB = bestB;\n\n    State curSt, newSt;\n    long long curErr = simulate(curA, curB, T, N, L, curSt);\n    bestErr = min(bestErr, curErr);\n\n    // residual arrays (computed from curSt.cnt)\n    auto computeResidualOrder = [&](const State& st) {\n        vector<pair<int,int>> under; under.reserve(N);\n        vector<pair<int,int>> all; all.reserve(N);\n        for (int i = 0; i < N; i++) {\n            int r = T[i] - st.cnt[i];\n            all.push_back({abs(r), i});\n            if (r > 0) under.push_back({r, i});\n        }\n        sort(under.begin(), under.end(), [&](auto &p, auto &q){ return p.first > q.first; });\n        sort(all.begin(), all.end(), [&](auto &p, auto &q){ return p.first > q.first; });\n        return pair<vector<pair<int,int>>, vector<pair<int,int>>>(under, all);\n    };\n\n    vector<pair<int,int>> underList, allAbsList;\n\n    size_t iter = 0;\n    while (elapsed() < TL) {\n        iter++;\n\n        // compute residual lists occasionally\n        if ((iter & 3) == 1) {\n            auto lists = computeResidualOrder(curSt);\n            underList = std::move(lists.first);\n            allAbsList = std::move(lists.second);\n        }\n\n        // choose i with roulette on abs residual (approx)\n        int i = 0;\n        {\n            long long sumAbs = 0;\n            array<long long, MAXN> absw{};\n            for (int k = 0; k < N; k++) {\n                long long r = (long long)T[k] - (long long)curSt.cnt[k];\n                long long w = llabs(r);\n                absw[k] = w;\n                sumAbs += w;\n            }\n            if (sumAbs == 0) {\n                i = uniform_int_distribution<int>(0, N-1)(rng);\n            } else {\n                uniform_int_distribution<long long> dist(1, sumAbs);\n                long long r = dist(rng);\n                for (int k = 0; k < N; k++) {\n                    if (r <= absw[k]) { i = k; break; }\n                    r -= absw[k];\n                }\n            }\n        }\n\n        // choose which edge to modify (a[i] if oddUse dominates)\n        bool changeAedge = true;\n        int ou = curSt.oddUse[i];\n        int eu = curSt.evenUse[i];\n        if (ou + eu == 0) {\n            changeAedge = (uniform_int_distribution<int>(0,1)(rng) == 0);\n        } else {\n            long long r = (long long)uniform_int_distribution<int>(0, 1000000)(rng);\n            changeAedge = (r % (ou + eu) < ou);\n        }\n\n        // choose destination j among underrepresented (prefer positive residual)\n        int curDest = changeAedge ? curA[i] : curB[i];\n\n        int j = curDest;\n        if (!underList.empty()) {\n            int K = min(20, (int)underList.size());\n            // pick among top K with weights proportional to (need+1)\n            long long sumw = 0;\n            for (int t = 0; t < K; t++) sumw += (long long)underList[t].first + 1;\n            uniform_int_distribution<long long> dist(1, sumw);\n            long long r = dist(rng);\n            for (int t = 0; t < K; t++) {\n                long long w = (long long)underList[t].first + 1;\n                if (r <= w) { j = underList[t].second; break; }\n                r -= w;\n            }\n        } else {\n            // fallback: pick from top abs residual indices\n            int K = min(20, (int)allAbsList.size());\n            j = allAbsList[uniform_int_distribution<int>(0, K-1)(rng)].second;\n        }\n\n        // make sure it's actually a change if possible\n        if (N > 1 && j == curDest) {\n            j = (j + 1) % N;\n        }\n\n        // propose change\n        vector<int> aTry = curA;\n        vector<int> bTry = curB;\n\n        if (changeAedge) aTry[i] = j;\n        else bTry[i] = j;\n\n        // occasional double-edge move to escape\n        if (uniform_int_distribution<int>(0, 9)(rng) == 0) {\n            int i2 = allAbsList.empty() ? uniform_int_distribution<int>(0, N-1)(rng)\n                                        : allAbsList[uniform_int_distribution<int>(0, min(30, N)-1)(rng)].second;\n            bool changeA2 = (uniform_int_distribution<int>(0,1)(rng) == 0);\n\n            int dest2 = changeA2 ? aTry[i2] : bTry[i2];\n            int needJ = dest2;\n            if (!underList.empty()) {\n                int K = min(20, (int)underList.size());\n                needJ = underList[uniform_int_distribution<int>(0, K-1)(rng)].second;\n            } else {\n                needJ = allAbsList[uniform_int_distribution<int>(0, min(30, N)-1)(rng)].second;\n            }\n            if (N > 1 && needJ == dest2) needJ = (needJ + 2) % N;\n\n            if (changeA2) aTry[i2] = needJ;\n            else bTry[i2] = needJ;\n        }\n\n        long long newErr = simulate(aTry, bTry, T, N, L, newSt);\n\n        // temperature schedule\n        double frac = elapsed() / TL;\n        double temp = 50000.0 * (1.0 - frac) + 2000.0; // decreases over time\n\n        bool accept = false;\n        if (newErr <= curErr) accept = true;\n        else {\n            double diff = (double)(curErr - newErr); // negative\n            double prob = exp(diff / temp); // exp(-delta/temp)\n            double u = uniform_real_distribution<double>(0.0, 1.0)(rng);\n            if (u < prob) accept = true;\n        }\n\n        if (accept) {\n            curA.swap(aTry);\n            curB.swap(bTry);\n            curErr = newErr;\n            curSt = std::move(newSt);\n            if (curErr < bestErr) {\n                bestErr = curErr;\n                bestA = curA;\n                bestB = curB;\n            }\n        }\n    }\n\n    // Output\n    for (int i = 0; i < N; i++) {\n        cout << bestA[i] << ' ' << bestB[i] << '\\n';\n    }\n    return 0;\n}","ahc045":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\n\nstruct DSU {\n    vector<int> p, r;\n    DSU(int n=0){ init(n); }\n    void init(int n){\n        p.resize(n);\n        r.assign(n,0);\n        iota(p.begin(), p.end(), 0);\n    }\n    int find(int x){ return p[x]==x? x : p[x]=find(p[x]); }\n    bool unite(int a,int b){\n        a=find(a); b=find(b);\n        if(a==b) return false;\n        if(r[a]<r[b]) swap(a,b);\n        p[b]=a;\n        if(r[a]==r[b]) r[a]++;\n        return true;\n    }\n};\n\nstatic inline uint64_t morton2d(uint32_t x, uint32_t y) {\n    // x,y in [0,2^14)\n    uint64_t z = 0;\n    for (uint32_t i = 0; i < 14; i++) {\n        z |= (uint64_t)((x >> i) & 1u) << (2 * i + 1);\n        z |= (uint64_t)((y >> i) & 1u) << (2 * i);\n    }\n    return z;\n}\n\n// rectangle lower bound squared distance between city a and b\nstatic inline ll rectLowerBoundSq(\n    int a, int b,\n    const vector<int>& lx, const vector<int>& rx,\n    const vector<int>& ly, const vector<int>& ry\n) {\n    ll dx = 0;\n    if (rx[a] < lx[b]) dx = (ll)lx[b] - rx[a];\n    else if (rx[b] < lx[a]) dx = (ll)lx[a] - rx[b];\n\n    ll dy = 0;\n    if (ry[a] < ly[b]) dy = (ll)ly[b] - ry[a];\n    else if (ry[b] < ly[a]) dy = (ll)ly[a] - ry[b];\n\n    return dx * dx + dy * dy;\n}\n\nstatic vector<int> reorderNNProxy(\n    const vector<int>& ids,\n    const vector<int>& lx, const vector<int>& rx,\n    const vector<int>& ly, const vector<int>& ry,\n    const vector<uint64_t>& mortonKey\n) {\n    int sz = (int)ids.size();\n    if (sz <= 2) return ids;\n\n    // choose a couple of starts: min/max morton\n    int smin = 0, smax = 0;\n    for (int i = 1; i < sz; i++) {\n        if (mortonKey[ids[i]] < mortonKey[ids[smin]]) smin = i;\n        if (mortonKey[ids[i]] > mortonKey[ids[smax]]) smax = i;\n    }\n\n    auto build = [&](int startPos) {\n        vector<char> used(sz, 0);\n        vector<int> path;\n        path.reserve(sz);\n        int cur = startPos;\n        used[cur] = 1;\n        ll total = 0;\n\n        for (int step = 0; step < sz; step++) {\n            path.push_back(ids[cur]);\n            if (step == sz - 1) break;\n            int best = -1;\n            ll bestW = (1LL<<62);\n            for (int j = 0; j < sz; j++) if (!used[j]) {\n                ll w = rectLowerBoundSq(ids[cur], ids[j], lx, rx, ly, ry);\n                if (w < bestW) bestW = w, best = j;\n            }\n            total += bestW;\n            cur = best;\n            used[cur] = 1;\n        }\n        return pair<ll, vector<int>>(total, path);\n    };\n\n    auto [t1, p1] = build(smin);\n    auto [t2, p2] = build(smax);\n    return (t2 < t1 ? p2 : p1);\n}\n\nstruct CandEdge {\n    int u, v;          // city indices\n    bool oracle;       // primary preference\n    ll w;              // proxy weight\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, Q, L, W;\n    cin >> N >> M >> Q >> L >> W;\n\n    vector<int> G(M);\n    for (int i = 0; i < M; i++) cin >> G[i];\n\n    vector<int> lx(N), rx(N), ly(N), ry(N);\n    for (int i = 0; i < N; i++) cin >> lx[i] >> rx[i] >> ly[i] >> ry[i];\n\n    vector<int> cx_i(N), cy_i(N);\n    vector<uint64_t> mortonKey(N);\n    for (int i = 0; i < N; i++) {\n        cx_i[i] = (lx[i] + rx[i]) / 2;\n        cy_i[i] = (ly[i] + ry[i]) / 2;\n        mortonKey[i] = morton2d((uint32_t)cx_i[i], (uint32_t)cy_i[i]);\n    }\n\n    // Morton sort\n    vector<int> cities(N);\n    iota(cities.begin(), cities.end(), 0);\n    sort(cities.begin(), cities.end(), [&](int a, int b){\n        if (mortonKey[a] != mortonKey[b]) return mortonKey[a] < mortonKey[b];\n        return a < b;\n    });\n\n    // Precompute adjacency proxy along Morton order\n    vector<ll> adjProxy(N-1, 0);\n    for (int i = 0; i < N-1; i++) {\n        adjProxy[i] = rectLowerBoundSq(cities[i], cities[i+1], lx, rx, ly, ry);\n    }\n    vector<ll> pref(N, 0);\n    for (int i = 0; i < N-1; i++) pref[i+1] = pref[i] + adjProxy[i];\n\n    // Greedy segment assignment of group sizes to minimize average adjProxy\n    vector<vector<int>> groupCities(M);\n    int ptr = 0;\n\n    // list of remaining group indices\n    vector<int> rem;\n    rem.reserve(M);\n    for (int i = 0; i < M; i++) rem.push_back(i);\n\n    while (!rem.empty()) {\n        int bestIdx = -1;\n        double bestAvg = 1e300;\n\n        for (int gi : rem) {\n            int sz = G[gi];\n            if (ptr + sz > N) continue;\n            // sum of adjProxy over edges inside segment [ptr..ptr+sz-1]\n            ll sum = pref[ptr + sz - 1] - pref[ptr]; // length sz-1\n            double avg = (sz <= 1 ? 0.0 : (double)sum / (double)(sz-1));\n            if (avg < bestAvg) {\n                bestAvg = avg;\n                bestIdx = gi;\n            }\n        }\n\n        int gi = bestIdx;\n        int sz = G[gi];\n        groupCities[gi].assign(cities.begin() + ptr, cities.begin() + ptr + sz);\n        ptr += sz;\n\n        rem.erase(find(rem.begin(), rem.end(), gi));\n    }\n\n    vector<vector<pair<int,int>>> roads(M);\n    int queriesUsed = 0;\n\n    for (int gi = 0; gi < M; gi++) {\n        auto base = groupCities[gi];\n        int sz = (int)base.size();\n\n        if (sz <= 1) {\n            roads[gi].clear();\n            continue;\n        }\n\n        // Reorder inside group using NN proxy\n        vector<int> ord = reorderNNProxy(base, lx, rx, ly, ry, mortonKey);\n\n        // local index mapping\n        vector<int> local(N, -1);\n        for (int i = 0; i < sz; i++) local[ord[i]] = i;\n\n        // Candidate edges\n        vector<CandEdge> cand;\n        cand.reserve((sz-1) + 6000);\n\n        auto addEdge = [&](int u, int v, bool oracle){\n            if (u == v) return;\n            if (u > v) swap(u, v);\n            ll w = rectLowerBoundSq(u, v, lx, rx, ly, ry);\n            cand.push_back({u, v, oracle, w});\n        };\n\n        // Always add chain edges\n        for (int i = 0; i + 1 < sz; i++) {\n            addEdge(ord[i], ord[i+1], false);\n        }\n\n        // Oracle queries\n        if (sz >= 3 && queriesUsed < Q) {\n            int s = min(L, sz);\n            int step = max(2, s - 1); // s>=3 => step>=2\n            for (int start = 0; start + s <= sz && queriesUsed < Q; start += step) {\n                // query subset ord[start..start+s-1]\n                cout << \"? \" << s;\n                for (int t = 0; t < s; t++) cout << ' ' << ord[start+t];\n                cout << '\\n' << flush;\n\n                // read s-1 edges\n                for (int k = 0; k < s - 1; k++) {\n                    int a, b;\n                    cin >> a >> b;\n                    addEdge(a, b, true);\n                }\n                queriesUsed++;\n            }\n        }\n\n        // Kruskal: prefer oracle edges first, then proxy weight\n        sort(cand.begin(), cand.end(), [&](const CandEdge& e1, const CandEdge& e2){\n            if (e1.oracle != e2.oracle) return e1.oracle > e2.oracle; // oracle first\n            if (e1.w != e2.w) return e1.w < e2.w;\n            if (e1.u != e2.u) return e1.u < e2.u;\n            return e1.v < e2.v;\n        });\n\n        DSU dsu(sz);\n        vector<pair<int,int>> chosen;\n        chosen.reserve(sz-1);\n\n        for (auto &e : cand) {\n            int lu = local[e.u], lv = local[e.v];\n            if (lu < 0 || lv < 0) continue;\n            if (dsu.unite(lu, lv)) {\n                int a = e.u, b = e.v;\n                if (a > b) swap(a, b);\n                chosen.push_back({a, b});\n                if ((int)chosen.size() == sz - 1) break;\n            }\n        }\n\n        // Safety fallback: if somehow not connected, use pure chain\n        if ((int)chosen.size() != sz - 1) {\n            chosen.clear();\n            for (int i = 1; i < sz; i++) {\n                int a = ord[i-1], b = ord[i];\n                if (a > b) swap(a, b);\n                chosen.push_back({a, b});\n            }\n        }\n\n        roads[gi] = std::move(chosen);\n\n        // Output order can be ord (doesn't matter)\n        groupCities[gi] = std::move(ord);\n    }\n\n    cout << \"!\" << '\\n' << flush;\n\n    for (int gi = 0; gi < M; gi++) {\n        auto &vec = groupCities[gi];\n        for (int i = 0; i < (int)vec.size(); i++) {\n            if (i) cout << ' ';\n            cout << vec[i];\n        }\n        cout << '\\n';\n        for (auto [u,v] : roads[gi]) {\n            cout << u << ' ' << v << '\\n';\n        }\n    }\n    cout << flush;\n    return 0;\n}","ahc046":"#include <bits/stdc++.h>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M;\n    cin >> N >> M;\n    vector<pair<int,int>> in(M);\n    for (int i = 0; i < M; i++) cin >> in[i].first >> in[i].second;\n\n    const int Vpos = N * N;\n    auto posIdx = [&](int x, int y) { return x * N + y; };\n    auto inside = [&](int x, int y) { return 0 <= x && x < N && 0 <= y && y < N; };\n\n    // Required targets in order: visit in[1], in[2], ... in[M-1]\n    const int R = M - 1; // 39\n    vector<int> reqPos(R);\n    for (int i = 0; i < R; i++) reqPos[i] = posIdx(in[i+1].first, in[i+1].second);\n\n    int startPos = posIdx(in[0].first, in[0].second);\n\n    // Neighbors for Move/Alter\n    int dx[4] = {-1, 1, 0, 0};\n    int dy[4] = {0, 0, -1, 1};\n    vector<array<int,4>> neigh(Vpos);\n    for (int p = 0; p < Vpos; p++) {\n        int x = p / N, y = p % N;\n        for (int d = 0; d < 4; d++) {\n            int nx = x + dx[d], ny = y + dy[d];\n            neigh[p][d] = inside(nx, ny) ? posIdx(nx, ny) : -1;\n        }\n    }\n\n    static const char DIRCH[4] = {'U','D','L','R'};\n    static const char ACTCH[3] = {'M','S','A'};\n\n    // ---------- Candidate selection ----------\n    // Weight each cell by how many required targets have it adjacent (4-neighborhood).\n    vector<int> weight(Vpos, 0);\n    for (int rp : reqPos) {\n        int x = rp / N, y = rp % N;\n        for (int d = 0; d < 4; d++) {\n            int nx = x + dx[d], ny = y + dy[d];\n            if (inside(nx, ny)) weight[posIdx(nx, ny)]++;\n        }\n    }\n    // Encourage including vicinity of start\n    {\n        int sx = startPos / N, sy = startPos % N;\n        weight[startPos] += 1;\n        for (int d = 0; d < 4; d++) {\n            int nx = sx + dx[d], ny = sy + dy[d];\n            if (inside(nx, ny)) weight[posIdx(nx, ny)] += 1;\n        }\n    }\n\n    // We will allow up to 4 blocks, so keep candidates small.\n    const int CC = 14;     // small enough for fast subset enumeration\n    const int MAXB = 4;    // allow 4 blocks simultaneously\n\n    vector<int> all;\n    all.reserve(Vpos);\n    for (int p = 0; p < Vpos; p++) if (weight[p] > 0) all.push_back(p);\n\n    sort(all.begin(), all.end(), [&](int a, int b){\n        if (weight[a] != weight[b]) return weight[a] > weight[b];\n        return a < b;\n    });\n\n    vector<int> cand;\n    cand.reserve(CC);\n\n    // Always take all weight>=2 first (up to CC)\n    for (int p : all) {\n        if ((int)cand.size() >= CC) break;\n        if (weight[p] >= 2) cand.push_back(p);\n    }\n    // Fill the rest with best remaining\n    for (int p : all) {\n        if ((int)cand.size() >= CC) break;\n        bool ok = true;\n        for (int q : cand) if (q == p) { ok = false; break; }\n        if (ok) cand.push_back(p);\n    }\n    // If still empty (extremely unlikely), fall back\n    if (cand.empty()) cand.push_back(startPos);\n    // If less than CC, pad with some cells near start\n    if ((int)cand.size() < CC) {\n        int sx = startPos / N, sy = startPos % N;\n        vector<int> pad;\n        pad.push_back(startPos);\n        for (int d = 0; d < 4; d++) {\n            int nx = sx + dx[d], ny = sy + dy[d];\n            if (inside(nx, ny)) pad.push_back(posIdx(nx, ny));\n        }\n        for (int p : pad) {\n            if ((int)cand.size() >= CC) break;\n            if (find(cand.begin(), cand.end(), p) == cand.end()) cand.push_back(p);\n        }\n    }\n    if ((int)cand.size() > CC) cand.resize(CC);\n\n    const int C = (int)cand.size(); // <=14\n\n    // Map cell -> candidate index\n    vector<int> candIndexOfCell(Vpos, -1);\n    for (int i = 0; i < C; i++) candIndexOfCell[cand[i]] = i;\n\n    // ---------- Enumerate masks with popcount <= MAXB ----------\n    // For C<=14, subset enumeration over [0..(1<<C)-1] is cheap.\n    const uint32_t LIM = 1u << C;\n    vector<int> idOf(LIM, -1);\n    vector<uint32_t> masks;\n    masks.reserve(2000);\n\n    for (uint32_t m = 0; m < LIM; m++) {\n        if (__builtin_popcount(m) <= MAXB) {\n            idOf[m] = (int)masks.size();\n            masks.push_back(m);\n        }\n    }\n    const int maskCount = (int)masks.size();\n\n    // For each mask: store block cell indices (up to MAXB), pad with -1.\n    vector<array<int,MAXB>> maskBlocks(maskCount);\n    for (int mid = 0; mid < maskCount; mid++) {\n        uint32_t m = masks[mid];\n        array<int,MAXB> arr;\n        arr.fill(-1);\n        int t = 0;\n        for (int i = 0; i < C; i++) if ((m>>i)&1u) {\n            arr[t++] = cand[i];\n            if (t == MAXB) break;\n        }\n        maskBlocks[mid] = arr;\n    }\n\n    // blocked[mid][pos] boolean\n    vector<uint8_t> blocked((size_t)maskCount * Vpos, 0);\n    for (int mid = 0; mid < maskCount; mid++) {\n        for (int bi = 0; bi < MAXB; bi++) {\n            int cell = maskBlocks[mid][bi];\n            if (cell != -1) blocked[(size_t)mid * Vpos + cell] = 1;\n        }\n    }\n    auto isBlocked = [&](int mid, int pos) -> bool {\n        return blocked[(size_t)mid * Vpos + pos] != 0;\n    };\n\n    // toggleNext[mid][ci] -> newMid or -1\n    vector<vector<int16_t>> toggleNext(maskCount, vector<int16_t>(C, -1));\n    for (int mid = 0; mid < maskCount; mid++) {\n        uint32_t m = masks[mid];\n        int pc = __builtin_popcount(m);\n        for (int ci = 0; ci < C; ci++) {\n            bool has = (m >> ci) & 1u;\n            if (has) {\n                uint32_t nm = m & ~(1u << ci);\n                toggleNext[mid][ci] = (idOf[nm] == -1 ? -1 : (int16_t)idOf[nm]);\n            } else {\n                if (pc >= MAXB) continue;\n                uint32_t nm = m | (1u << ci);\n                toggleNext[mid][ci] = (idOf[nm] == -1 ? -1 : (int16_t)idOf[nm]);\n            }\n        }\n    }\n\n    // slideStop[mid][dir][pos] => stop cell index\n    vector<uint16_t> slideStop((size_t)maskCount * 4 * Vpos);\n    auto slideRef = [&](int mid, int dir, int pos) -> uint16_t& {\n        return slideStop[((size_t)mid * 4 + dir) * Vpos + pos];\n    };\n\n    for (int mid = 0; mid < maskCount; mid++) {\n        auto blocks = maskBlocks[mid];\n        for (int pos = 0; pos < Vpos; pos++) {\n            int x = pos / N, y = pos % N;\n\n            for (int dir = 0; dir < 4; dir++) {\n                if (dir == 0) { // U\n                    int best = -1; // max bx < x with same column\n                    for (int bi = 0; bi < MAXB; bi++) if (blocks[bi] != -1) {\n                        int bx = blocks[bi] / N;\n                        int by = blocks[bi] % N;\n                        if (by == y && bx < x) best = max(best, bx);\n                    }\n                    int stopX = (best == -1) ? 0 : best + 1;\n                    slideRef(mid,dir,pos) = (uint16_t)posIdx(stopX, y);\n                } else if (dir == 1) { // D\n                    int best = N; // min bx > x\n                    for (int bi = 0; bi < MAXB; bi++) if (blocks[bi] != -1) {\n                        int bx = blocks[bi] / N;\n                        int by = blocks[bi] % N;\n                        if (by == y && bx > x) best = min(best, bx);\n                    }\n                    int stopX = (best == N) ? (N-1) : best - 1;\n                    slideRef(mid,dir,pos) = (uint16_t)posIdx(stopX, y);\n                } else if (dir == 2) { // L\n                    int best = -1; // max by < y with same row\n                    for (int bi = 0; bi < MAXB; bi++) if (blocks[bi] != -1) {\n                        int bx = blocks[bi] / N;\n                        int by = blocks[bi] % N;\n                        if (bx == x && by < y) best = max(best, by);\n                    }\n                    int stopY = (best == -1) ? 0 : best + 1;\n                    slideRef(mid,dir,pos) = (uint16_t)posIdx(x, stopY);\n                } else { // R\n                    int best = N; // min by > y\n                    for (int bi = 0; bi < MAXB; bi++) if (blocks[bi] != -1) {\n                        int bx = blocks[bi] / N;\n                        int by = blocks[bi] % N;\n                        if (bx == x && by > y) best = min(best, by);\n                    }\n                    int stopY = (best == N) ? (N-1) : best - 1;\n                    slideRef(mid,dir,pos) = (uint16_t)posIdx(x, stopY);\n                }\n            }\n        }\n    }\n\n    // ---------- Global BFS over (k visited, position, mask) ----------\n    // k in [0..R]. k==R means all required targets visited.\n    const int Kst = R + 1; // 40\n    const int TOTAL = Kst * Vpos * maskCount;\n\n    auto sid = [&](int k, int pos, int mid) -> int {\n        return (k * Vpos + pos) * maskCount + mid;\n    };\n\n    vector<int16_t> dist(TOTAL, -1);\n    vector<int> parent(TOTAL, -1);\n    vector<uint8_t> parentCode(TOTAL, 0); // act*4+dir\n\n    int startMid = idOf[0u];\n    int startState = sid(0, startPos, startMid);\n    dist[startState] = 0;\n\n    vector<int> q;\n    q.reserve(30'000'000);\n    q.push_back(startState);\n    size_t head = 0;\n\n    int goalState = -1;\n\n    while (head < q.size()) {\n        int v = q[head++];\n        int dcur = dist[v];\n\n        int mid = v % maskCount;\n        int tmp = v / maskCount;\n        int pos = tmp % Vpos;\n        int k = tmp / Vpos;\n\n        // If already at/over goal, stop (BFS => minimal).\n        if (k == R) {\n            goalState = v;\n            break;\n        }\n        if (isBlocked(mid, pos)) continue; // cannot stand on a block\n\n        for (int dir = 0; dir < 4; dir++) {\n            // 1) Move\n            {\n                int np = neigh[pos][dir];\n                if (np != -1 && !isBlocked(mid, np)) {\n                    int nk = k;\n                    if (nk < R && np == reqPos[nk]) nk++;\n                    int to = sid(nk, np, mid);\n                    if (dist[to] == -1) {\n                        dist[to] = (int16_t)(dcur + 1);\n                        parent[to] = v;\n                        parentCode[to] = (uint8_t)(0 * 4 + dir); // M\n                        q.push_back(to);\n                    }\n                }\n            }\n\n            // 2) Slide\n            {\n                int sp = (int)slideRef(mid, dir, pos);\n                // stop cell should be unblocked; still check:\n                if (!isBlocked(mid, sp)) {\n                    int nk = k;\n                    if (nk < R && sp == reqPos[nk]) nk++;\n                    int to = sid(nk, sp, mid);\n                    if (dist[to] == -1) {\n                        dist[to] = (int16_t)(dcur + 1);\n                        parent[to] = v;\n                        parentCode[to] = (uint8_t)(1 * 4 + dir); // S\n                        q.push_back(to);\n                    }\n                }\n            }\n\n            // 3) Alter (toggle adjacent candidate cell, if it stays within popcount<=MAXB)\n            {\n                int ap = neigh[pos][dir];\n                if (ap != -1) {\n                    int ci = candIndexOfCell[ap];\n                    if (ci != -1) {\n                        int16_t nm = toggleNext[mid][ci];\n                        if (nm != -1) {\n                            int to = sid(k, pos, (int)nm);\n                            if (dist[to] == -1) {\n                                dist[to] = (int16_t)(dcur + 1);\n                                parent[to] = v;\n                                parentCode[to] = (uint8_t)(2 * 4 + dir); // A\n                                q.push_back(to);\n                            }\n                        }\n                    }\n                }\n            }\n        }\n    }\n\n    // Safety fallback: move-only (always fits limit) if somehow no goal found.\n    auto outputMoveOnly = [&]() {\n        vector<pair<char,char>> ans;\n        ans.reserve(2000);\n        int cx = in[0].first, cy = in[0].second;\n        for (int k = 0; k < R; k++) {\n            int tx = in[k+1].first, ty = in[k+1].second;\n            while (cx != tx) {\n                int nx = cx + (tx > cx ? 1 : -1);\n                ans.push_back({'M', (tx > cx) ? 'D' : 'U'});\n                cx = nx;\n            }\n            while (cy != ty) {\n                int ny = cy + (ty > cy ? 1 : -1);\n                ans.push_back({'M', (ty > cy) ? 'R' : 'L'});\n                cy = ny;\n            }\n        }\n        int limit = 2 * N * M;\n        if ((int)ans.size() > limit) ans.resize(limit);\n        for (auto &e : ans) cout << e.first << ' ' << e.second << \"\\n\";\n    };\n\n    if (goalState == -1) {\n        outputMoveOnly();\n        return 0;\n    }\n\n    vector<pair<char,char>> actions;\n    actions.reserve(2000);\n    int cur = goalState;\n    while (cur != startState) {\n        uint8_t code = parentCode[cur];\n        int prev = parent[cur];\n        int act = code / 4;\n        int dir = code % 4;\n        actions.push_back({ACTCH[act], DIRCH[dir]});\n        cur = prev;\n    }\n    reverse(actions.begin(), actions.end());\n\n    int limit = 2 * N * M; // 1600\n    if ((int)actions.size() > limit) {\n        outputMoveOnly();\n        return 0;\n    }\n\n    for (auto &e : actions) {\n        cout << e.first << ' ' << e.second << \"\\n\";\n    }\n    return 0;\n}"},"16":{"ahc001":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\n\nstruct Company { int x, y; ll r; };\nstruct Rect { int a, b, c, d; }; // [a,c) x [b,d)\nstruct Cand { int k; long double cost; };\n\nstatic inline long double cutCostLogRatio(\n    ll areaParent, ll sumRParent,\n    ll areaL, ll sumRL\n) {\n    (void)areaParent;\n    ll areaR = areaParent - areaL;\n    ll sumRR = sumRParent - sumRL;\n    long double dL = logl((long double)(areaL + 1)) - logl((long double)(sumRL + 1));\n    long double dR = logl((long double)(areaR + 1)) - logl((long double)(sumRR + 1));\n    return dL * dL + dR * dR;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int n;\n    cin >> n;\n    vector<Company> comp(n);\n    for (int i = 0; i < n; i++) cin >> comp[i].x >> comp[i].y >> comp[i].r;\n\n    constexpr int N = 10000;\n\n    auto scoreOf = [&](const vector<Rect>& rects) -> long double {\n        long double total = 0;\n        for (int i = 0; i < n; i++) {\n            ll w = rects[i].c - rects[i].a;\n            ll h = rects[i].d - rects[i].b;\n            ll s = w * h;\n            ll ri = comp[i].r;\n            ll mn = min(ri, s);\n            ll mx = max(ri, s);\n            long double t = (long double)mn / (long double)mx; // (0,1]\n            total += 1.0L - (1.0L - t) * (1.0L - t);             // 2t - t^2\n        }\n        return total;\n    };\n\n    uint64_t baseSeed = chrono::steady_clock::now().time_since_epoch().count();\n    auto start = chrono::steady_clock::now();\n\n    const int TIME_LIMIT_MS = 4970;\n\n    // Heuristic parameters\n    const int BEAM_ROOT = 7;     // top root actions\n    const int RUN_PER_ACTION = 5; // stochastic builds per root action\n    const int TOPSPLIT = 28;\n    const int TOPK_CUT = 10;\n    const int DEDUP_CAP = 90;\n\n    const long double ORI_BETA_BASE = 2.0L; // direction stochasticity base\n    const long double CUT_BETA_BASE = 2.6L; // cut stochasticity base\n\n    auto depthFactor = [&](int depth) -> long double {\n        // shallow: more exploration, deep: more exploitation\n        return 1.0L + 0.14L * (long double)max(0, depth - 1);\n    };\n\n    auto fallbackSplitV = [&](const vector<int>& ids, int lx, int rx) -> int {\n        vector<int> xs;\n        xs.reserve(ids.size());\n        for (int id : ids) xs.push_back(comp[id].x);\n        sort(xs.begin(), xs.end());\n        xs.erase(unique(xs.begin(), xs.end()), xs.end());\n        for (int i = 0; i + 1 < (int)xs.size(); i++) {\n            int k = xs[i] + 1;\n            if (lx + 1 <= k && k <= rx - 1) return k;\n        }\n        return -1;\n    };\n\n    auto fallbackSplitH = [&](const vector<int>& ids, int ly, int ry) -> int {\n        vector<int> ys;\n        ys.reserve(ids.size());\n        for (int id : ids) ys.push_back(comp[id].y);\n        sort(ys.begin(), ys.end());\n        ys.erase(unique(ys.begin(), ys.end()), ys.end());\n        for (int i = 0; i + 1 < (int)ys.size(); i++) {\n            int k = ys[i] + 1;\n            if (ly + 1 <= k && k <= ry - 1) return k;\n        }\n        return -1;\n    };\n\n    // Candidate generation for a node\n    auto getCandidates = [&](const vector<int>& ids,\n                             int lx, int rx, int ly, int ry,\n                             ll areaParent, ll sumRParent,\n                             bool vertical,\n                             mt19937_64& rng) -> vector<Cand> {\n        int m = (int)ids.size();\n        if (m <= 1) return {};\n        if (areaParent <= 0) return {};\n\n        if (vertical) {\n            if (rx - lx <= 1) return {};\n            ll height = (ll)(ry - ly);\n\n            vector<int> v = ids;\n            sort(v.begin(), v.end(), [&](int a, int b){ return comp[a].x < comp[b].x; });\n\n            vector<int> xs;\n            vector<ll> sumR;\n            xs.reserve(m); sumR.reserve(m);\n            for (int i = 0; i < m; ) {\n                int j = i;\n                int xval = comp[v[i]].x;\n                ll s = 0;\n                while (j < m && comp[v[j]].x == xval) { s += comp[v[j]].r; j++; }\n                xs.push_back(xval);\n                sumR.push_back(s);\n                i = j;\n            }\n            int G = (int)xs.size();\n            if (G <= 1) return {};\n\n            vector<ll> pref(G + 1, 0);\n            for (int i = 0; i < G; i++) pref[i+1] = pref[i] + sumR[i];\n\n            struct IntervalBest { int g; long double bestCost; int bestK; };\n            vector<IntervalBest> intervals;\n            intervals.reserve(G);\n\n            for (int g = 0; g < G - 1; g++) {\n                ll sumRL = pref[g + 1];\n                int uL = xs[g], uR = xs[g + 1];\n\n                int k_low = max(lx + 1, uL + 1);\n                int k_high = min(rx - 1, uR);\n                if (k_low > k_high) continue;\n\n                long double k_exact = (long double)lx + (long double)sumRL / (long double)height;\n                int k0 = (int)floor(k_exact);\n\n                long double bestCost = numeric_limits<long double>::infinity();\n                int bestK = k_low;\n\n                auto tryK = [&](int k) {\n                    if (k < k_low || k > k_high) return;\n                    ll areaL = 1LL * (k - lx) * height;\n                    long double c = cutCostLogRatio(areaParent, sumRParent, areaL, sumRL);\n                    if (c < bestCost) { bestCost = c; bestK = k; }\n                };\n                tryK(k0);\n                tryK(k0 + 1);\n                tryK(k_low);\n                tryK(k_high);\n\n                intervals.push_back({g, bestCost, bestK});\n            }\n            if (intervals.empty()) return {};\n\n            sort(intervals.begin(), intervals.end(), [&](const auto& A, const auto& B){\n                if (A.bestCost != B.bestCost) return A.bestCost < B.bestCost;\n                return A.g < B.g;\n            });\n            if ((int)intervals.size() > TOPSPLIT) intervals.resize(TOPSPLIT);\n\n            vector<Cand> cand;\n            cand.reserve(TOPSPLIT * 14);\n\n            for (auto ib : intervals) {\n                int g = ib.g;\n                ll sumRL = pref[g + 1];\n                int uL = xs[g], uR = xs[g + 1];\n\n                int k_low = max(lx + 1, uL + 1);\n                int k_high = min(rx - 1, uR);\n                if (k_low > k_high) continue;\n\n                long double k_exact = (long double)lx + (long double)sumRL / (long double)height;\n                int kf = (int)floor(k_exact);\n\n                auto pushK = [&](int k) {\n                    if (k < k_low || k > k_high) return;\n                    ll areaL = 1LL * (k - lx) * height;\n                    long double c = cutCostLogRatio(areaParent, sumRParent, areaL, sumRL);\n                    cand.push_back({k, c});\n                };\n\n                pushK(k_low);\n                pushK(k_high);\n                pushK(kf);\n                pushK(kf + 1);\n                pushK(ib.bestK);\n                pushK(ib.bestK - 1);\n                pushK(ib.bestK + 1);\n\n                for (int t = 0; t < 2; t++) {\n                    long double u = (long double)(rng() % 1000000) / 1000000.0L;\n                    long double kk = k_exact + (u - 0.5L) * (long double)(k_high - k_low) / 5.0L;\n                    pushK((int)llround(kk));\n                }\n            }\n\n            if (cand.empty()) return {};\n            sort(cand.begin(), cand.end(), [&](const Cand& A, const Cand& B){\n                if (A.k != B.k) return A.k < B.k;\n                return A.cost < B.cost;\n            });\n\n            // dedup by k (keep best cost)\n            vector<Cand> ded;\n            ded.reserve(cand.size());\n            for (auto &c : cand) {\n                if (ded.empty() || ded.back().k != c.k) ded.push_back(c);\n                else if (c.cost < ded.back().cost) ded.back().cost = c.cost;\n            }\n            sort(ded.begin(), ded.end(), [&](const Cand& A, const Cand& B){\n                return A.cost < B.cost;\n            });\n            if ((int)ded.size() > DEDUP_CAP) ded.resize(DEDUP_CAP);\n            // resort by cost asc (already) ok\n            return ded;\n\n        } else {\n            if (ry - ly <= 1) return {};\n            ll width = (ll)(rx - lx);\n\n            vector<int> v = ids;\n            sort(v.begin(), v.end(), [&](int a, int b){ return comp[a].y < comp[b].y; });\n\n            vector<int> ys;\n            vector<ll> sumR;\n            ys.reserve(m); sumR.reserve(m);\n            for (int i = 0; i < m; ) {\n                int j = i;\n                int yval = comp[v[i]].y;\n                ll s = 0;\n                while (j < m && comp[v[j]].y == yval) { s += comp[v[j]].r; j++; }\n                ys.push_back(yval);\n                sumR.push_back(s);\n                i = j;\n            }\n            int G = (int)ys.size();\n            if (G <= 1) return {};\n\n            vector<ll> pref(G + 1, 0);\n            for (int i = 0; i < G; i++) pref[i+1] = pref[i] + sumR[i];\n\n            struct IntervalBest { int g; long double bestCost; int bestK; };\n            vector<IntervalBest> intervals;\n            intervals.reserve(G);\n\n            for (int g = 0; g < G - 1; g++) {\n                ll sumRB = pref[g + 1];\n                int uB = ys[g], uT = ys[g + 1];\n\n                int k_low = max(ly + 1, uB + 1);\n                int k_high = min(ry - 1, uT);\n                if (k_low > k_high) continue;\n\n                long double k_exact = (long double)ly + (long double)sumRB / (long double)width;\n                int k0 = (int)floor(k_exact);\n\n                long double bestCost = numeric_limits<long double>::infinity();\n                int bestK = k_low;\n\n                auto tryK = [&](int k) {\n                    if (k < k_low || k > k_high) return;\n                    ll areaB = 1LL * (k - ly) * width;\n                    long double c = cutCostLogRatio(areaParent, sumRParent, areaB, sumRB);\n                    if (c < bestCost) { bestCost = c; bestK = k; }\n                };\n                tryK(k0);\n                tryK(k0 + 1);\n                tryK(k_low);\n                tryK(k_high);\n\n                intervals.push_back({g, bestCost, bestK});\n            }\n            if (intervals.empty()) return {};\n\n            sort(intervals.begin(), intervals.end(), [&](const auto& A, const auto& B){\n                if (A.bestCost != B.bestCost) return A.bestCost < B.bestCost;\n                return A.g < B.g;\n            });\n            if ((int)intervals.size() > TOPSPLIT) intervals.resize(TOPSPLIT);\n\n            vector<Cand> cand;\n            cand.reserve(TOPSPLIT * 14);\n\n            for (auto ib : intervals) {\n                int g = ib.g;\n                ll sumRB = pref[g + 1];\n                int uB = ys[g], uT = ys[g + 1];\n\n                int k_low = max(ly + 1, uB + 1);\n                int k_high = min(ry - 1, uT);\n                if (k_low > k_high) continue;\n\n                long double k_exact = (long double)ly + (long double)sumRB / (long double)width;\n                int kf = (int)floor(k_exact);\n\n                auto pushK = [&](int k) {\n                    if (k < k_low || k > k_high) return;\n                    ll areaB = 1LL * (k - ly) * width;\n                    long double c = cutCostLogRatio(areaParent, sumRParent, areaB, sumRB);\n                    cand.push_back({k, c});\n                };\n\n                pushK(k_low);\n                pushK(k_high);\n                pushK(kf);\n                pushK(kf + 1);\n                pushK(ib.bestK);\n                pushK(ib.bestK - 1);\n                pushK(ib.bestK + 1);\n\n                for (int t = 0; t < 2; t++) {\n                    long double u = (long double)(rng() % 1000000) / 1000000.0L;\n                    long double kk = k_exact + (u - 0.5L) * (long double)(k_high - k_low) / 5.0L;\n                    pushK((int)llround(kk));\n                }\n            }\n\n            if (cand.empty()) return {};\n            sort(cand.begin(), cand.end(), [&](const Cand& A, const Cand& B){\n                if (A.k != B.k) return A.k < B.k;\n                return A.cost < B.cost;\n            });\n\n            vector<Cand> ded;\n            ded.reserve(cand.size());\n            for (auto &c : cand) {\n                if (ded.empty() || ded.back().k != c.k) ded.push_back(c);\n                else if (c.cost < ded.back().cost) ded.back().cost = c.cost;\n            }\n            sort(ded.begin(), ded.end(), [&](const Cand& A, const Cand& B){\n                return A.cost < B.cost;\n            });\n            if ((int)ded.size() > DEDUP_CAP) ded.resize(DEDUP_CAP);\n            return ded;\n        }\n    };\n\n    auto build = [&](auto&& self,\n                      int lx, int rx, int ly, int ry,\n                      const vector<int>& ids, ll sumRNode,\n                      int depth, mt19937_64& rng,\n                      vector<Rect>& rects) -> void {\n        if ((int)ids.size() == 1) {\n            rects[ids[0]] = Rect{lx, ly, rx, ry};\n            return;\n        }\n        ll areaParent = 1LL * (rx - lx) * (ry - ly);\n        if (areaParent <= 0) {\n            // Should not happen. Safety.\n            rects[ids[0]] = Rect{lx, ly, rx, ry};\n            return;\n        }\n\n        bool canV = (rx - lx > 1);\n        bool canH = (ry - ly > 1);\n\n        vector<Cand> candV, candH;\n        if (canV) candV = getCandidates(ids, lx, rx, ly, ry, areaParent, sumRNode, true, rng);\n        if (canH) candH = getCandidates(ids, lx, rx, ly, ry, areaParent, sumRNode, false, rng);\n\n        bool chooseV;\n        if (candV.empty()) chooseV = false;\n        else if (candH.empty()) chooseV = true;\n        else {\n            long double f = depthFactor(depth);\n            long double betaDir = ORI_BETA_BASE * f;\n            int takeV = min(TOPK_CUT, (int)candV.size());\n            int takeH = min(TOPK_CUT, (int)candH.size());\n            long double ZV = 0, ZH = 0;\n            for (int i = 0; i < takeV; i++) ZV += expl(-candV[i].cost * betaDir);\n            for (int i = 0; i < takeH; i++) ZH += expl(-candH[i].cost * betaDir);\n            if (ZV <= 0 || ZH <= 0) chooseV = (candV[0].cost <= candH[0].cost);\n            else {\n                long double u = (long double)(rng() % 1000000) / 1000000.0L;\n                chooseV = (u < ZV / (ZV + ZH));\n            }\n        }\n\n        if (chooseV) {\n            int k = -1;\n            if (!candV.empty()) {\n                long double f = depthFactor(depth);\n                long double betaCut = CUT_BETA_BASE * f;\n                int take = min(TOPK_CUT, (int)candV.size());\n                vector<long double> w(take);\n                long double Z = 0;\n                for (int i = 0; i < take; i++) { w[i] = expl(-candV[i].cost * betaCut); Z += w[i]; }\n                if (Z <= 0) k = candV[0].k;\n                else {\n                    long double u = (long double)(rng() % 1000000) / 1000000.0L * Z;\n                    long double acc = 0;\n                    for (int i = 0; i < take; i++) {\n                        acc += w[i];\n                        if (u <= acc) { k = candV[i].k; break; }\n                    }\n                }\n            }\n            if (k <= lx || k >= rx) k = fallbackSplitV(ids, lx, rx);\n            if (k <= lx || k >= rx) { rects[ids[0]] = Rect{lx, ly, rx, ry}; return; }\n\n            vector<int> L, R;\n            ll sumL = 0, sumR = 0;\n            for (int id : ids) {\n                if (comp[id].x < k) { L.push_back(id); sumL += comp[id].r; }\n                else { R.push_back(id); sumR += comp[id].r; }\n            }\n            if (L.empty() || R.empty()) {\n                int k2 = fallbackSplitV(ids, lx, rx);\n                if (k2 <= lx || k2 >= rx) { rects[ids[0]] = Rect{lx, ly, rx, ry}; return; }\n                L.clear(); R.clear(); sumL = 0; sumR = 0;\n                for (int id : ids) {\n                    if (comp[id].x < k2) { L.push_back(id); sumL += comp[id].r; }\n                    else { R.push_back(id); sumR += comp[id].r; }\n                }\n            }\n            if (L.empty() || R.empty()) { rects[ids[0]] = Rect{lx, ly, rx, ry}; return; }\n            self(self, lx, k, ly, ry, L, sumL, depth + 1, rng, rects);\n            self(self, k, rx, ly, ry, R, sumR, depth + 1, rng, rects);\n\n        } else {\n            int k = -1;\n            if (!candH.empty()) {\n                long double f = depthFactor(depth);\n                long double betaCut = CUT_BETA_BASE * f;\n                int take = min(TOPK_CUT, (int)candH.size());\n                vector<long double> w(take);\n                long double Z = 0;\n                for (int i = 0; i < take; i++) { w[i] = expl(-candH[i].cost * betaCut); Z += w[i]; }\n                if (Z <= 0) k = candH[0].k;\n                else {\n                    long double u = (long double)(rng() % 1000000) / 1000000.0L * Z;\n                    long double acc = 0;\n                    for (int i = 0; i < take; i++) {\n                        acc += w[i];\n                        if (u <= acc) { k = candH[i].k; break; }\n                    }\n                }\n            }\n            if (k <= ly || k >= ry) k = fallbackSplitH(ids, ly, ry);\n            if (k <= ly || k >= ry) { rects[ids[0]] = Rect{lx, ly, rx, ry}; return; }\n\n            vector<int> B, T;\n            ll sumB = 0, sumT = 0;\n            for (int id : ids) {\n                if (comp[id].y < k) { B.push_back(id); sumB += comp[id].r; }\n                else { T.push_back(id); sumT += comp[id].r; }\n            }\n            if (B.empty() || T.empty()) {\n                int k2 = fallbackSplitH(ids, ly, ry);\n                if (k2 <= ly || k2 >= ry) { rects[ids[0]] = Rect{lx, ly, rx, ry}; return; }\n                B.clear(); T.clear(); sumB = 0; sumT = 0;\n                for (int id : ids) {\n                    if (comp[id].y < k2) { B.push_back(id); sumB += comp[id].r; }\n                    else { T.push_back(id); sumT += comp[id].r; }\n                }\n            }\n            if (B.empty() || T.empty()) { rects[ids[0]] = Rect{lx, ly, rx, ry}; return; }\n            self(self, lx, rx, ly, k, B, sumB, depth + 1, rng, rects);\n            self(self, lx, rx, k, ry, T, sumT, depth + 1, rng, rects);\n        }\n    };\n\n    vector<int> allIds(n);\n    iota(allIds.begin(), allIds.end(), 0);\n    ll sumRAll = 0;\n    for (auto &c : comp) sumRAll += c.r;\n\n    ll areaRoot = 1LL * N * N;\n\n    long double bestScore = -1e100L;\n    vector<Rect> bestRects(n);\n\n    int iter = 0;\n    while (true) {\n        int elapsed = (int)chrono::duration_cast<chrono::milliseconds>(chrono::steady_clock::now() - start).count();\n        if (elapsed >= TIME_LIMIT_MS) break;\n\n        iter++;\n        mt19937_64 rng(baseSeed ^ (uint64_t)iter * 0x9e3779b97f4a7c15ULL);\n\n        // Generate root candidates (with this rng)\n        vector<Cand> candV = getCandidates(allIds, 0, N, 0, N, areaRoot, sumRAll, true, rng);\n        vector<Cand> candH = getCandidates(allIds, 0, N, 0, N, areaRoot, sumRAll, false, rng);\n\n        struct RootAct { bool vertical; int k; long double cost; };\n        vector<RootAct> acts;\n\n        for (int i = 0; i < (int)candV.size() && i < BEAM_ROOT; i++)\n            acts.push_back({true, candV[i].k, candV[i].cost});\n        for (int i = 0; i < (int)candH.size() && i < BEAM_ROOT; i++)\n            acts.push_back({false, candH[i].k, candH[i].cost});\n\n        if (acts.empty()) continue;\n        sort(acts.begin(), acts.end(), [&](const RootAct& a, const RootAct& b){\n            return a.cost < b.cost;\n        });\n        if ((int)acts.size() > BEAM_ROOT) acts.resize(BEAM_ROOT);\n\n        RootAct bestAct = acts[0];\n        long double bestLocalScore = -1e100L;\n        vector<Rect> bestLocalRects;\n\n        auto applyRootAndRun = [&](const RootAct& act, uint64_t seedOffset) -> pair<long double, vector<Rect>> {\n            vector<Rect> rects(n);\n            vector<int> ids1, ids2;\n            ll sum1 = 0, sum2 = 0;\n\n            if (act.vertical) {\n                for (int id : allIds) {\n                    if (comp[id].x < act.k) { ids1.push_back(id); sum1 += comp[id].r; }\n                    else { ids2.push_back(id); sum2 += comp[id].r; }\n                }\n            } else {\n                for (int id : allIds) {\n                    if (comp[id].y < act.k) { ids1.push_back(id); sum1 += comp[id].r; }\n                    else { ids2.push_back(id); sum2 += comp[id].r; }\n                }\n            }\n            if (ids1.empty() || ids2.empty()) return {-1e100L, {}};\n\n            mt19937_64 rng2(rng() ^ seedOffset);\n            // depth=1 after root\n            if (act.vertical) {\n                build(build, 0, act.k, 0, N, ids1, sum1, 1, rng2, rects);\n                build(build, act.k, N, 0, N, ids2, sum2, 1, rng2, rects);\n            } else {\n                build(build, 0, N, 0, act.k, ids1, sum1, 1, rng2, rects);\n                build(build, 0, N, act.k, N, ids2, sum2, 1, rng2, rects);\n            }\n\n            long double sc = scoreOf(rects);\n            return {sc, rects};\n        };\n\n        // Beam evaluation: try each root action several times\n        for (int i = 0; i < (int)acts.size(); i++) {\n            for (int t = 0; t < RUN_PER_ACTION; t++) {\n                uint64_t seedOffset = (uint64_t)i * 1000003ULL + (uint64_t)t * 9176ULL + (uint64_t)iter * 13ULL;\n                auto res = applyRootAndRun(acts[i], seedOffset);\n                if (res.first > bestLocalScore) {\n                    bestLocalScore = res.first;\n                    bestAct = acts[i];\n                    bestLocalRects = std::move(res.second);\n                }\n            }\n            elapsed = (int)chrono::duration_cast<chrono::milliseconds>(chrono::steady_clock::now() - start).count();\n            if (elapsed >= TIME_LIMIT_MS) break;\n        }\n\n        // Exploit: fix the best root action, do more restarts\n        while (true) {\n            elapsed = (int)chrono::duration_cast<chrono::milliseconds>(chrono::steady_clock::now() - start).count();\n            if (elapsed >= TIME_LIMIT_MS) break;\n\n            uint64_t seedOffset = (uint64_t)iter * 10000019ULL + (uint64_t)(bestLocalScore * 1e6) + (uint64_t)elapsed;\n            auto res = applyRootAndRun(bestAct, seedOffset);\n            if (res.first > bestLocalScore) {\n                bestLocalScore = res.first;\n                bestLocalRects = std::move(res.second);\n            }\n        }\n\n        if (bestLocalScore > bestScore) {\n            bestScore = bestLocalScore;\n            bestRects = bestLocalRects;\n        }\n    }\n\n    for (int i = 0; i < n; i++) {\n        cout << bestRects[i].a << ' ' << bestRects[i].b << ' '\n             << bestRects[i].c << ' ' << bestRects[i].d << '\\n';\n    }\n    return 0;\n}","ahc002":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const int H = 50, W = 50;\nstatic const int N = H * W;\n\nstatic inline int id(int i, int j) { return i * W + j; }\n\nstatic char dirBetween(int a, int b) {\n    int ai = a / W, aj = a % W;\n    int bi = b / W, bj = b % W;\n    if (bi == ai - 1 && bj == aj) return 'U';\n    if (bi == ai + 1 && bj == aj) return 'D';\n    if (bi == ai && bj == aj - 1) return 'L';\n    if (bi == ai && bj == aj + 1) return 'R';\n    return '?';\n}\n\nstruct RNG {\n    mt19937_64 mt;\n    RNG() : mt((uint64_t)chrono::steady_clock::now().time_since_epoch().count()) {}\n    int nextInt(int l, int r) { return uniform_int_distribution<int>(l, r)(mt); } // inclusive\n    double nextDouble() { return uniform_real_distribution<double>(0.0, 1.0)(mt); }\n};\n\nstruct Param {\n    double beta;       // weight for best future p\n    double gammaAvail;// weight for mobility (avail moves from candidate)\n    double gammaDistinct; // weight for precomputed distinct neighbors\n    double temp;      // softmax temp for suffix repair\n    double noise;     // noise magnitude for ordering/backtracking\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int si, sj;\n    cin >> si >> sj;\n\n    vector<int> tile(N);\n    for (int i = 0; i < H; i++) for (int j = 0; j < W; j++) cin >> tile[id(i, j)];\n\n    vector<int> p(N);\n    for (int i = 0; i < H; i++) for (int j = 0; j < W; j++) cin >> p[id(i, j)];\n\n    int M = 0;\n    for (int x : tile) M = max(M, x + 1);\n    int start = id(si, sj);\n\n    // neighbors on squares\n    vector<array<int,4>> neigh(N);\n    for (int i = 0; i < H; i++) for (int j = 0; j < W; j++) {\n        int v = id(i, j);\n        array<int,4> a; a.fill(-1);\n        if (i > 0) a[0] = id(i-1, j);\n        if (i+1 < H) a[1] = id(i+1, j);\n        if (j > 0) a[2] = id(i, j-1);\n        if (j+1 < W) a[3] = id(i, j+1);\n        neigh[v] = a;\n    }\n\n    // cntAdjDistinct[v] = distinct tile IDs among neighbors of v excluding same tile\n    vector<int> cntAdjDistinct(N, 0);\n    for (int v = 0; v < N; v++) {\n        int tv = tile[v];\n        int seen[4]; int sc = 0;\n        for (int k = 0; k < 4; k++) {\n            int u = neigh[v][k];\n            if (u < 0) continue;\n            int tu = tile[u];\n            if (tu == tv) continue;\n            bool ok = true;\n            for (int q = 0; q < sc; q++) if (seen[q] == tu) ok = false;\n            if (!ok) continue;\n            seen[sc++] = tu;\n        }\n        cntAdjDistinct[v] = sc;\n    }\n\n    RNG rng;\n\n    vector<int> usedStamp(M, 0);\n    int curStamp = 1;\n    auto stampReset = [&]() {\n        curStamp++;\n        if (curStamp == INT_MAX) {\n            fill(usedStamp.begin(), usedStamp.end(), 0);\n            curStamp = 1;\n        }\n    };\n    auto isUsed = [&](int tid) -> bool { return usedStamp[tid] == curStamp; };\n    auto markUsed = [&](int tid) { usedStamp[tid] = curStamp; };\n    auto unmarkUsed = [&](int tid) { usedStamp[tid] = 0; /* not necessary with stamps */ };\n\n    // compute evaluation value for moving to candidate square nb from current state\n    auto evalMove = [&](int nb, int tnb, const Param &par, const int curTile) -> double {\n        // lookahead one step from nb (after moving to nb, tile tnb becomes used, so exclude tnn==tnb)\n        int bestExit = -1;\n        int avail = 0;\n        for (int dd = 0; dd < 4; dd++) {\n            int nn = neigh[nb][dd];\n            if (nn < 0) continue;\n            int tnn = tile[nn];\n            if (tnn == tnb) continue;          // would step on same tile again\n            if (isUsed(tnn)) continue;        // forbidden because already used\n            avail++;\n            bestExit = max(bestExit, p[nn]);\n        }\n        if (bestExit < 0) bestExit = 0;\n\n        double val = (double)p[nb]\n            + par.beta * (double)bestExit\n            + par.gammaAvail * (double)avail\n            + par.gammaDistinct * (double)cntAdjDistinct[nb];\n        val += (rng.nextDouble() - 0.5) * par.noise; // tie-breaking / ordering noise\n        return val;\n    };\n\n    // DFS with backtracking and stochastic ordering (no softmax inside DFS; backtracking explores alternatives)\n    struct Frame {\n        int cand[4];\n        int sz = 0;\n        int idx = 0;\n    };\n\n    auto runDFSBacktrack = [&](const Param &par, long long timeBudgetNs,\n                               chrono::steady_clock::time_point t0,\n                               vector<int> &outPath, long long &outScore) {\n        outPath.clear();\n        outScore = -1;\n\n        stampReset();\n        markUsed(tile[start]);\n\n        vector<int> path;\n        path.reserve(M);\n        path.push_back(start);\n\n        vector<Frame> st;\n        st.reserve(M);\n\n        long long score = p[start];\n\n        auto computeCandidates = [&](int cur, Frame &fr) {\n            fr.sz = 0;\n            fr.idx = 0;\n            int tcur = tile[cur];\n            (void)tcur;\n            int tcurDummy = tcur;\n\n            for (int d = 0; d < 4; d++) {\n                int nb = neigh[cur][d];\n                if (nb < 0) continue;\n                int tnb = tile[nb];\n                if (isUsed(tnb)) continue; // cannot step on used tile again\n                fr.cand[fr.sz++] = nb;\n            }\n            // sort candidates by eval value descending (insertion sort, sz <= 4)\n            double vals[4];\n            for (int i = 0; i < fr.sz; i++) {\n                int nb = fr.cand[i];\n                vals[i] = evalMove(nb, tile[nb], par, tcurDummy);\n            }\n            for (int i = 1; i < fr.sz; i++) {\n                int x = fr.cand[i];\n                double vx = vals[i];\n                int j = i - 1;\n                while (j >= 0 && vals[j] < vx) {\n                    fr.cand[j+1] = fr.cand[j];\n                    vals[j+1] = vals[j];\n                    j--;\n                }\n                fr.cand[j+1] = x;\n                vals[j+1] = vx;\n            }\n        };\n\n        // Main DFS loop (iterative)\n        while (true) {\n            auto now = chrono::steady_clock::now();\n            long long elapsedNs = chrono::duration_cast<chrono::nanoseconds>(now - t0).count();\n            if (elapsedNs > timeBudgetNs) break;\n\n            int d = (int)path.size() - 1; // current depth, currently at path[d]\n\n            if ((int)st.size() <= d) {\n                st.emplace_back();\n                computeCandidates(path[d], st.back());\n            }\n\n            Frame &fr = st[d];\n\n            if (fr.idx >= fr.sz) {\n                // Exhausted all moves from this node; backtrack\n                st.pop_back();\n                if (d == 0) break; // finished this restart\n                int last = path.back();\n                path.pop_back();\n                score -= p[last];\n\n                // unmarking with stamps: easiest is to just increment stamp on restart;\n                // but for backtracking we need accurate state.\n                // With stamps, we can't \"unmark\" by setting to 0 without losing other marks.\n                // We'll implement unmark by keeping a stack of visited tile ids and clearing them.\n                // (Because candidate branching is tiny, overhead is fine.)\n                // We'll do it by tracking visited tiles in another stack below.\n            } else {\n                int nb = fr.cand[fr.idx++];\n\n                // mark tile nb as used, push nb\n                int tnb = tile[nb];\n                // We need proper unmark on backtrack: implement by setting usedStamp[tnb]=0\n                // (safe because stamps ensure only current stamp matters; setting to 0 clears it).\n                // Note: marking uses current stamp.\n                usedStamp[tnb] = curStamp;\n\n                path.push_back(nb);\n                score += p[nb];\n                // update best\n                if (score > outScore) {\n                    outScore = score;\n                    outPath = path;\n                }\n                // continue deeper; next loop will compute st[d+1]\n                continue;\n            }\n\n            // If we backtracked above, we must unmark the tile of the removed last node.\n            // But because we didn't track which tile to unmark at the time we popped,\n            // we do it here using tile[last] from the current path pop.\n            // However the code popped already above; adjust:\n            // We'll implement correct behavior by restructuring to always know 'last' on pop.\n            // To keep code correct, we redo DFS properly below.\n        }\n    };\n\n    // The DFS above had an unmark issue with stamps. Let's implement a correct DFS:\n    auto runDFSBacktrack2 = [&](const Param &par, long long timeBudgetNs,\n                                chrono::steady_clock::time_point t0,\n                                vector<int> &outPath, long long &outScore) {\n        outPath.clear();\n        outScore = -1;\n\n        stampReset();\n        // visited tiles stack for unmark\n        vector<int> tileStack;\n        tileStack.reserve(M);\n\n        usedStamp[tile[start]] = curStamp;\n        tileStack.push_back(tile[start]);\n\n        long long score = p[start];\n\n        vector<int> path;\n        path.reserve(M);\n        path.push_back(start);\n\n        vector<Frame> st;\n        st.reserve(M);\n\n        auto computeCandidates = [&](int cur, Frame &fr) {\n            fr.sz = 0;\n            fr.idx = 0;\n            for (int d = 0; d < 4; d++) {\n                int nb = neigh[cur][d];\n                if (nb < 0) continue;\n                int tnb = tile[nb];\n                if (usedStamp[tnb] == curStamp) continue;\n                fr.cand[fr.sz++] = nb;\n            }\n            double vals[4];\n            for (int i = 0; i < fr.sz; i++) vals[i] = 0.0;\n            int tcurDummy = tile[cur];\n            for (int i = 0; i < fr.sz; i++) {\n                int nb = fr.cand[i];\n                int tnb = tile[nb];\n                int bestExit = -1;\n                int avail = 0;\n                for (int dd = 0; dd < 4; dd++) {\n                    int nn = neigh[nb][dd];\n                    if (nn < 0) continue;\n                    int tnn = tile[nn];\n                    if (tnn == tnb) continue; // same tile, forbidden next\n                    if (usedStamp[tnn] == curStamp) continue;\n                    avail++;\n                    bestExit = max(bestExit, p[nn]);\n                }\n                if (bestExit < 0) bestExit = 0;\n                vals[i] = (double)p[nb]\n                        + par.beta * (double)bestExit\n                        + par.gammaAvail * (double)avail\n                        + par.gammaDistinct * (double)cntAdjDistinct[nb]\n                        + (rng.nextDouble() - 0.5) * par.noise;\n            }\n            // insertion sort by vals desc\n            for (int i = 1; i < fr.sz; i++) {\n                int x = fr.cand[i];\n                double vx = vals[i];\n                int j = i - 1;\n                while (j >= 0 && vals[j] < vx) {\n                    fr.cand[j+1] = fr.cand[j];\n                    vals[j+1] = vals[j];\n                    j--;\n                }\n                fr.cand[j+1] = x;\n                vals[j+1] = vx;\n            }\n        };\n\n        if (p[start] > outScore) {\n            outScore = p[start];\n            outPath = path;\n        }\n\n        while (true) {\n            auto now = chrono::steady_clock::now();\n            long long elapsedNs = chrono::duration_cast<chrono::nanoseconds>(now - t0).count();\n            if (elapsedNs > timeBudgetNs) break;\n\n            int d = (int)path.size() - 1;\n            if ((int)st.size() <= d) {\n                st.emplace_back();\n                computeCandidates(path[d], st.back());\n            }\n            Frame &fr = st[d];\n\n            if (fr.idx >= fr.sz) {\n                // backtrack one step\n                st.pop_back();\n                if (d == 0) break;\n                int lastSq = path.back();\n                path.pop_back();\n                score -= p[lastSq];\n\n                // unmark tile of lastSq\n                int tlast = tile[lastSq];\n                usedStamp[tlast] = 0;\n                tileStack.pop_back();\n                continue;\n            }\n\n            int nb = fr.cand[fr.idx++];\n            int tnb = tile[nb];\n            // mark + move\n            usedStamp[tnb] = curStamp;\n            tileStack.push_back(tnb);\n\n            path.push_back(nb);\n            score += p[nb];\n\n            if (score > outScore) {\n                outScore = score;\n                outPath = path;\n            }\n            // next depth frame will be computed in next loop iteration\n        }\n    };\n\n    auto runSuffixWalk = [&](const Param &par, long long timeBudgetNs,\n                              chrono::steady_clock::time_point t0,\n                              const vector<int> &prefixPath, int cutIdx,\n                              vector<int> &outMerged, long long baseScore) {\n        // used tiles from prefix\n        stampReset();\n\n        for (int i = 0; i <= cutIdx; i++) {\n            int sq = prefixPath[i];\n            usedStamp[tile[sq]] = curStamp;\n        }\n\n        int cur = prefixPath[cutIdx];\n        long long score = baseScore;\n\n        vector<int> suffix;\n        suffix.reserve(N);\n        suffix.push_back(cur);\n\n        int candSq[4];\n        double candVal[4];\n\n        auto computeCandList = [&](int v, int &k) {\n            k = 0;\n            int tv = tile[v];\n            (void)tv;\n            for (int d = 0; d < 4; d++) {\n                int nb = neigh[v][d];\n                if (nb < 0) continue;\n                int tnb = tile[nb];\n                if (usedStamp[tnb] == curStamp) continue; // tile must be unvisited\n                // lookahead from nb after stepping onto nb:\n                int bestExit = -1;\n                int avail = 0;\n                for (int dd = 0; dd < 4; dd++) {\n                    int nn = neigh[nb][dd];\n                    if (nn < 0) continue;\n                    int tnn = tile[nn];\n                    if (tnn == tnb) continue;\n                    if (usedStamp[tnn] == curStamp) continue;\n                    avail++;\n                    bestExit = max(bestExit, p[nn]);\n                }\n                if (bestExit < 0) bestExit = 0;\n\n                double val = (double)p[nb]\n                           + par.beta * (double)bestExit\n                           + par.gammaAvail * (double)avail\n                           + par.gammaDistinct * (double)cntAdjDistinct[nb]\n                           + (rng.nextDouble() - 0.5) * par.noise * 0.2;\n                candSq[k] = nb;\n                candVal[k] = val;\n                k++;\n            }\n            // sort descending by candVal (small k<=4)\n            for (int i = 1; i < k; i++) {\n                int xs = candSq[i];\n                double xv = candVal[i];\n                int j = i - 1;\n                while (j >= 0 && candVal[j] < xv) {\n                    candSq[j+1] = candSq[j];\n                    candVal[j+1] = candVal[j];\n                    j--;\n                }\n                candSq[j+1] = xs;\n                candVal[j+1] = xv;\n            }\n        };\n\n        while (true) {\n            auto now = chrono::steady_clock::now();\n            long long elapsedNs = chrono::duration_cast<chrono::nanoseconds>(now - t0).count();\n            if (elapsedNs > timeBudgetNs) break;\n\n            int k = 0;\n            computeCandList(cur, k);\n            if (k == 0) break;\n\n            int K = min(k, 4);\n            double mx = -1e100;\n            for (int i = 0; i < K; i++) mx = max(mx, candVal[i]);\n            double sumW = 0.0;\n            double w[4];\n            for (int i = 0; i < K; i++) {\n                w[i] = exp((candVal[i] - mx) / max(1e-6, par.temp));\n                sumW += w[i];\n            }\n            double r = rng.nextDouble() * sumW;\n            int pick = 0;\n            for (int i = 0; i < K; i++) {\n                if (r <= w[i]) { pick = i; break; }\n                r -= w[i];\n            }\n\n            int nxt = candSq[pick];\n            usedStamp[tile[nxt]] = curStamp;\n            cur = nxt;\n            suffix.push_back(cur);\n            score += p[cur];\n        }\n\n        outMerged.clear();\n        outMerged.reserve(prefixPath.size() + suffix.size());\n        for (int i = 0; i <= cutIdx; i++) outMerged.push_back(prefixPath[i]);\n        for (int i = 1; i < (int)suffix.size(); i++) outMerged.push_back(suffix[i]);\n\n        return score;\n    };\n\n    auto t0 = chrono::steady_clock::now();\n    double TIME_LIMIT = 1.98;\n    long long totalBudgetNs = (long long)(TIME_LIMIT * 1e9);\n\n    vector<Param> params = {\n        {0.95, 1.00, 0.85, 1.25, 0.20},\n        {1.10, 0.80, 1.10, 1.15, 0.18},\n        {0.80, 1.35, 0.70, 1.35, 0.22},\n        {1.20, 0.65, 0.95, 1.05, 0.16}\n    };\n\n    vector<int> bestPath, tmpPath, merged;\n    long long bestScore = -1;\n\n    // Phase 1: multiple restarts with DFS backtracking\n    while (true) {\n        auto now = chrono::steady_clock::now();\n        long long elapsed = chrono::duration_cast<chrono::nanoseconds>(now - t0).count();\n        if (elapsed > totalBudgetNs) break;\n\n        const Param &par = params[rng.nextInt(0, (int)params.size() - 1)];\n\n        vector<int> path;\n        long long sc = -1;\n\n        // give each DFS restart a small slice\n        long long slice = (long long)(0.07 * 1e9); // 70ms\n        auto now2 = chrono::steady_clock::now();\n        long long startElapsed = chrono::duration_cast<chrono::nanoseconds>(now2 - t0).count();\n        if (startElapsed + slice > totalBudgetNs) slice = max(1LL, totalBudgetNs - startElapsed);\n\n        runDFSBacktrack2(par, slice, t0, path, sc);\n\n        if (sc > bestScore) {\n            bestScore = sc;\n            bestPath = std::move(path);\n        }\n    }\n\n    // Phase 2: suffix repair on best path\n    if (!bestPath.empty()) {\n        int L = (int)bestPath.size();\n        int regionL = max(0, L - 700);\n\n        // choose cut points near the end, biased by low p (often helps escape)\n        vector<pair<int,double>> cutW;\n        cutW.reserve(L);\n        for (int i = regionL; i < L; i++) {\n            double w = (100.0 - p[bestPath[i]] + 1.0);\n            w = max(0.1, w);\n            cutW.push_back({i, w});\n        }\n\n        long long remain = totalBudgetNs - chrono::duration_cast<chrono::nanoseconds>(chrono::steady_clock::now() - t0).count();\n        long long sliceTotal = min(remain, (long long)(0.45 * 1e9));\n\n        // sample ~70 cuts max\n        vector<int> cuts;\n        int attemptsCuts = 0;\n        while ((int)cuts.size() < 70 && attemptsCuts < 200) {\n            attemptsCuts++;\n            double sumW = 0;\n            for (auto &x : cutW) sumW += x.second;\n            double r = rng.nextDouble() * sumW;\n            int pick = cutW.back().first;\n            for (auto &x : cutW) {\n                r -= x.second;\n                if (r <= 0) { pick = x.first; break; }\n            }\n            cuts.push_back(pick);\n        }\n        sort(cuts.begin(), cuts.end());\n        cuts.erase(unique(cuts.begin(), cuts.end()), cuts.end());\n        if (cuts.empty()) cuts.push_back(L - 1);\n\n        for (int cutIdx : cuts) {\n            auto now = chrono::steady_clock::now();\n            long long elapsed = chrono::duration_cast<chrono::nanoseconds>(now - t0).count();\n            long long remaining = totalBudgetNs - elapsed;\n            if (remaining <= 0) break;\n\n            long long perCut = min(remaining, (long long)(0.01 * 1e9)); // 10ms each attempt\n            if (perCut <= 0) break;\n\n            // baseScore of prefix\n            long long base = 0;\n            for (int i = 0; i <= cutIdx; i++) base += p[bestPath[i]];\n\n            for (int rep = 0; rep < 3; rep++) {\n                const Param &par = params[(cutIdx + rep) % params.size()];\n                merged.clear();\n                long long sc2 = runSuffixWalk(par, perCut, t0, bestPath, cutIdx, merged, base);\n                if (sc2 > bestScore) {\n                    bestScore = sc2;\n                    bestPath = merged;\n                }\n            }\n        }\n    }\n\n    // Output directions\n    string ans;\n    if (!bestPath.empty()) {\n        ans.reserve(max(0, (int)bestPath.size() - 1));\n        for (int i = 1; i < (int)bestPath.size(); i++) {\n            ans.push_back(dirBetween(bestPath[i-1], bestPath[i]));\n        }\n    }\n    cout << ans << \"\\n\";\n    return 0;\n}","ahc003":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int H = 30;\nstatic constexpr int W = 30;\nstatic constexpr int N = H * W;\n\nstatic constexpr int HOR = H * (W - 1);   // 30*29 = 870\nstatic constexpr int VER = (H - 1) * W;   // 29*30 = 870\nstatic constexpr int ECOUNT = HOR + VER;  // 1740\n\nstatic inline int idx_node(int i, int j) { return i * W + j; }\nstatic inline int idx_horizontal_edge(int i, int j) { return i * (W - 1) + j; } // j in [0..28]\nstatic inline int idx_vertical_edge(int i, int j) { return HOR + i * W + j; }    // i in [0..28]\n\nstruct PathResult {\n    string moves;\n    vector<int> usedEdges;\n};\n\nstruct FitLine {\n    bool two = false;\n    int split = 0;         // left: [0..split-1], right: [split..n-1]\n    double mean1 = 0.0;\n    double meanL = 0.0;\n    double meanR = 0.0;\n    double bestCost = 0.0;\n};\n\nstruct SegmentParam {\n    bool isRow;   // true: row segments (horizontal edges), false: col segments (vertical edges)\n    int idx;      // row index or col index\n    bool two;     // if false => single segment (side ignored)\n    int side;     // 0/1 if two\n    int split;    // valid if two (split position)\n    long long cnt = 0;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // Build adjacency\n    vector<vector<pair<int,int>>> adj(N);\n    for (int i = 0; i < H; i++) for (int j = 0; j < W; j++) {\n        int u = idx_node(i, j);\n        if (j + 1 < W) {\n            int v = idx_node(i, j + 1);\n            int e = idx_horizontal_edge(i, j);\n            adj[u].push_back({v, e});\n            adj[v].push_back({u, e});\n        }\n        if (i + 1 < H) {\n            int v = idx_node(i + 1, j);\n            int e = idx_vertical_edge(i, j);\n            adj[u].push_back({v, e});\n            adj[v].push_back({u, e});\n        }\n    }\n\n    const double LO_W = 500.0;\n    const double HI_W = 9500.0;\n\n    auto clampW = [&](long double x) -> double {\n        if (x < (long double)LO_W) return LO_W;\n        if (x > (long double)HI_W) return HI_W;\n        return (double)x;\n    };\n\n    vector<double> w_hat(ECOUNT, 5000.0), w_noisy(ECOUNT, 5000.0);\n\n    mt19937_64 rng(123456789ULL);\n    auto rand01 = [&]() -> double {\n        return (rng() >> 11) * (1.0 / 9007199254740992.0);\n    };\n    normal_distribution<double> gauss(0.0, 1.0);\n\n    // Dijkstra buffers\n    const double INF = 1e100;\n    vector<double> dist(N);\n    vector<int> parent(N), parentEdge(N);\n\n    auto build_path = [&](int s, int t) -> PathResult {\n        PathResult res;\n        if (s == t) return res;\n        if (parent[t] < 0) return res;\n\n        vector<char> revMoves;\n        vector<int> revEdges;\n        int cur = t;\n        while (cur != s) {\n            int p = parent[cur];\n            int e = parentEdge[cur];\n            if (p < 0 || e < 0) return PathResult{};\n\n            int pi = p / W, pj = p % W;\n            int ci = cur / W, cj = cur % W;\n\n            char mv;\n            if (ci == pi - 1 && cj == pj) mv = 'U';\n            else if (ci == pi + 1 && cj == pj) mv = 'D';\n            else if (ci == pi && cj == pj - 1) mv = 'L';\n            else if (ci == pi && cj == pj + 1) mv = 'R';\n            else mv = '?';\n\n            revMoves.push_back(mv);\n            revEdges.push_back(e);\n            cur = p;\n        }\n\n        reverse(revMoves.begin(), revMoves.end());\n        reverse(revEdges.begin(), revEdges.end());\n        res.moves.assign(revMoves.begin(), revMoves.end());\n        res.usedEdges = std::move(revEdges);\n        return res;\n    };\n\n    auto dijkstra_path = [&](int s, int t, const double* w_use) -> PathResult {\n        for (int i = 0; i < N; i++) {\n            dist[i] = INF;\n            parent[i] = -1;\n            parentEdge[i] = -1;\n        }\n\n        struct State {\n            double d; int v;\n            bool operator>(const State& o) const { return d > o.d; }\n        };\n\n        priority_queue<State, vector<State>, greater<State>> pq;\n        dist[s] = 0.0;\n        parent[s] = s;\n        pq.push({0.0, s});\n\n        const double EPS = 1e-12;\n        while (!pq.empty()) {\n            auto [dcur, u] = pq.top();\n            pq.pop();\n            if (dcur != dist[u]) continue;\n            if (u == t) break;\n\n            for (auto [to, e] : adj[u]) {\n                double nd = dcur + w_use[e];\n                if (nd + EPS < dist[to]) {\n                    dist[to] = nd;\n                    parent[to] = u;\n                    parentEdge[to] = e;\n                    pq.push({nd, to});\n                } else if (fabs(nd - dist[to]) <= EPS) {\n                    if (rand01() < 0.5) {\n                        parent[to] = u;\n                        parentEdge[to] = e;\n                        pq.push({nd, to});\n                    }\n                }\n            }\n        }\n        return build_path(s, t);\n    };\n\n    auto monotone_path = [&](int s, int t) -> PathResult {\n        int si = s / W, sj = s % W;\n        int ti = t / W, tj = t % W;\n        int i = si, j = sj;\n\n        PathResult res;\n        while (i != ti || j != tj) {\n            bool canV = (i != ti);\n            bool canH = (j != tj);\n            bool doV = (canV && canH) ? (rand01() < 0.5) : canV;\n\n            if (doV) {\n                if (ti > i) {\n                    int e = idx_vertical_edge(i, j);\n                    res.usedEdges.push_back(e);\n                    res.moves.push_back('D');\n                    i++;\n                } else {\n                    int e = idx_vertical_edge(i - 1, j);\n                    res.usedEdges.push_back(e);\n                    res.moves.push_back('U');\n                    i--;\n                }\n            } else {\n                if (tj > j) {\n                    int e = idx_horizontal_edge(i, j);\n                    res.usedEdges.push_back(e);\n                    res.moves.push_back('R');\n                    j++;\n                } else {\n                    int e = idx_horizontal_edge(i, j - 1);\n                    res.usedEdges.push_back(e);\n                    res.moves.push_back('L');\n                    j--;\n                }\n            }\n        }\n        return res;\n    };\n\n    auto fit_row = [&](int row, double TH) -> FitLine {\n        // horizontal row, n=29 edges j=0..28\n        const int n = W - 1;\n        array<double, W> a{};\n        for (int j = 0; j < n; j++) a[j] = w_hat[idx_horizontal_edge(row, j)];\n\n        double sum = 0.0, sumsq = 0.0;\n        for (int j = 0; j < n; j++) { sum += a[j]; sumsq += a[j] * a[j]; }\n        double mean1 = sum / n;\n        double cost1 = sumsq - (double)n * mean1 * mean1;\n\n        array<double, W> pref{}, pref2{};\n        pref[0] = pref2[0] = 0.0;\n        for (int j = 0; j < n; j++) {\n            pref[j + 1] = pref[j] + a[j];\n            pref2[j + 1] = pref2[j] + a[j] * a[j];\n        }\n\n        double bestCost = cost1;\n        int bestX = 0;\n        double bestMeanL = mean1, bestMeanR = mean1;\n\n        for (int x = 1; x <= n - 1; x++) {\n            int nl = x, nr = n - x;\n            double sumL = pref[x], sumR = pref[n] - pref[x];\n            double sumsqL = pref2[x], sumsqR = pref2[n] - pref2[x];\n            double meanL = sumL / nl;\n            double meanR = sumR / nr;\n            double cost = (sumsqL - (double)nl * meanL * meanL) + (sumsqR - (double)nr * meanR * meanR);\n            if (cost < bestCost) {\n                bestCost = cost;\n                bestX = x;\n                bestMeanL = meanL;\n                bestMeanR = meanR;\n            }\n        }\n\n        FitLine f;\n        f.mean1 = mean1;\n        f.bestCost = bestCost;\n        if (cost1 > 1e-9 && bestCost < cost1 * TH) {\n            f.two = true;\n            f.split = bestX;\n            f.meanL = bestMeanL;\n            f.meanR = bestMeanR;\n        } else {\n            f.two = false;\n            f.split = 0;\n            f.meanL = mean1;\n            f.meanR = mean1;\n        }\n        return f;\n    };\n\n    auto fit_col = [&](int col, double TH) -> FitLine {\n        // vertical column, n=29 edges i=0..28\n        const int n = H - 1;\n        array<double, H> a{};\n        for (int i = 0; i < n; i++) a[i] = w_hat[idx_vertical_edge(i, col)];\n\n        double sum = 0.0, sumsq = 0.0;\n        for (int i = 0; i < n; i++) { sum += a[i]; sumsq += a[i] * a[i]; }\n        double mean1 = sum / n;\n        double cost1 = sumsq - (double)n * mean1 * mean1;\n\n        array<double, H> pref{}, pref2{};\n        pref[0] = pref2[0] = 0.0;\n        for (int i = 0; i < n; i++) {\n            pref[i + 1] = pref[i] + a[i];\n            pref2[i + 1] = pref2[i] + a[i] * a[i];\n        }\n\n        double bestCost = cost1;\n        int bestY = 0;\n        double bestMeanT = mean1, bestMeanB = mean1;\n\n        for (int y = 1; y <= n - 1; y++) {\n            int nt = y, nb = n - y;\n            double sumT = pref[y], sumB = pref[n] - pref[y];\n            double sumsqT = pref2[y], sumsqB = pref2[n] - pref2[y];\n            double meanT = sumT / nt;\n            double meanB = sumB / nb;\n            double cost = (sumsqT - (double)nt * meanT * meanT) + (sumsqB - (double)nb * meanB * meanB);\n            if (cost < bestCost) {\n                bestCost = cost;\n                bestY = y;\n                bestMeanT = meanT;\n                bestMeanB = meanB;\n            }\n        }\n\n        FitLine f;\n        f.mean1 = mean1;\n        f.bestCost = bestCost;\n        if (cost1 > 1e-9 && bestCost < cost1 * TH) {\n            f.two = true;\n            f.split = bestY;\n            f.meanL = bestMeanT; // top\n            f.meanR = bestMeanB; // bottom\n        } else {\n            f.two = false;\n            f.split = 0;\n            f.meanL = mean1;\n            f.meanR = mean1;\n        }\n        return f;\n    };\n\n    for (int k = 0; k < 1000; k++) {\n        int si, sj, ti, tj;\n        if (!(cin >> si >> sj >> ti >> tj)) return 0;\n        int s = idx_node(si, sj);\n        int t = idx_node(ti, tj);\n\n        PathResult cand_det = dijkstra_path(s, t, w_hat.data());\n        if (cand_det.moves.empty()) cand_det = monotone_path(s, t);\n\n        long double pred_det = 0;\n        for (int e : cand_det.usedEdges) pred_det += (long double)w_hat[e];\n\n        // exploration\n        double pNoisy = (k < 160 ? 0.55 : (k < 520 ? 0.26 : 0.12));\n        bool doNoisy = (rand01() < pNoisy);\n\n        PathResult chosen = cand_det;\n        long double pred_chosen = pred_det;\n\n        if (doNoisy) {\n            double sigmaBase = 1400.0 + 900.0 * (1.0 - min(1.0, (double)k / 700.0));\n            double sigmaEdge = 160.0;\n\n            array<double, H> rowOff{};\n            array<double, W> colOff{};\n            for (int i = 0; i < H; i++) rowOff[i] = gauss(rng) * sigmaBase;\n            for (int j = 0; j < W; j++) colOff[j] = gauss(rng) * sigmaBase;\n\n            for (int e = 0; e < ECOUNT; e++) {\n                double w = w_hat[e];\n                if (e < HOR) {\n                    int row = e / (W - 1);\n                    w += rowOff[row] + gauss(rng) * sigmaEdge;\n                } else {\n                    int z = e - HOR;\n                    int col = z % W;\n                    w += colOff[col] + gauss(rng) * sigmaEdge;\n                }\n                w_noisy[e] = clampW((long double)w);\n            }\n\n            PathResult cand_noi = dijkstra_path(s, t, w_noisy.data());\n            if (!cand_noi.moves.empty()) {\n                long double pred_noi = 0;\n                for (int e : cand_noi.usedEdges) pred_noi += (long double)w_hat[e];\n\n                // soft selection: better predicted => more likely\n                long double diff = pred_noi - pred_det; // negative => better\n                long double T = 7000.0L;\n                long double prob_noi = 1.0L / (1.0L + expl(diff / T));\n                if (rand01() < (double)prob_noi) {\n                    chosen = std::move(cand_noi);\n                    pred_chosen = pred_noi;\n                }\n            }\n        }\n\n        cout << chosen.moves << '\\n' << flush;\n\n        long long y_int;\n        if (!(cin >> y_int)) return 0;\n        long double y = (long double)y_int;\n\n        int m = (int)chosen.usedEdges.size();\n        if (m == 0) continue;\n\n        long double err = y - pred_chosen;\n        long double bound = 0.45L * max(1.0L, pred_chosen);\n        if (err > bound) err = bound;\n        if (err < -bound) err = -bound;\n\n        // touched lines\n        array<char, H> usedRows{};\n        array<char, W> usedCols{};\n        for (int e : chosen.usedEdges) {\n            if (e < HOR) usedRows[e / (W - 1)] = 1;\n            else usedCols[(e - HOR) % W] = 1;\n        }\n\n        // stricter THfit helps prevent wrong split oscillation\n        double THfit = (k < 200 ? 0.78 : (k < 600 ? 0.75 : 0.72));\n        vector<FitLine> rowFit(H), colFit(W);\n        vector<int> touchRow, touchCol;\n        for (int i = 0; i < H; i++) if (usedRows[i]) { rowFit[i] = fit_row(i, THfit); touchRow.push_back(i); }\n        for (int j = 0; j < W; j++) if (usedCols[j]) { colFit[j] = fit_col(j, THfit); touchCol.push_back(j); }\n\n        // build segment params for touched lines\n        vector<SegmentParam> params;\n        auto addParam = [&](bool isRow, int idx, bool two, int side, int split) {\n            SegmentParam p;\n            p.isRow = isRow; p.idx = idx; p.two = two;\n            p.side = side; p.split = split; p.cnt = 0;\n            params.push_back(p);\n        };\n\n        for (int i : touchRow) {\n            if (rowFit[i].two) {\n                addParam(true, i, true, 0, rowFit[i].split);\n                addParam(true, i, true, 1, rowFit[i].split);\n            } else {\n                addParam(true, i, false, 0, 0);\n            }\n        }\n        for (int j : touchCol) {\n            if (colFit[j].two) {\n                addParam(false, j, true, 0, colFit[j].split); // top\n                addParam(false, j, true, 1, colFit[j].split); // bottom\n            } else {\n                addParam(false, j, false, 0, 0);\n            }\n        }\n\n        auto findParamIndex = [&](bool isRow, int idx, bool two, int side) -> int {\n            for (int pid = 0; pid < (int)params.size(); pid++) {\n                if (params[pid].isRow != isRow) continue;\n                if (params[pid].idx != idx) continue;\n                if (params[pid].two != two) continue;\n                if (params[pid].side != side) continue;\n                return pid;\n            }\n            return -1;\n        };\n\n        for (int e : chosen.usedEdges) {\n            if (e < HOR) {\n                int row = e / (W - 1);\n                int pos = e % (W - 1); // 0..28\n                if (rowFit[row].two) {\n                    int side = (pos < rowFit[row].split ? 0 : 1);\n                    int pid = findParamIndex(true, row, true, side);\n                    if (pid >= 0) params[pid].cnt++;\n                } else {\n                    int pid = findParamIndex(true, row, false, 0);\n                    if (pid >= 0) params[pid].cnt++;\n                }\n            } else {\n                int col = (e - HOR) % W;\n                int pos = (e - HOR) / W; // i in 0..28\n                if (colFit[col].two) {\n                    int side = (pos < colFit[col].split ? 0 : 1); // top/bottom\n                    int pid = findParamIndex(false, col, true, side);\n                    if (pid >= 0) params[pid].cnt++;\n                } else {\n                    int pid = findParamIndex(false, col, false, 0);\n                    if (pid >= 0) params[pid].cnt++;\n                }\n            }\n        }\n\n        long double eta = 0.24L / sqrt((long double)(k + 1));\n        eta = max((long double)0.0025, eta);\n\n        // === CHANGED: denom = m (not \u03a3 cnt^2) to avoid under-updating ===\n        long double denom = (long double)m;\n\n        // segment shift magnitude scaling (slightly larger early)\n        long double betaSeg = (k < 200 ? 1.10L : (k < 600 ? 1.00L : 0.95L));\n\n        for (auto &p : params) {\n            if (p.cnt == 0) continue;\n            long double c = (long double)p.cnt;\n            long double delta = eta * err * (c / denom) * betaSeg;\n\n            if (fabsl(delta) < 1e-18L) continue;\n\n            if (p.isRow) {\n                int row = p.idx;\n                int nEdges = W - 1;\n                if (p.two) {\n                    int split = p.split;\n                    for (int j = 0; j < nEdges; j++) {\n                        bool inSeg = (p.side == 0 ? (j < split) : (j >= split));\n                        if (!inSeg) continue;\n                        int e = idx_horizontal_edge(row, j);\n                        w_hat[e] = clampW((long double)w_hat[e] + delta);\n                    }\n                } else {\n                    for (int j = 0; j < nEdges; j++) {\n                        int e = idx_horizontal_edge(row, j);\n                        w_hat[e] = clampW((long double)w_hat[e] + delta);\n                    }\n                }\n            } else {\n                int col = p.idx;\n                int nEdges = H - 1;\n                if (p.two) {\n                    int split = p.split;\n                    for (int i = 0; i < nEdges; i++) {\n                        bool inSeg = (p.side == 0 ? (i < split) : (i >= split)); // top/bottom\n                        if (!inSeg) continue;\n                        int e = idx_vertical_edge(i, col);\n                        w_hat[e] = clampW((long double)w_hat[e] + delta);\n                    }\n                } else {\n                    for (int i = 0; i < nEdges; i++) {\n                        int e = idx_vertical_edge(i, col);\n                        w_hat[e] = clampW((long double)w_hat[e] + delta);\n                    }\n                }\n            }\n        }\n\n        // === Residual edge-level update (helps with per-edge noise \u03b4) ===\n        long double gammaEdge = (k < 200 ? 0.06L : 0.04L);\n        long double dEdge = gammaEdge * eta * err / (long double)m;\n        if (fabsl(dEdge) > 1e-18L) {\n            for (int e : chosen.usedEdges) {\n                w_hat[e] = clampW((long double)w_hat[e] + dEdge);\n            }\n        }\n\n        // === Projection (slightly weaker than before) ===\n        double alphaProj = (k < 200 ? 0.06 : (k < 600 ? 0.052 : 0.045));\n\n        for (int i : touchRow) {\n            if (rowFit[i].two) {\n                int split = rowFit[i].split;\n                double L = rowFit[i].meanL;\n                double R = rowFit[i].meanR;\n                for (int j = 0; j < W - 1; j++) {\n                    int e = idx_horizontal_edge(i, j);\n                    double target = (j < split ? L : R);\n                    w_hat[e] = clampW((long double)w_hat[e] * (1.0L - alphaProj) + (long double)target * alphaProj);\n                }\n            } else {\n                double T = rowFit[i].mean1;\n                for (int j = 0; j < W - 1; j++) {\n                    int e = idx_horizontal_edge(i, j);\n                    w_hat[e] = clampW((long double)w_hat[e] * (1.0L - alphaProj) + (long double)T * alphaProj);\n                }\n            }\n        }\n        for (int j : touchCol) {\n            if (colFit[j].two) {\n                int split = colFit[j].split;\n                double Top = colFit[j].meanL;\n                double Bot = colFit[j].meanR;\n                for (int i = 0; i < H - 1; i++) {\n                    int e = idx_vertical_edge(i, j);\n                    double target = (i < split ? Top : Bot);\n                    w_hat[e] = clampW((long double)w_hat[e] * (1.0L - alphaProj) + (long double)target * alphaProj);\n                }\n            } else {\n                double T = colFit[j].mean1;\n                for (int i = 0; i < H - 1; i++) {\n                    int e = idx_vertical_edge(i, j);\n                    w_hat[e] = clampW((long double)w_hat[e] * (1.0L - alphaProj) + (long double)T * alphaProj);\n                }\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 ALPHA = 8; // A..H\n\n// --------- Hash for greedy helper maps (not hot) ----------\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}\nstruct SlowHash {\n    size_t operator()(uint64_t x) const {\n        static const uint64_t FIXED_RANDOM =\n            chrono::steady_clock::now().time_since_epoch().count();\n        return (size_t)splitmix64(x + FIXED_RANDOM);\n    }\n};\n\n// --------- Open-addressing hash table for (len<<48)|enc -> id (hot) ----------\nstruct KeyToIdTable {\n    static constexpr uint64_t EMPTY = UINT64_MAX;\n\n    int mask = 0;\n    int cap = 0;\n    vector<uint64_t> keys;\n    vector<int> vals;\n\n    static inline uint64_t h(uint64_t x) {\n        static const uint64_t MAGIC = 11400714819323198485ULL;\n        return x * MAGIC;\n    }\n\n    void init(int expectedSize) {\n        cap = 1;\n        while (cap < expectedSize * 4) cap <<= 1; // load <= 0.25\n        mask = cap - 1;\n        keys.assign(cap, EMPTY);\n        vals.assign(cap, -1);\n    }\n\n    inline void setKey(uint64_t key, int id) {\n        int pos = (int)(h(key) & (uint64_t)mask);\n        while (true) {\n            if (keys[pos] == EMPTY) {\n                keys[pos] = key;\n                vals[pos] = id;\n                return;\n            }\n            if (keys[pos] == key) {\n                vals[pos] = id;\n                return;\n            }\n            pos = (pos + 1) & mask;\n        }\n    }\n\n    inline int find(uint64_t key) const {\n        int pos = (int)(h(key) & (uint64_t)mask);\n        while (true) {\n            uint64_t cur = keys[pos];\n            if (cur == EMPTY) return -1;\n            if (cur == key) return vals[pos];\n            pos = (pos + 1) & mask;\n        }\n    }\n};\n\nstruct Solver {\n    int M;\n\n    vector<string> S;\n    vector<vector<uint8_t>> scodes;\n    vector<int> slen;\n    vector<uint64_t> skey; // composite key already (len<<48)|enc\n\n    // distinct input strings\n    vector<int> mult; // multiplicity per id\n    vector<int> occ;  // occurrence count in current grid\n    long long curC = 0;\n\n    // objective keys\n    bool needLen[13]{};\n    vector<int> neededLens;\n    uint64_t maskLower[13]{};\n    uint64_t keyShift[13]{};\n\n    KeyToIdTable table;\n\n    int bestC = -1;\n    array<array<uint8_t, N>, N> g{};\n    array<array<uint8_t, N>, N> bestG{};\n\n    // greedy overlap maps: prefixCand[ov][prefixEnc] -> list of indices\n    // suffixCand[ov][suffixEnc] -> list of indices\n    vector<unordered_map<uint64_t, vector<int>, SlowHash>> prefixCand, suffixCand;\n\n    mt19937_64 rng;\n\n    Solver() : rng((uint64_t)chrono::steady_clock::now().time_since_epoch().count()) {}\n\n    static inline uint8_t charToCode(char c) { return (uint8_t)(c - 'A'); }\n\n    static inline uint64_t encSeq(const vector<uint8_t>& v) {\n        uint64_t enc = 0;\n        for (uint8_t x : v) enc = (enc << 3) | (uint64_t)x;\n        return enc;\n    }\n\n    static inline uint64_t encSeqRange(const vector<uint8_t>& v, int l, int r) {\n        uint64_t enc = 0;\n        for (int i = l; i < r; i++) enc = (enc << 3) | (uint64_t)v[i];\n        return enc;\n    }\n\n    static inline uint64_t compositeKey(int len, uint64_t enc) {\n        return ((uint64_t)len << 48) | enc;\n    }\n\n    void buildObjective() {\n        memset(needLen, 0, sizeof(needLen));\n        unordered_map<uint64_t, int, SlowHash> idMap;\n        idMap.reserve((size_t)M * 2);\n\n        mult.clear();\n        needLen[0] = false;\n\n        for (int i = 0; i < M; i++) {\n            uint64_t key = skey[i];\n            auto it = idMap.find(key);\n            if (it == idMap.end()) {\n                int id = (int)mult.size();\n                idMap.emplace(key, id);\n                mult.push_back(1);\n                needLen[slen[i]] = true;\n            } else {\n                mult[it->second] += 1;\n                needLen[slen[i]] = true;\n            }\n        }\n\n        neededLens.clear();\n        for (int k = 2; k <= 12; k++) if (needLen[k]) neededLens.push_back(k);\n\n        for (int k = 2; k <= 12; k++) {\n            int bits = 3 * (k - 1); // <= 33\n            maskLower[k] = (1ULL << bits) - 1ULL;\n            keyShift[k] = (uint64_t)k << 48;\n        }\n\n        int K = (int)mult.size();\n        occ.assign(K, 0);\n        curC = 0;\n\n        table.init(K);\n        for (auto &p : idMap) {\n            table.setKey(p.first, p.second);\n        }\n    }\n\n    void buildOverlapMaps() {\n        prefixCand.assign(13, {});\n        suffixCand.assign(13, {});\n        for (int i = 0; i < M; i++) {\n            int L = slen[i];\n            for (int ov = 2; ov <= L - 1; ov++) {\n                uint64_t pref = encSeqRange(scodes[i], 0, ov);\n                uint64_t suf = encSeqRange(scodes[i], L - ov, L);\n                prefixCand[ov][pref].push_back(i);\n                suffixCand[ov][suf].push_back(i);\n            }\n        }\n    }\n\n    // Update one line (row or column) by delta (+1/-1 for adding/removing that line's occurrences)\n    inline void updateLine(bool isRow, int idx, int delta) {\n        uint8_t ext[2 * N];\n        if (isRow) {\n            for (int t = 0; t < 2 * N; t++) ext[t] = g[idx][t % N];\n        } else {\n            for (int t = 0; t < 2 * N; t++) ext[t] = g[t % N][idx];\n        }\n\n        for (int k : neededLens) {\n            uint64_t enc = 0;\n            for (int t = 0; t < k; t++) enc = (enc << 3) | (uint64_t)ext[t];\n\n            const uint64_t shift = keyShift[k];\n\n            for (int start = 0; start < N; start++) {\n                uint64_t key = shift | enc;\n                int id = table.find(key);\n                if (id != -1) {\n                    int before = occ[id];\n                    if (delta == +1) {\n                        occ[id] = before + 1;\n                        if (before == 0) curC += mult[id];\n                    } else {\n                        occ[id] = before - 1;\n                        if (before == 1) curC -= mult[id];\n                    }\n                }\n                if (start == N - 1) break;\n                enc = ((enc & maskLower[k]) << 3) | (uint64_t)ext[start + k];\n            }\n        }\n    }\n\n    void computeInitialCounts() {\n        fill(occ.begin(), occ.end(), 0);\n        curC = 0;\n        for (int i = 0; i < N; i++) updateLine(true, i, +1);\n        for (int j = 0; j < N; j++) updateLine(false, j, +1);\n    }\n\n    inline void setCell(int i, int j, uint8_t nv) {\n        uint8_t old = g[i][j];\n        if (old == nv) return;\n        updateLine(true, i, -1);\n        updateLine(false, j, -1);\n        g[i][j] = nv;\n        updateLine(true, i, +1);\n        updateLine(false, j, +1);\n    }\n\n    inline void swapInRow(int i, int j1, int j2) {\n        if (j1 == j2) return;\n        if (g[i][j1] == g[i][j2]) return;\n\n        updateLine(true, i, -1);\n        updateLine(false, j1, -1);\n        updateLine(false, j2, -1);\n\n        std::swap(g[i][j1], g[i][j2]);\n\n        updateLine(true, i, +1);\n        updateLine(false, j1, +1);\n        updateLine(false, j2, +1);\n    }\n\n    inline void swapInCol(int j, int i1, int i2) {\n        if (i1 == i2) return;\n        if (g[i1][j] == g[i2][j]) return;\n\n        updateLine(false, j, -1);\n        updateLine(true, i1, -1);\n        updateLine(true, i2, -1);\n\n        std::swap(g[i1][j], g[i2][j]);\n\n        updateLine(false, j, +1);\n        updateLine(true, i1, +1);\n        updateLine(true, i2, +1);\n    }\n\n    // Greedy build N independent cyclic sequences:\n    // if horizontal=true => fill each row; else fill each column.\n    void buildInitialGridGreedy(bool horizontal) {\n        vector<unordered_set<uint64_t, SlowHash>> coveredKeys(13);\n        vector<char> coveredInput(M, 0);\n\n        for (int k : neededLens) {\n            coveredKeys[k].reserve(1 << 14);\n        }\n\n        auto addSeqToCovered = [&](const array<uint8_t, N>& seq) {\n            for (int k : neededLens) {\n                uint64_t enc = 0;\n                for (int t = 0; t < k; t++) enc = (enc << 3) | (uint64_t)seq[t];\n                coveredKeys[k].insert(keyShift[k] | enc);\n                for (int start = 1; start < N; start++) {\n                    enc = ((enc & maskLower[k]) << 3) | (uint64_t)seq[(start + k - 1) % N];\n                    // careful: rolling above uses last symbol index (start+k-1).\n                    // Alternatively compute with (start+k)%N:\n                    // enc = ((enc & maskLower[k])<<3) | seq[(start+k)%N]\n                    // We'll correct by recomputing robustly:\n                    // To avoid mistakes, do robust roll:\n                }\n            }\n\n            // Robust insertion (correct rolling), overwriting above with clean method:\n            // (We keep it simple; N small.)\n            for (int k : neededLens) {\n                coveredKeys[k].clear();\n                uint64_t enc0 = 0;\n                for (int t = 0; t < k; t++) enc0 = (enc0 << 3) | (uint64_t)seq[t];\n                uint64_t cur = enc0;\n                coveredKeys[k].insert(keyShift[k] | cur);\n                for (int start = 1; start < N; start++) {\n                    cur = ((cur & maskLower[k]) << 3) | (uint64_t)seq[(start + k - 1) % N];\n                    coveredKeys[k].insert(keyShift[k] | cur);\n                }\n            }\n        };\n\n        auto updateCoveredInput = [&]() {\n            for (int i = 0; i < M; i++) {\n                if (coveredInput[i]) continue;\n                int k = slen[i];\n                if (!needLen[k]) continue;\n                if (!coveredKeys[k].empty() && coveredKeys[k].find(skey[i]) != coveredKeys[k].end()) {\n                    coveredInput[i] = 1;\n                }\n            }\n        };\n\n        // We need coveredKeys accumulating across multiple lines, so we cannot clear inside addSeqToCovered.\n        // Fix: implement a correct addSeqToCovered that accumulates.\n        // Let's re-implement properly:\n        coveredKeys.assign(13, {});\n        for (int k : neededLens) coveredKeys[k].reserve(1 << 14);\n\n        auto addSeqToCoveredAccum = [&](const array<uint8_t, N>& seq) {\n            for (int k : neededLens) {\n                uint64_t enc = 0;\n                for (int t = 0; t < k; t++) enc = (enc << 3) | (uint64_t)seq[t];\n                coveredKeys[k].insert(keyShift[k] | enc);\n                for (int start = 1; start < N; start++) {\n                    enc = ((enc & maskLower[k]) << 3) | (uint64_t)seq[(start + k - 1) % N];\n                    coveredKeys[k].insert(keyShift[k] | enc);\n                }\n            }\n        };\n\n        int minOverlap = 2;\n        for (int fixed = 0; fixed < N; fixed++) {\n            int bestL = -1;\n            vector<int> cand;\n            for (int idx = 0; idx < M; idx++) {\n                if (coveredInput[idx]) continue;\n                if (slen[idx] > bestL) {\n                    bestL = slen[idx];\n                    cand.clear();\n                    cand.push_back(idx);\n                } else if (slen[idx] == bestL) {\n                    cand.push_back(idx);\n                }\n            }\n\n            array<uint8_t, N> seqArr{};\n            if (bestL < 0) {\n                for (int t = 0; t < N; t++) seqArr[t] = (uint8_t)(rng() % ALPHA);\n            } else {\n                int seed = cand[(int)(rng() % cand.size())];\n                vector<uint8_t> cur = scodes[seed];\n\n                while ((int)cur.size() < N) {\n                    int curLen = (int)cur.size();\n                    int maxOv = min(curLen - 1, 11);\n\n                    int bestRightLen = curLen, bestRightIdx = -1, bestRightOv = -1;\n                    for (int ov = maxOv; ov >= minOverlap; ov--) {\n                        uint64_t sufEnc = 0;\n                        for (int t = curLen - ov; t < curLen; t++) sufEnc = (sufEnc << 3) | (uint64_t)cur[t];\n                        auto it = prefixCand[ov].find(sufEnc);\n                        if (it == prefixCand[ov].end()) continue;\n                        for (int candIdx : it->second) {\n                            if (slen[candIdx] <= ov) continue;\n                            int newLen = curLen + slen[candIdx] - ov;\n                            if (newLen <= N && newLen > bestRightLen) {\n                                bestRightLen = newLen;\n                                bestRightIdx = candIdx;\n                                bestRightOv = ov;\n                            }\n                        }\n                    }\n\n                    int bestLeftLen = curLen, bestLeftIdx = -1, bestLeftOv = -1;\n                    for (int ov = maxOv; ov >= minOverlap; ov--) {\n                        uint64_t prefEnc = 0;\n                        for (int t = 0; t < ov; t++) prefEnc = (prefEnc << 3) | (uint64_t)cur[t];\n                        auto it = suffixCand[ov].find(prefEnc);\n                        if (it == suffixCand[ov].end()) continue;\n                        for (int candIdx : it->second) {\n                            if (slen[candIdx] <= ov) continue;\n                            int newLen = curLen + slen[candIdx] - ov;\n                            if (newLen <= N && newLen > bestLeftLen) {\n                                bestLeftLen = newLen;\n                                bestLeftIdx = candIdx;\n                                bestLeftOv = ov;\n                            }\n                        }\n                    }\n\n                    int finalLen = max(bestRightLen, bestLeftLen);\n                    if (finalLen == curLen) break;\n\n                    bool takeRight;\n                    if (bestRightLen > bestLeftLen) takeRight = true;\n                    else if (bestLeftLen > bestRightLen) takeRight = false;\n                    else takeRight = (rng() & 1ULL);\n\n                    if (takeRight) {\n                        auto &cv = scodes[bestRightIdx];\n                        int ov = bestRightOv;\n                        for (int t = ov; t < (int)cv.size() && (int)cur.size() < N; t++) cur.push_back(cv[t]);\n                    } else {\n                        auto &cv = scodes[bestLeftIdx];\n                        int ov = bestLeftOv;\n                        vector<uint8_t> ncur;\n                        ncur.reserve(N);\n                        for (int t = 0; t < (int)cv.size() - ov && (int)ncur.size() < N; t++) ncur.push_back(cv[t]);\n                        for (uint8_t x : cur) {\n                            if ((int)ncur.size() >= N) break;\n                            ncur.push_back(x);\n                        }\n                        cur.swap(ncur);\n                    }\n                }\n\n                while ((int)cur.size() < N) cur.push_back((uint8_t)(rng() % ALPHA));\n                for (int t = 0; t < N; t++) seqArr[t] = cur[t];\n            }\n\n            if (horizontal) {\n                for (int j = 0; j < N; j++) g[fixed][j] = seqArr[j];\n            } else {\n                for (int i = 0; i < N; i++) g[i][fixed] = seqArr[i];\n            }\n\n            addSeqToCoveredAccum(seqArr);\n            updateCoveredInput();\n        }\n    }\n\n    void solveSA(chrono::steady_clock::time_point deadline) {\n        computeInitialCounts();\n        if (curC > bestC) { bestC = (int)curC; bestG = g; }\n\n        // time slice -> steps\n        auto now = chrono::steady_clock::now();\n        int remainingMs = (int)chrono::duration_cast<chrono::milliseconds>(deadline - now).count();\n        if (remainingMs < 100) return;\n        int stepsMax = min(260000, max(90000, remainingMs * 80));\n\n        const long double Tstart = 4.2L;\n        const long double Tmin = 0.10L;\n        long double alpha = pow((double)(Tmin / Tstart), 1.0L / (long double)stepsMax);\n        long double T = Tstart;\n\n        const int pRow = 15; // %\n        const int pCol = 15; // %\n        const int pCell = 70;\n\n        const int checkEvery = 512;\n\n        for (int it = 0; it < stepsMax; it++) {\n            if ((it % checkEvery) == 0 && chrono::steady_clock::now() >= deadline) break;\n            T = max(Tmin, T * alpha);\n\n            int before = (int)curC;\n\n            int r = (int)(rng() % 100);\n            bool accepted = false;\n\n            if (r < pRow) {\n                int i = (int)(rng() % N);\n                int j1 = (int)(rng() % N);\n                int j2 = (int)(rng() % N);\n                if (j1 != j2) {\n                    swapInRow(i, j1, j2);\n                    int after = (int)curC;\n                    if (after >= before) accepted = true;\n                    else {\n                        long double x = (long double)(after - before) / T; // negative\n                        if (x < -12) accepted = false;\n                        else {\n                            long double prob = expl(x);\n                            long double u = (long double)rng() / (long double)UINT32_MAX;\n                            accepted = (u < prob);\n                        }\n                    }\n                    if (!accepted) swapInRow(i, j1, j2);\n                }\n            } else if (r < pRow + pCol) {\n                int j = (int)(rng() % N);\n                int i1 = (int)(rng() % N);\n                int i2 = (int)(rng() % N);\n                if (i1 != i2) {\n                    swapInCol(j, i1, i2);\n                    int after = (int)curC;\n                    if (after >= before) accepted = true;\n                    else {\n                        long double x = (long double)(after - before) / T;\n                        if (x < -12) accepted = false;\n                        else {\n                            long double prob = expl(x);\n                            long double u = (long double)rng() / (long double)UINT32_MAX;\n                            accepted = (u < prob);\n                        }\n                    }\n                    if (!accepted) swapInCol(j, i1, i2);\n                }\n            } else {\n                int i = (int)(rng() % N);\n                int j = (int)(rng() % N);\n                uint8_t old = g[i][j];\n                uint8_t nv = old;\n                while (nv == old) nv = (uint8_t)(rng() % ALPHA);\n\n                setCell(i, j, nv);\n                int after = (int)curC;\n                if (after >= before) accepted = true;\n                else {\n                    long double x = (long double)(after - before) / T;\n                    if (x < -12) accepted = false;\n                    else {\n                        long double prob = expl(x);\n                        long double u = (long double)rng() / (long double)UINT32_MAX;\n                        accepted = (u < prob);\n                    }\n                }\n                if (!accepted) setCell(i, j, old);\n            }\n\n            if (accepted && (int)curC > bestC) {\n                bestC = (int)curC;\n                bestG = g;\n                if (bestC >= M) return;\n            }\n        }\n    }\n\n    void run() {\n        ios::sync_with_stdio(false);\n        cin.tie(nullptr);\n\n        int Nread;\n        cin >> Nread >> M; // FIX: read into Nread, do NOT read into const N.\n        // N is fixed to 20; ignore Nread safely.\n\n        S.resize(M);\n        for (int i = 0; i < M; i++) cin >> S[i];\n\n        scodes.assign(M, {});\n        slen.assign(M, 0);\n        skey.assign(M, 0);\n\n        for (int i = 0; i < M; i++) {\n            slen[i] = (int)S[i].size();\n            scodes[i].resize(slen[i]);\n            for (int t = 0; t < slen[i]; t++) scodes[i][t] = charToCode(S[i][t]);\n            skey[i] = compositeKey(slen[i], encSeq(scodes[i]));\n        }\n\n        buildObjective();\n        buildOverlapMaps();\n\n        auto start = chrono::steady_clock::now();\n        auto deadline = start + chrono::milliseconds(2850);\n\n        bestC = -1;\n\n        int baseRuns = 6;\n        for (int b = 0; b < baseRuns; b++) {\n            if (chrono::steady_clock::now() >= deadline) break;\n\n            bool horizontal = (b % 2 == 0);\n            buildInitialGridGreedy(horizontal);\n\n            // cheap perturbation (recompute counts inside solveSA)\n            int perturb = 10 + 2 * b;\n            for (int t = 0; t < perturb; t++) {\n                int i = (int)(rng() % N);\n                int j = (int)(rng() % N);\n                g[i][j] = (uint8_t)(rng() % ALPHA);\n            }\n\n            solveSA(deadline);\n        }\n\n        for (int i = 0; i < N; i++) {\n            string row;\n            row.reserve(N);\n            for (int j = 0; j < N; j++) row.push_back(char('A' + bestG[i][j]));\n            cout << row << '\\n';\n        }\n    }\n};\n\nint main() {\n    Solver s;\n    s.run();\n    return 0;\n}","ahc005":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct DSU {\n    int n;\n    vector<int> p, r;\n    DSU(int n=0): n(n), p(n), r(n,0) { iota(p.begin(), p.end(), 0); }\n    int find(int x){ return p[x]==x? x : p[x]=find(p[x]); }\n    bool unite(int a,int b){\n        a=find(a); b=find(b);\n        if(a==b) return false;\n        if(r[a]<r[b]) swap(a,b);\n        p[b]=a;\n        if(r[a]==r[b]) r[a]++;\n        return true;\n    }\n};\n\nstatic inline char dirChar(const pair<int,int>& a, const pair<int,int>& b){\n    int ar=a.first, ac=a.second, br=b.first, bc=b.second;\n    if(br==ar-1 && bc==ac) return 'U';\n    if(br==ar+1 && bc==ac) return 'D';\n    if(br==ar && bc==ac-1) return 'L';\n    return 'R';\n}\n\nstruct TourResult{\n    bool ok=false;\n    long long t = (1LL<<62);\n    vector<int> seq; // vertices, seq[0]==seq.back()==start\n};\n\nint main(){\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, si, sj;\n    cin >> N >> si >> sj;\n    vector<string> g(N);\n    for(int i=0;i<N;i++) cin >> g[i];\n\n    auto inside = [&](int r,int c){ return 0<=r && r<N && 0<=c && c<N; };\n\n    // BFS from (si,sj) to get connected component of road cells\n    vector<vector<int>> idx(N, vector<int>(N, -1));\n    vector<pair<int,int>> cells;\n    vector<int> wts;\n    queue<pair<int,int>> q;\n    vector<vector<char>> vis(N, vector<char>(N,0));\n    q.push({si,sj});\n    vis[si][sj]=1;\n\n    int dr[4]={-1,1,0,0};\n    int dc[4]={0,0,-1,1};\n\n    while(!q.empty()){\n        auto [r,c]=q.front(); q.pop();\n        int id=(int)cells.size();\n        idx[r][c]=id;\n        cells.push_back({r,c});\n        wts.push_back(g[r][c]-'0');\n        for(int k=0;k<4;k++){\n            int nr=r+dr[k], nc=c+dc[k];\n            if(!inside(nr,nc)) continue;\n            if(vis[nr][nc]) continue;\n            if(g[nr][nc]=='#') continue;\n            vis[nr][nc]=1;\n            q.push({nr,nc});\n        }\n    }\n\n    int m = (int)cells.size();\n    if(m<=1){\n        cout << \"\\n\";\n        return 0;\n    }\n    int sidx = idx[si][sj];\n\n    // Component adjacency with unique undirected edges via right/down\n    vector<vector<pair<int,int>>> adj(m); // (to, edgeId)\n    vector<int> eu, ev;\n    eu.reserve(2*m); ev.reserve(2*m);\n\n    auto addAdjEdge = [&](int a,int b){\n        int eid=(int)eu.size();\n        eu.push_back(a);\n        ev.push_back(b);\n        adj[a].push_back({b,eid});\n        adj[b].push_back({a,eid});\n    };\n\n    for(int u=0;u<m;u++){\n        auto [r,c]=cells[u];\n        if(c+1<N && idx[r][c+1]!=-1) addAdjEdge(u, idx[r][c+1]);\n        if(r+1<N && idx[r+1][c]!=-1) addAdjEdge(u, idx[r+1][c]);\n    }\n\n    int E = (int)eu.size();\n    vector<int> edgeW(E);\n    for(int eid=0;eid<E;eid++){\n        int a=eu[eid], b=ev[eid];\n        edgeW[eid]=wts[a]+wts[b]; // metric used for MST/pairing stage\n    }\n\n    // Pre-group edges by cost for faster MST\n    vector<int> uniq = edgeW;\n    sort(uniq.begin(), uniq.end());\n    uniq.erase(unique(uniq.begin(), uniq.end()), uniq.end());\n    unordered_map<int, vector<int>> byCost;\n    byCost.reserve(uniq.size()*2+5);\n    for(int eid=0;eid<E;eid++) byCost[edgeW[eid]].push_back(eid);\n\n    // Deterministic RNG to reduce score variance\n    uint64_t seed = 123456789ULL;\n    auto splitmix64 = [&](){\n        seed += 0x9e3779b97f4a7c15ULL;\n        uint64_t z = seed;\n        z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9ULL;\n        z = (z ^ (z >> 27)) * 0x94d049bb133111ebULL;\n        return z ^ (z >> 31);\n    };\n    auto rnd = [&](uint64_t mod){ return (int)(splitmix64()%mod); };\n\n    auto buildMST = [&](bool randomTies)->pair<vector<int>, vector<int>>{\n        DSU dsu(m);\n        vector<int> mstDeg(m,0), mstEdges;\n        mstEdges.reserve(m-1);\n\n        for(int cst: uniq){\n            auto vec = byCost[cst];\n            if(randomTies){\n                // Fisher-Yates shuffle using deterministic rng\n                for(int i=(int)vec.size()-1;i>0;i--){\n                    int j = rnd(i+1);\n                    swap(vec[i], vec[j]);\n                }\n            }\n            for(int eid: vec){\n                int a=eu[eid], b=ev[eid];\n                if(dsu.unite(a,b)){\n                    mstEdges.push_back(eid);\n                    mstDeg[a]++; mstDeg[b]++;\n                    if((int)mstEdges.size()==m-1) break;\n                }\n            }\n            if((int)mstEdges.size()==m-1) break;\n        }\n        if((int)mstEdges.size()!=m-1) return {{},{}}; // should not happen\n        return {mstEdges, mstDeg};\n    };\n\n    auto doubledTreeTour = [&](const vector<int>& mstEdges)->TourResult{\n        // Build tree adjacency\n        vector<vector<int>> treeAdj(m);\n        for(int eid: mstEdges){\n            int a=eu[eid], b=ev[eid];\n            treeAdj[a].push_back(b);\n            treeAdj[b].push_back(a);\n        }\n        // Compute time for doubled-tree DFS walk:\n        long long t=0;\n        for(int u=0;u<m;u++) t += 1LL*wts[u]*(long long)treeAdj[u].size();\n\n        // Build a vertex sequence corresponding to a DFS that traverses each tree edge twice\n        vector<int> seq;\n        seq.reserve(2*(m-1)+1);\n        struct Frame{int u,p, it;};\n        vector<Frame> st;\n        st.reserve(m);\n        st.push_back({sidx,-1,0});\n        seq.push_back(sidx);\n\n        while(!st.empty()){\n            auto &top=st.back();\n            int u=top.u;\n            if(top.it < (int)treeAdj[u].size()){\n                int v = treeAdj[u][top.it++];\n                if(v==top.p) continue;\n                seq.push_back(v);\n                st.push_back({v,u,0});\n            }else{\n                int p=top.p;\n                st.pop_back();\n                if(!st.empty()){\n                    seq.push_back(st.back().u);\n                }else{\n                    // finished at root\n                }\n            }\n        }\n\n        TourResult res;\n        res.ok = (!seq.empty() && seq.front()==sidx && seq.back()==sidx);\n        res.t = t;\n        res.seq = std::move(seq);\n        return res;\n    };\n\n    auto buildEulerFromCnt = [&](vector<int> cnt)->TourResult{\n        // parity check\n        vector<int> parity(m,0);\n        for(int eid=0;eid<E;eid++){\n            if(cnt[eid]&1){\n                parity[eu[eid]]^=1;\n                parity[ev[eid]]^=1;\n            }\n        }\n        for(int u=0;u<m;u++) if(parity[u]) return {};\n\n        vector<vector<int>> inc(m);\n        inc.assign(m, {});\n        for(int eid=0;eid<E;eid++){\n            if(cnt[eid]==0) continue;\n            inc[eu[eid]].push_back(eid);\n            inc[ev[eid]].push_back(eid);\n        }\n\n        vector<int> ptr(m,0), stV, circuit;\n        stV.reserve(1);\n        circuit.reserve(1);\n        stV.push_back(sidx);\n\n        auto otherEnd = [&](int eid, int u)->int{\n            return (u==eu[eid]? ev[eid] : eu[eid]);\n        };\n\n        while(!stV.empty()){\n            int u=stV.back();\n            auto &vec = inc[u];\n            while(ptr[u]<(int)vec.size() && cnt[vec[ptr[u]]]==0) ptr[u]++;\n            if(ptr[u]==(int)vec.size()){\n                circuit.push_back(u);\n                stV.pop_back();\n            }else{\n                int eid = vec[ptr[u]];\n                cnt[eid]--;\n                int v = otherEnd(eid,u);\n                stV.push_back(v);\n            }\n        }\n\n        reverse(circuit.begin(), circuit.end());\n        if(circuit.size()<=1) return {};\n        if(circuit.front()!=sidx || circuit.back()!=sidx) return {};\n\n        // Ensure all vertices in component visited at least once => v=r\n        vector<char> seen(m,0);\n        for(int v: circuit) seen[v]=1;\n        for(int u=0;u<m;u++) if(!seen[u]) return {};\n\n        long long t=0;\n        for(int i=1;i<(int)circuit.size();i++) t += wts[circuit[i]];\n\n        return {true, t, std::move(circuit)};\n    };\n\n    // Multi-source Dijkstra with metric cost(u->v) = w[u]+w[v]\n    auto multiSourceDijkstra_metric = [&](const vector<int>& sources,\n                                           vector<long long>& dist,\n                                           vector<int>& srcLabel,\n                                           vector<int>& parent,\n                                           vector<int>& parentEid){\n        const long long INF = (1LL<<60);\n        dist.assign(m, INF);\n        srcLabel.assign(m, -1);\n        parent.assign(m, -1);\n        parentEid.assign(m, -1);\n\n        using P = pair<long long,int>;\n        priority_queue<P, vector<P>, greater<P>> pq;\n\n        for(int s: sources){\n            dist[s]=0;\n            srcLabel[s]=s;\n            parent[s]=-1;\n            parentEid[s]=-1;\n            pq.push({0,s});\n        }\n\n        while(!pq.empty()){\n            auto [d,u]=pq.top(); pq.pop();\n            if(d!=dist[u]) continue;\n            for(auto [v,eid]: adj[u]){\n                long long nd = d + (long long)wts[u] + (long long)wts[v]; // w[u]+w[v]\n                if(nd < dist[v]){\n                    dist[v]=nd;\n                    srcLabel[v]=srcLabel[u];\n                    parent[v]=u;\n                    parentEid[v]=eid;\n                    pq.push({nd,v});\n                }\n            }\n        }\n    };\n\n    auto augmentedEulerTour = [&](const vector<int>& mstEdges, const vector<int>& mstDeg)->TourResult{\n        vector<int> cnt(E,0);\n        for(int eid: mstEdges) cnt[eid]=1;\n\n        vector<int> odd;\n        for(int u=0;u<m;u++) if(mstDeg[u]&1) odd.push_back(u);\n        if(odd.empty()) return {};\n\n        // Phase 1: multi-source Dijkstra + greedy candidate pairing\n        vector<long long> dist;\n        vector<int> srcLabel, parent, parentEid;\n        multiSourceDijkstra_metric(odd, dist, srcLabel, parent, parentEid);\n\n        struct Cand{\n            long long cost;\n            int sa,sb;\n            int x,y; // edge endpoints (vertices)\n            int eid;\n            uint64_t key;\n        };\n        vector<Cand> cands;\n        cands.reserve(E);\n        for(int eid=0;eid<E;eid++){\n            int a0=eu[eid], b0=ev[eid];\n            int sa=srcLabel[a0], sb=srcLabel[b0];\n            if(sa==-1 || sb==-1 || sa==sb) continue;\n            long long cost = dist[a0] + dist[b0] + (long long)wts[a0] + (long long)wts[b0];\n            cands.push_back({cost, sa, sb, a0, b0, eid, splitmix64()});\n        }\n        sort(cands.begin(), cands.end(), [&](const Cand& A, const Cand& B){\n            if(A.cost!=B.cost) return A.cost<B.cost;\n            return A.key<B.key;\n        });\n\n        vector<char> usedSource(m,0);\n\n        auto addPathToSource = [&](int node, int targetSource){\n            int cur=node;\n            while(cur!=targetSource){\n                int pe = parentEid[cur];\n                int pr = parent[cur];\n                if(pe<0 || pr<0) break;\n                cnt[pe]++;\n                cur=pr;\n            }\n        };\n\n        for(auto &cd: cands){\n            if(usedSource[cd.sa] || usedSource[cd.sb]) continue;\n            addPathToSource(cd.x, cd.sa);\n            cnt[cd.eid]++;\n            addPathToSource(cd.y, cd.sb);\n            usedSource[cd.sa]=usedSource[cd.sb]=1;\n        }\n\n        // Phase 2: remaining odds paired by nearest-odd Dijkstra (true move cost w[dest])\n        auto getOddFromCnt = [&](){\n            vector<int> o;\n            vector<char> inOdd(m,0);\n            for(int eid=0;eid<E;eid++){\n                if(cnt[eid]&1){\n                    inOdd[eu[eid]]^=1;\n                    inOdd[ev[eid]]^=1;\n                }\n            }\n            for(int u=0;u<m;u++) if(inOdd[u]) o.push_back(u);\n            return o;\n        };\n\n        vector<int> remaining = getOddFromCnt();\n        // Greedy pairing using early stop (pair count typically small)\n        while(!remaining.empty()){\n            // pick one\n            int a = remaining.back();\n            remaining.pop_back();\n\n            // if a already even due to parity updates, recompute\n            // (rare, but keep robust)\n            auto odd2 = getOddFromCnt();\n            vector<char> inOdd(m,0);\n            for(int u: odd2) inOdd[u]=1;\n            if(!inOdd[a]) continue;\n\n            // Dijkstra from a; stop when reaching any other odd\n            const long long INF = (1LL<<60);\n            vector<long long> d(m, INF);\n            vector<int> par(m,-1), parE(m,-1);\n            using P = pair<long long,int>;\n            priority_queue<P, vector<P>, greater<P>> pq;\n            d[a]=0;\n            pq.push({0,a});\n\n            int foundB=-1;\n            while(!pq.empty()){\n                auto [du,u]=pq.top(); pq.pop();\n                if(du!=d[u]) continue;\n                if(u!=a && inOdd[u]){\n                    foundB=u;\n                    break;\n                }\n                for(auto [v,eid]: adj[u]){\n                    long long nd = du + (long long)wts[v]; // move cost is w[dest]\n                    if(nd < d[v]){\n                        d[v]=nd;\n                        par[v]=u;\n                        parE[v]=eid;\n                        pq.push({nd,v});\n                    }\n                }\n            }\n            if(foundB==-1) break; // fail -> will be rejected by Euler builder\n\n            // Add path edges by following parents foundB -> a\n            int cur=foundB;\n            while(cur!=a){\n                int pe = parE[cur];\n                if(pe<0) break;\n                cnt[pe]++;\n                cur=par[cur];\n            }\n        }\n\n        return buildEulerFromCnt(cnt);\n    };\n\n    // Search over multiple MSTs, keep best by t\n    TourResult best;\n    bool hasBest=false;\n    int attempts = 18;\n\n    for(int it=0; it<attempts; it++){\n        bool randomTies = (it>0);\n        auto [mstE, mstDeg] = buildMST(randomTies);\n        if(mstE.empty()) continue;\n\n        // Augmented Euler\n        TourResult aug = augmentedEulerTour(mstE, mstDeg);\n        if(aug.ok && (!hasBest || aug.t < best.t)){\n            best = std::move(aug);\n            hasBest=true;\n        }\n\n        // Baseline doubled tree\n        TourResult base = doubledTreeTour(mstE);\n        if(base.ok){\n            // ensure all vertices visited at least once (v=r)\n            vector<char> seen(m,0);\n            for(int v: base.seq) seen[v]=1;\n            bool okAll=true;\n            for(int u=0;u<m;u++) if(!seen[u]) { okAll=false; break; }\n            if(okAll && (!hasBest || base.t < best.t)){\n                best = std::move(base);\n                hasBest=true;\n            }\n        }\n    }\n\n    if(!hasBest){\n        auto [mstE, mstDeg] = buildMST(false);\n        best = doubledTreeTour(mstE);\n    }\n\n    // ----- Controlled shortcutting post-process -----\n    // Goal: reduce t while keeping v=r. We protect vertices with occ==1.\n    if(best.ok && (int)best.seq.size() >= 3){\n        vector<int>& seq = best.seq;\n\n        auto computeT = [&]()->long long{\n            long long t=0;\n            for(int i=1;i<(int)seq.size();i++) t += wts[seq[i]];\n            return t;\n        };\n\n        long long curT = computeT();\n\n        vector<int> occ(m,0);\n        for(int v: seq) occ[v]++;\n\n        auto dijkstraPathDirected = [&](int A, int B, int maxPathLen)->vector<int>{\n            if(A==B) return {A};\n            const long long INF = (1LL<<60);\n            vector<long long> dist(m, INF);\n            vector<int> par(m,-1);\n            using P = pair<long long,int>;\n            priority_queue<P, vector<P>, greater<P>> pq;\n            dist[A]=0;\n            pq.push({0,A});\n            while(!pq.empty()){\n                auto [d,u]=pq.top(); pq.pop();\n                if(d!=dist[u]) continue;\n                if(u==B) break;\n                for(auto [v,eid]: adj[u]){\n                    (void)eid;\n                    long long nd = d + (long long)wts[v]; // entering v\n                    if(nd < dist[v]){\n                        dist[v]=nd;\n                        par[v]=u;\n                        pq.push({nd,v});\n                    }\n                }\n            }\n            if(par[B]==-1) return {};\n            vector<int> path;\n            int cur=B;\n            path.push_back(cur);\n            while(cur!=A){\n                cur=par[cur];\n                if(cur==-1) return {};\n                path.push_back(cur);\n                if((int)path.size()>maxPathLen) return {};\n            }\n            reverse(path.begin(), path.end());\n            if(path.front()!=A || path.back()!=B) return {};\n            return path;\n        };\n\n        int L = (int)seq.size();\n        int passes = 3;\n        int maxSegmentLen = min(90, L-2);\n        int maxPathLen = 360;\n        int maxAccepted = 120;\n        int accepted = 0;\n\n        for(int pass=0; pass<passes && accepted<maxAccepted; pass++){\n            bool improved = false;\n\n            // Collect heavy internal positions (w>=8) to bias selection\n            vector<int> heavyPos;\n            for(int i=1;i<L-1;i++){\n                if(wts[seq[i]]>=8) heavyPos.push_back(i);\n            }\n            if(heavyPos.empty()) {\n                // still allow, but with less bias\n                for(int i=1;i<L-1;i++) heavyPos.push_back(i);\n            }\n\n            int attempts = min(900, 120 + L/3);\n\n            for(int it=0; it<attempts && accepted<maxAccepted; it++){\n                if((int)seq.size() < 5) break;\n                L = (int)seq.size();\n\n                int midIndex = heavyPos[rnd(heavyPos.size())];\n                // choose l < midIndex < r and within segment length bounds\n                int l = max(0, midIndex - 1 - rnd(20));\n                int r = min(L-1, midIndex + 1 + rnd(20));\n                if(r <= l+1) continue;\n                if(r-l > maxSegmentLen) continue;\n\n                int A = seq[l], B = seq[r];\n                if(A==B) continue;\n\n                // Path A->B\n                vector<int> path = dijkstraPathDirected(A, B, maxPathLen);\n                if(path.empty() || (int)path.size() < 2) continue;\n\n                // Compute oldSum and newSum (time contribution)\n                long long oldSum=0;\n                bool hasHeavyInside=false;\n                for(int k=l+1;k<=r;k++){\n                    oldSum += wts[seq[k]];\n                    if(wts[seq[k]]>=8) hasHeavyInside=true;\n                }\n                if(!hasHeavyInside && (rnd(100)<70)) continue; // enforce heavy bias mostly\n\n                long long newSum=0;\n                for(int i=1;i<(int)path.size();i++) newSum += wts[path[i]];\n\n                if(newSum >= oldSum) continue;\n\n                // Coverage safety: vertices with occ==1 must not disappear\n                // removed positions are seq[l+1..r] inclusive\n                vector<char> inAdded(m,0);\n                for(int i=1;i<(int)path.size();i++) inAdded[path[i]]=1;\n\n                // Check all vertices appearing in removed segment that currently have occ==1\n                bool ok=true;\n                vector<char> seenRemoved(m,0);\n                for(int k=l+1;k<=r;k++){\n                    int u=seq[k];\n                    if(seenRemoved[u]) continue;\n                    seenRemoved[u]=1;\n                    if(occ[u]==1 && !inAdded[u]){\n                        ok=false; break;\n                    }\n                }\n                if(!ok) continue;\n\n                // Apply shortcut: replace seq[l+1..r] with path[1..end]\n                // Update occ counts by recomputing removed/added frequencies (segment sizes are small)\n                vector<int> removedVertices;\n                removedVertices.reserve(r-l);\n                for(int k=l+1;k<=r;k++) removedVertices.push_back(seq[k]);\n\n                vector<int> addedVertices;\n                addedVertices.reserve((int)path.size());\n                for(int i=1;i<(int)path.size();i++) addedVertices.push_back(path[i]);\n\n                // Update occ and time\n                for(int u: removedVertices) occ[u]--;\n                for(int u: addedVertices) occ[u]++;\n\n                // sequence edit\n                seq.erase(seq.begin()+l+1, seq.begin()+r+1);\n                seq.insert(seq.begin()+l+1, path.begin()+1, path.end());\n\n                // Update L and curT\n                curT += (newSum - oldSum);\n                accepted++;\n                improved = true;\n\n                // Verify v=r invariant quickly\n                bool all=true;\n                for(int u=0;u<m;u++) if(occ[u]<=0){ all=false; break; }\n                if(!all){\n                    // revert (rare but safe)\n                    // For simplicity, recompute from scratch acceptance is complex; just stop.\n                    break;\n                }\n\n                if(accepted>=maxAccepted) break;\n            }\n\n            if(!improved) break;\n        }\n\n        best.t = curT;\n    }\n\n    // Output route string\n    string route;\n    route.reserve(max(0, (int)best.seq.size()-1));\n    for(int i=0;i+1<(int)best.seq.size();i++){\n        int u=best.seq[i], v=best.seq[i+1];\n        route.push_back(dirChar(cells[u], cells[v]));\n    }\n    cout << route << \"\\n\";\n    return 0;\n}","future-contest-2022-qual":"#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, K, R;\n    cin >> N >> M >> K >> R;\n\n    vector<double> p(N, 0.0);      // sqrt(sum d^2)\n    vector<long long> p2(N, 0LL); // sum d^2 (for tie-break)\n\n    for (int i = 0; i < N; i++) {\n        long long sum = 0;\n        for (int k = 0; k < K; k++) {\n            long long x;\n            cin >> x;\n            sum += x * x;\n        }\n        p2[i] = sum;\n        p[i] = sqrt((double)sum);\n    }\n\n    vector<vector<int>> out(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        out[u].push_back(v);\n        indeg[v]++;\n    }\n\n    // ---- Static time-based criticality (integer scaled) ----\n    // Use a global ability guess A0 to build a rough proxy duration.\n    const double A0 = 35.0;\n    const long long SCALE = 1000LL;\n\n    vector<long long> timeProxyInt(N);\n    for (int i = 0; i < N; i++) {\n        double diff = p[i] - A0;\n        double wprime = max(0.0, diff);\n        double tproxy = 1.0 + wprime; // consistent with proxy used for scoring\n        timeProxyInt[i] = (long long)llround(tproxy * (double)SCALE);\n    }\n\n    vector<long long> critInt(N, 0);\n    for (int i = N - 1; i >= 0; i--) {\n        long long bestChild = 0;\n        for (int v : out[i]) bestChild = max(bestChild, critInt[v]);\n        critInt[i] = timeProxyInt[i] + bestChild;\n    }\n    long long maxCritInt = 0;\n    for (int i = 0; i < N; i++) maxCritInt = max(maxCritInt, critInt[i]);\n\n    // Ready set ordered by: higher criticality, then smaller difficulty norm, then id.\n    struct Comp {\n        const vector<long long>* crit;\n        const vector<long long>* p2;\n        bool operator()(int a, int b) const {\n            if ((*crit)[a] != (*crit)[b]) return (*crit)[a] > (*crit)[b];\n            if ((*p2)[a] != (*p2)[b]) return (*p2)[a] < (*p2)[b];\n            return a < b;\n        }\n    };\n    Comp comp{&critInt, &p2};\n    set<int, Comp> ready(comp);\n\n    vector<char> state(N, 0); // 0 unstarted, 1 running, 2 done\n    for (int i = 0; i < N; i++) if (indeg[i] == 0) ready.insert(i);\n\n    vector<int> curTask(M, -1);\n    vector<int> startDay(M, -1);\n\n    // ---- Learning parameters per member ----\n    // param[j] ~ threshold on p such that deficit ~ max(0, p_i - param[j])\n    // Bounds LB/UB maintained by observations.\n    const double NEG_INF = -1e100, POS_INF = 1e100;\n    vector<double> LB(M, NEG_INF), UB(M, POS_INF);\n    vector<double> param(M, A0);\n\n    auto recomputeParam = [&](int j) {\n        double lb = LB[j], ub = UB[j];\n        double x;\n        bool lbOk = (lb > NEG_INF/2);\n        bool ubOk = (ub < POS_INF/2);\n        if (!lbOk && !ubOk) x = A0;\n        else if (!lbOk) x = ub - 2.5;\n        else if (!ubOk) x = lb + 2.5;\n        else x = 0.5 * (lb + ub);\n\n        x = min(100.0, max(0.0, x));\n        param[j] = x;\n    };\n\n    // Estimate expected duration under proxy: E[t] ~ 1 + max(0, p_i - param[j])\n    auto estimateExpected = [&](int j, int task) -> double {\n        double diff = p[task] - param[j];\n        double wprime = max(0.0, diff);\n        return 1.0 + wprime;\n    };\n\n    // Score: shorter expected time is better; also favor critical tasks.\n    auto estimateScore = [&](int j, int task) -> double {\n        double expT = estimateExpected(j, task);\n        double critNorm = (maxCritInt ? (double)critInt[task] / (double)maxCritInt : 0.0);\n        const double beta = 2.0;\n        double denom = 1.0 + beta * critNorm;\n        return expT / denom;\n    };\n\n    mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());\n\n    int day = 1;\n    const int LCAND = 200; // improved from ~60\n\n    while (day <= 2000) {\n        vector<int> idle;\n        idle.reserve(M);\n        for (int j = 0; j < M; j++) if (curTask[j] == -1) idle.push_back(j);\n\n        // Stronger first (larger param => easier tasks => smaller deficit)\n        sort(idle.begin(), idle.end(), [&](int a, int b) {\n            if (param[a] != param[b]) return param[a] > param[b];\n            return a < b;\n        });\n\n        vector<pair<int,int>> assign; // (member, task)\n        assign.reserve(M);\n\n        // For each idle member choose best task from top LCAND of ready-set.\n        for (int j : idle) {\n            if (ready.empty()) break;\n\n            int bestTask = -1;\n            double bestScore = 1e100;\n            auto itBest = ready.end();\n\n            int cnt = 0;\n            for (auto it = ready.begin(); it != ready.end() && cnt < LCAND; ++it, ++cnt) {\n                int t = *it;\n                // (state[t] should be 0 here, but safe)\n                if (state[t] != 0) continue;\n\n                double sc = estimateScore(j, t);\n\n                // tiny random tie-breaker\n                sc += uniform_real_distribution<double>(0.0, 1e-7)(rng);\n\n                if (sc < bestScore) {\n                    bestScore = sc;\n                    bestTask = t;\n                    itBest = it;\n                }\n            }\n\n            if (bestTask == -1) break;\n\n            // commit\n            state[bestTask] = 1;\n            curTask[j] = bestTask;\n            startDay[j] = day;\n            ready.erase(itBest);\n            assign.emplace_back(j, bestTask);\n        }\n\n        // Output\n        cout << assign.size();\n        for (auto [j, t] : assign) {\n            cout << ' ' << (j + 1) << ' ' << (t + 1);\n        }\n        cout << \"\\n\" << flush;\n\n        // Read completion status\n        int ncomp;\n        cin >> ncomp;\n        if (ncomp == -1) return 0;\n\n        for (int i = 0; i < ncomp; i++) {\n            int f;\n            cin >> f;\n            --f; // member index\n            int task = curTask[f];\n            if (task < 0) continue; // should not happen\n\n            curTask[f] = -1;\n            state[task] = 2;\n\n            int dur = day - startDay[f] + 1;\n\n            // ---- Update bounds for param[f] using duration ----\n            // Proxy deficit: w' = max(0, p[task] - param[f])\n            // Actual model: t = max(1, w + r), r in [-3,3]\n            //\n            // We use: if dur >= 2 then w' must be > 0 => p - param = w' roughly in [dur-3, dur+3].\n            // Convert to param interval:\n            //   param in [p - (dur+3), p - (dur-3)]\n            // Clamp and update LB/UB accordingly.\n            double pi = p[task];\n\n            if (dur <= 1) {\n                // If observed 1 day, it's likely w' is very small; allow param close to pi.\n                // Conservative: param >= pi - 1 (not too strict)\n                LB[f] = max(LB[f], pi - 1.0);\n            } else {\n                double lowW = max(1.0, (double)dur - 3.0);\n                double highW = (double)dur + 3.0;\n\n                // w' in [lowW, highW] => param in [pi-highW, pi-lowW]\n                LB[f] = max(LB[f], pi - highW);\n                UB[f] = min(UB[f], pi - lowW);\n            }\n\n            // If bounds inverted due to noise, slightly relax by merging towards midpoint.\n            if (LB[f] > UB[f]) {\n                double mid = 0.5 * (LB[f] + UB[f]);\n                LB[f] = mid;\n                UB[f] = mid;\n            }\n\n            // recompute param\n            recomputeParam(f);\n\n            // Update dependencies\n            for (int v : out[task]) {\n                indeg[v]--;\n                if (indeg[v] == 0 && state[v] == 0) {\n                    ready.insert(v);\n                }\n            }\n        }\n\n        day++;\n    }\n\n    return 0;\n}","ahc006":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic inline int manhattan(int x1, int y1, int x2, int y2) {\n    return abs(x1 - x2) + abs(y1 - y2);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    const int N = 1000;\n    const int M = 50;\n    const int XOFF = 400, YOFF = 400;\n    const long long INF = (1LL << 62);\n\n    vector<int> px(N), py(N), dx(N), dy(N);\n    for (int i = 0; i < N; i++) cin >> px[i] >> py[i] >> dx[i] >> dy[i];\n\n    // RNG seed: mix input hash + time for better exploration/robustness\n    uint64_t seed = 0x9e3779b97f4a7c15ULL;\n    for (int i = 0; i < 40; i++) {\n        seed ^= (uint64_t)(px[i] + 1) * 1000003ULL;\n        seed ^= (uint64_t)(py[i] + 7) * 10007ULL;\n        seed ^= (uint64_t)(dx[i] + 13) * 10000019ULL;\n        seed ^= (uint64_t)(dy[i] + 23) * 10000079ULL;\n        seed = seed * 6364136223846793005ULL + 1442695040888963407ULL;\n    }\n    seed ^= (uint64_t)chrono::steady_clock::now().time_since_epoch().count();\n    mt19937 rng((uint32_t)(seed & 0xffffffffu));\n\n    auto idx = [&](int i, int j) { return i * N + j; };\n\n    // Matrices:\n    // internal[i] = pick_i -> drop_i\n    // startDist[i] = office -> pick_i\n    // endDist[i] = drop_i -> office\n    //\n    // trans[i][j] = drop_i -> pick_j\n    // pickDist[i][j] = pick_i -> pick_j\n    // dropDist[i][j] = drop_i -> drop_j\n    vector<int> internal(N), startDist(N), endDist(N);\n    vector<int> trans(N * N), pickDist(N * N), dropDist(N * N);\n\n    for (int i = 0; i < N; i++) {\n        internal[i] = manhattan(px[i], py[i], dx[i], dy[i]);\n        startDist[i] = manhattan(XOFF, YOFF, px[i], py[i]);\n        endDist[i]   = manhattan(dx[i], dy[i], XOFF, YOFF);\n    }\n    for (int i = 0; i < N; i++) {\n        int dix = dx[i], diy = dy[i];\n        int pix = px[i], piy = py[i];\n        for (int j = 0; j < N; j++) {\n            trans[idx(i, j)] = manhattan(dix, diy, px[j], py[j]);\n            pickDist[idx(i, j)] = manhattan(pix, piy, px[j], py[j]);\n            dropDist[idx(i, j)] = manhattan(dix, diy, dx[j], dy[j]);\n        }\n    }\n\n    auto getTrans = [&](int i, int j) -> int { return trans[idx(i, j)]; };\n    auto getPick  = [&](int i, int j) -> int { return pickDist[idx(i, j)]; };\n    auto getDrop  = [&](int i, int j) -> int { return dropDist[idx(i, j)]; };\n\n    auto macroNoInternal = [&](const vector<int>& seq) -> long long {\n        long long c = startDist[seq.front()] + endDist[seq.back()];\n        for (int k = 0; k + 1 < M; k++) c += getTrans(seq[k], seq[k + 1]); // drop_k -> pick_next\n        return c;\n    };\n    auto macroCost = [&](const vector<int>& seq, long long internalSum) -> long long {\n        return internalSum + macroNoInternal(seq);\n    };\n\n    auto twoStageCostExact = [&](const vector<int>& P, const vector<int>& D) -> long long {\n        long long c = startDist[P[0]];\n        for (int i = 0; i + 1 < M; i++) c += getPick(P[i], P[i + 1]);\n        // cross: pick_last -> drop(D0) == dist(drop(D0)->pick_last) = trans[D0][pick_last]\n        c += getTrans(D[0], P.back());\n        for (int i = 0; i + 1 < M; i++) c += getDrop(D[i], D[i + 1]);\n        c += endDist[D.back()];\n        return c;\n    };\n\n    auto buildMacroRoute = [&](const vector<int>& seq) -> vector<pair<int,int>> {\n        vector<pair<int,int>> route;\n        route.reserve(2 * M + 2);\n        route.push_back({XOFF, YOFF});\n        for (int ord : seq) {\n            route.push_back({px[ord], py[ord]});\n            route.push_back({dx[ord], dy[ord]});\n        }\n        route.push_back({XOFF, YOFF});\n        return route;\n    };\n\n    auto buildTwoStageRoute = [&](const vector<int>& P, const vector<int>& D) -> vector<pair<int,int>> {\n        vector<pair<int,int>> route;\n        route.reserve(2 * M + 2);\n        route.push_back({XOFF, YOFF});\n        for (int ord : P) route.push_back({px[ord], py[ord]});\n        for (int ord : D) route.push_back({dx[ord], dy[ord]});\n        route.push_back({XOFF, YOFF});\n        return route;\n    };\n\n    // candidate insertion positions for relocate (small neighborhood)\n    auto relocatePositions = [&](int i) -> array<int, 11> {\n        array<int, 11> cand{};\n        int t = 0;\n        auto add = [&](int x) {\n            if (0 <= x && x < M) cand[t++] = x;\n        };\n        add(0); add(1); add(2);\n        add(M-3); add(M-2); add(M-1);\n        for (int d = -3; d <= 3; d++) add(i + d);\n\n        sort(cand.begin(), cand.end());\n        t = unique(cand.begin(), cand.end()) - cand.begin();\n        // compress to first t, rest arbitrary\n        for (int k = t; k < 11; k++) cand[k] = cand[max(0, t - 1)];\n        return cand;\n    };\n\n    // Macro construction\n    auto buildMacroForward = [&](const vector<int>& subset, bool randomStart) -> vector<int> {\n        vector<char> used(N, 0);\n        vector<int> seq;\n        seq.reserve(M);\n\n        int first = subset[0];\n        for (int v : subset) if (startDist[v] < startDist[first]) first = v;\n\n        if (randomStart) {\n            vector<pair<int,int>> starts;\n            for (int v : subset) starts.push_back({startDist[v], v});\n            sort(starts.begin(), starts.end());\n            int top = min(4, (int)starts.size());\n            uniform_int_distribution<int> ud(0, top - 1);\n            first = starts[ud(rng)].second;\n        }\n\n        seq.push_back(first);\n        used[first] = 1;\n\n        while ((int)seq.size() < M) {\n            int cur = seq.back();\n            int pos = (int)seq.size(); // next index\n            bool isLast = (pos == M - 1);\n\n            vector<pair<long long,int>> cand;\n            cand.reserve(M);\n            for (int c : subset) if (!used[c]) {\n                long long val = getTrans(cur, c);\n                if (isLast) val += endDist[c];\n                cand.push_back({val, c});\n            }\n            sort(cand.begin(), cand.end());\n            int top = randomStart ? min(7, (int)cand.size()) : 1;\n            uniform_int_distribution<int> ud(0, top - 1);\n            int nxt = cand[ud(rng)].second;\n\n            used[nxt] = 1;\n            seq.push_back(nxt);\n        }\n        return seq;\n    };\n\n    auto buildMacroBackward = [&](const vector<int>& subset, bool randomStart) -> vector<int> {\n        vector<char> used(N, 0);\n        vector<int> seq(M, -1);\n\n        int last = subset[0];\n        for (int v : subset) if (endDist[v] < endDist[last]) last = v;\n\n        if (randomStart) {\n            vector<pair<int,int>> lasts;\n            for (int v : subset) lasts.push_back({endDist[v], v});\n            sort(lasts.begin(), lasts.end());\n            int top = min(4, (int)lasts.size());\n            uniform_int_distribution<int> ud(0, top - 1);\n            last = lasts[ud(rng)].second;\n        }\n\n        seq[M-1] = last;\n        used[last] = 1;\n\n        for (int pos = M - 2; pos >= 0; pos--) {\n            int nxt = seq[pos + 1];\n            bool isFirst = (pos == 0);\n\n            vector<pair<long long,int>> cand;\n            cand.reserve(M);\n            for (int c : subset) if (!used[c]) {\n                long long val = getTrans(c, nxt); // drop_c -> pick_nxt\n                if (isFirst) val += startDist[c];\n                cand.push_back({val, c});\n            }\n            sort(cand.begin(), cand.end());\n            int top = randomStart ? min(7, (int)cand.size()) : 1;\n            uniform_int_distribution<int> ud(0, top - 1);\n            int pre = cand[ud(rng)].second;\n\n            used[pre] = 1;\n            seq[pos] = pre;\n        }\n        return seq;\n    };\n\n    auto improveMacro = [&](vector<int>& seq, long long internalSum, int rounds, const chrono::steady_clock::time_point& stopTime) {\n        (void)internalSum;\n        auto timeUp = [&](){ return chrono::steady_clock::now() >= stopTime; };\n\n        long long curNo = macroNoInternal(seq);\n        for (int it = 0; it < rounds && !timeUp(); it++) {\n            bool improved = false;\n\n            // best swap\n            {\n                long long bestNo = curNo;\n                int bi = -1, bj = -1;\n                for (int i = 0; i < M && !timeUp(); i++) {\n                    for (int j = i + 1; j < M && !timeUp(); j++) {\n                        swap(seq[i], seq[j]);\n                        long long nc = macroNoInternal(seq);\n                        swap(seq[i], seq[j]);\n                        if (nc < bestNo) {\n                            bestNo = nc;\n                            bi = i; bj = j;\n                        }\n                    }\n                }\n                if (bi != -1 && bestNo < curNo) {\n                    swap(seq[bi], seq[bj]);\n                    curNo = bestNo;\n                    improved = true;\n                }\n            }\n            if (timeUp()) break;\n            // best relocate in small neighborhood\n            {\n                long long bestNo = curNo;\n                int bestI = -1, bestJ = -1;\n\n                for (int i = 0; i < M && !timeUp(); i++) {\n                    auto candPos = relocatePositions(i);\n                    for (int t = 0; t < 11 && !timeUp(); t++) {\n                        int j = candPos[t];\n                        if (j == i) continue;\n\n                        vector<int> tmp = seq;\n                        int val = tmp[i];\n                        tmp.erase(tmp.begin() + i);\n                        int j2 = j;\n                        if (j > i) j2 = j - 1;\n                        tmp.insert(tmp.begin() + j2, val);\n\n                        long long nc = macroNoInternal(tmp);\n                        if (nc < bestNo) {\n                            bestNo = nc;\n                            bestI = i;\n                            bestJ = j2;\n                        }\n                    }\n                }\n\n                if (bestI != -1 && bestNo < curNo) {\n                    int val = seq[bestI];\n                    seq.erase(seq.begin() + bestI);\n                    seq.insert(seq.begin() + bestJ, val);\n                    curNo = bestNo;\n                    improved = true;\n                }\n            }\n            if (!improved) break;\n        }\n    };\n\n    // Two-stage construction variants (consistent D build; no invalid reverse-after-build)\n    auto buildTwoStage = [&](const vector<int>& subset, int variant, vector<int>& P, vector<int>& D) {\n        vector<char> usedP(N, 0);\n        vector<char> usedD(N, 0);\n        P.clear(); D.clear();\n        P.reserve(M); D.reserve(M);\n\n        // pickups P\n        int firstP = subset[0];\n        for (int v : subset) if (startDist[v] < startDist[firstP]) firstP = v;\n        if (variant >= 1) {\n            vector<pair<int,int>> starts;\n            for (int v : subset) starts.push_back({startDist[v], v});\n            sort(starts.begin(), starts.end());\n            int top = min(4, (int)starts.size());\n            uniform_int_distribution<int> ud(0, top - 1);\n            firstP = starts[ud(rng)].second;\n        }\n        P.push_back(firstP);\n        usedP[firstP] = 1;\n\n        while ((int)P.size() < M) {\n            int cur = P.back();\n            int pos = (int)P.size();\n            bool isLast = (pos == M - 1); // last pickup doesn't need special term, objective uses endDist only on last drop\n\n            (void)isLast;\n            vector<pair<long long,int>> cand;\n            for (int c : subset) if (!usedP[c]) {\n                cand.push_back({getPick(cur, c), c});\n            }\n            sort(cand.begin(), cand.end());\n            int top = (variant >= 2 ? min(6, (int)cand.size()) : 1);\n            if (variant == 1) top = min(4, (int)cand.size());\n            uniform_int_distribution<int> ud(0, top - 1);\n            int nxt = cand[ud(rng)].second;\n\n            usedP[nxt] = 1;\n            P.push_back(nxt);\n        }\n\n        int lastPick = P.back();\n\n        // destinations D\n        vector<pair<long long,int>> cross; // trans[D0][lastPick]\n        for (int v : subset) cross.push_back({getTrans(v, lastPick), v});\n        sort(cross.begin(), cross.end());\n        int D0 = cross[0].second;\n        if (variant == 1) {\n            int top = min(4, (int)cross.size());\n            uniform_int_distribution<int> ud(0, top - 1);\n            D0 = cross[ud(rng)].second;\n        } else if (variant == 2) {\n            int top = min(5, (int)cross.size());\n            uniform_int_distribution<int> ud(0, top - 1);\n            D0 = cross[ud(rng)].second;\n        }\n\n        D.push_back(D0);\n        usedD[D0] = 1;\n\n        while ((int)D.size() < M) {\n            int curDrop = D.back();\n            bool nextIsLastChoice = ((int)D.size() == M - 1); // next pushed becomes last, so add endDist\n            vector<pair<long long,int>> cand;\n            for (int c : subset) if (!usedD[c]) {\n                long long val = getDrop(curDrop, c);\n                if (nextIsLastChoice) val += endDist[c];\n                cand.push_back({val, c});\n            }\n            sort(cand.begin(), cand.end());\n            int top = 1;\n            if (variant == 1) top = min(4, (int)cand.size());\n            if (variant == 2) top = min(6, (int)cand.size());\n            uniform_int_distribution<int> ud(0, top - 1);\n            int nxt = cand[ud(rng)].second;\n\n            usedD[nxt] = 1;\n            D.push_back(nxt);\n        }\n    };\n\n    auto improveTwoStage = [&](vector<int>& P, vector<int>& D, int rounds, const chrono::steady_clock::time_point& stopTime) {\n        auto timeUp = [&](){ return chrono::steady_clock::now() >= stopTime; };\n\n        for (int it = 0; it < rounds && !timeUp(); it++) {\n            bool improved = false;\n            long long cur = twoStageCostExact(P, D);\n\n            // swap in P\n            {\n                long long best = cur;\n                int bi=-1, bj=-1;\n                for (int i = 0; i < M && !timeUp(); i++) {\n                    for (int j = i+1; j < M && !timeUp(); j++) {\n                        swap(P[i], P[j]);\n                        long long nc = twoStageCostExact(P, D);\n                        swap(P[i], P[j]);\n                        if (nc < best) { best = nc; bi=i; bj=j; }\n                    }\n                }\n                if (bi != -1 && best < cur) {\n                    swap(P[bi], P[bj]);\n                    cur = best;\n                    improved = true;\n                }\n            }\n            if (timeUp()) break;\n\n            // relocate in P (limited)\n            if (!improved || rounds >= 2) {\n                long long best = cur;\n                int bestI=-1, bestJ=-1;\n                for (int i = 0; i < M && !timeUp(); i++) {\n                    auto candPos = relocatePositions(i);\n                    for (int t = 0; t < 11 && !timeUp(); t++) {\n                        int j = candPos[t];\n                        if (j == i) continue;\n\n                        vector<int> tmp = P;\n                        int val = tmp[i];\n                        tmp.erase(tmp.begin()+i);\n                        int j2 = j;\n                        if (j > i) j2 = j - 1;\n                        tmp.insert(tmp.begin()+j2, val);\n\n                        long long nc = twoStageCostExact(tmp, D);\n                        if (nc < best) { best = nc; bestI=i; bestJ=j2; }\n                    }\n                }\n                if (bestI != -1 && best < cur) {\n                    int val = P[bestI];\n                    P.erase(P.begin()+bestI);\n                    P.insert(P.begin()+bestJ, val);\n                    cur = best;\n                    improved = true;\n                }\n            }\n            if (timeUp()) break;\n\n            // swap in D\n            {\n                long long best = cur;\n                int bi=-1, bj=-1;\n                for (int i = 0; i < M && !timeUp(); i++) {\n                    for (int j = i+1; j < M && !timeUp(); j++) {\n                        swap(D[i], D[j]);\n                        long long nc = twoStageCostExact(P, D);\n                        swap(D[i], D[j]);\n                        if (nc < best) { best = nc; bi=i; bj=j; }\n                    }\n                }\n                if (bi != -1 && best < cur) {\n                    swap(D[bi], D[bj]);\n                    cur = best;\n                    improved = true;\n                }\n            }\n            if (timeUp()) break;\n\n            // relocate in D (limited)\n            if (rounds >= 2) {\n                long long best = cur;\n                int bestI=-1, bestJ=-1;\n                for (int i = 0; i < M && !timeUp(); i++) {\n                    auto candPos = relocatePositions(i);\n                    for (int t = 0; t < 11 && !timeUp(); t++) {\n                        int j = candPos[t];\n                        if (j == i) continue;\n\n                        vector<int> tmp = D;\n                        int val = tmp[i];\n                        tmp.erase(tmp.begin()+i);\n                        int j2 = j;\n                        if (j > i) j2 = j - 1;\n                        tmp.insert(tmp.begin()+j2, val);\n\n                        long long nc = twoStageCostExact(P, tmp);\n                        if (nc < best) { best = nc; bestI=i; bestJ=j2; }\n                    }\n                }\n                if (bestI != -1 && best < cur) {\n                    int val = D[bestI];\n                    D.erase(D.begin()+bestI);\n                    D.insert(D.begin()+bestJ, val);\n                    cur = best;\n                    improved = true;\n                }\n            }\n\n            if (!improved) break;\n        }\n    };\n\n    // Weighted subset sampling\n    vector<long long> weight(N);\n    for (int i = 0; i < N; i++) weight[i] = (long long)internal[i] + startDist[i] + endDist[i];\n\n    vector<int> ids(N);\n    iota(ids.begin(), ids.end(), 0);\n    sort(ids.begin(), ids.end(), [&](int a, int b){\n        if (weight[a] != weight[b]) return weight[a] < weight[b];\n        return a < b;\n    });\n\n    vector<int> pool;\n    {\n        int TOP = 360;\n        for (int i = 0; i < TOP; i++) pool.push_back(ids[i]);\n        uniform_int_distribution<int> ud(0, N-1);\n        while ((int)pool.size() < 620) {\n            int v = ud(rng);\n            if (!binary_search(pool.begin(), pool.end(), v)) pool.push_back(v);\n        }\n        sort(pool.begin(), pool.end());\n        pool.erase(unique(pool.begin(), pool.end()), pool.end());\n    }\n\n    auto sampleSubset = [&](int k) -> vector<int> {\n        vector<pair<long double,int>> keys;\n        keys.reserve(pool.size());\n        uniform_real_distribution<long double> ur(1e-12L, 1.0L);\n        for (int v : pool) {\n            long double u = ur(rng);\n            long double key = -log(u) * ((long double)weight[v] + 1.0L);\n            keys.push_back({key, v});\n        }\n        nth_element(keys.begin(), keys.begin() + k, keys.end(),\n                    [](auto &a, auto &b){ return a.first < b.first; });\n        keys.resize(k);\n        vector<int> subset;\n        subset.reserve(k);\n        for (auto &p : keys) subset.push_back(p.second);\n        return subset;\n    };\n\n    auto internalSumOf = [&](const vector<int>& subset) -> long long {\n        long long s = 0;\n        for (int v : subset) s += internal[v];\n        return s;\n    };\n\n    // Search\n    auto start = chrono::steady_clock::now();\n    auto stopTime = start + chrono::milliseconds(1950);\n\n    long long bestCost = INF;\n    vector<int> bestOrders;\n    vector<pair<int,int>> bestRoute;\n\n    // keep top macro candidates for deeper two-stage\n    struct MacroCand { long long cost; long long isum; vector<int> seq; };\n    vector<MacroCand> topMacros;\n    auto pushTopMacro = [&](long long cost, long long isum, const vector<int>& seq) {\n        int KEEP = 18;\n        if ((int)topMacros.size() < KEEP) {\n            topMacros.push_back({cost, isum, seq});\n            return;\n        }\n        int worst = 0;\n        for (int i = 1; i < (int)topMacros.size(); i++)\n            if (topMacros[i].cost > topMacros[worst].cost) worst = i;\n        if (cost < topMacros[worst].cost) topMacros[worst] = {cost, isum, seq};\n    };\n\n    auto evalSubset = [&](const vector<int>& subset, bool randomMacro) {\n        if (chrono::steady_clock::now() >= stopTime) return;\n\n        long long isum = internalSumOf(subset);\n\n        // macro forward\n        {\n            auto seq = buildMacroForward(subset, randomMacro);\n            improveMacro(seq, isum, randomMacro ? 1 : 2, stopTime);\n            long long c = macroCost(seq, isum);\n            pushTopMacro(c, isum, seq);\n\n            if (c < bestCost) {\n                bestCost = c;\n                bestOrders = seq;\n                bestRoute = buildMacroRoute(seq);\n            }\n\n            // two-stage from this set if promising\n            if (c <= bestCost + 30000) {\n                for (int var = 0; var < 3; var++) {\n                    vector<int> P, D;\n                    buildTwoStage(seq, var, P, D);\n                    improveTwoStage(P, D, 1, stopTime);\n                    long long tc = twoStageCostExact(P, D);\n                    if (tc < bestCost) {\n                        bestCost = tc;\n                        bestOrders = P;\n                        bestRoute = buildTwoStageRoute(P, D);\n                    }\n                    if (chrono::steady_clock::now() >= stopTime) break;\n                }\n            }\n        }\n        if (chrono::steady_clock::now() >= stopTime) return;\n\n        // macro backward\n        {\n            auto seq = buildMacroBackward(subset, randomMacro);\n            improveMacro(seq, isum, randomMacro ? 1 : 2, stopTime);\n            long long c = macroCost(seq, isum);\n            pushTopMacro(c, isum, seq);\n\n            if (c < bestCost) {\n                bestCost = c;\n                bestOrders = seq;\n                bestRoute = buildMacroRoute(seq);\n            }\n\n            if (c <= bestCost + 30000) {\n                for (int var = 0; var < 3; var++) {\n                    vector<int> P, D;\n                    buildTwoStage(seq, var, P, D);\n                    improveTwoStage(P, D, 1, stopTime);\n                    long long tc = twoStageCostExact(P, D);\n                    if (tc < bestCost) {\n                        bestCost = tc;\n                        bestOrders = P;\n                        bestRoute = buildTwoStageRoute(P, D);\n                    }\n                    if (chrono::steady_clock::now() >= stopTime) break;\n                }\n            }\n        }\n    };\n\n    // initial deterministic subsets\n    for (int rep = 0; rep < 6 && chrono::steady_clock::now() < stopTime; rep++) {\n        vector<int> subset;\n        if (rep == 0) {\n            subset.assign(ids.begin(), ids.begin() + M);\n        } else if (rep == 1) {\n            subset.assign(ids.begin(), ids.begin() + M);\n            // already sorted by weight; keep\n        } else if (rep == 2) {\n            subset = ids;\n            // sort by internal\n            sort(subset.begin(), subset.end(), [&](int a, int b){ return internal[a] < internal[b]; });\n            subset.resize(M);\n        } else if (rep == 3) {\n            subset = ids;\n            sort(subset.begin(), subset.end(), [&](int a, int b){ return startDist[a] < startDist[b]; });\n            subset.resize(M);\n        } else if (rep == 4) {\n            subset = ids;\n            sort(subset.begin(), subset.end(), [&](int a, int b){ return endDist[a] < endDist[b]; });\n            subset.resize(M);\n        } else {\n            subset = sampleSubset(M);\n        }\n        evalSubset(subset, false);\n    }\n\n    // random subsets\n    for (int it = 0; it < 220 && chrono::steady_clock::now() < stopTime; it++) {\n        auto subset = sampleSubset(M);\n        evalSubset(subset, true);\n    }\n\n    // Deep two-stage on best macro candidates\n    sort(topMacros.begin(), topMacros.end(), [](const MacroCand& a, const MacroCand& b){ return a.cost < b.cost; });\n    int K2 = min(8, (int)topMacros.size());\n    for (int i = 0; i < K2 && chrono::steady_clock::now() < stopTime; i++) {\n        const auto& mc = topMacros[i];\n        for (int var = 0; var < 3 && chrono::steady_clock::now() < stopTime; var++) {\n            vector<int> P, D;\n            buildTwoStage(mc.seq, var, P, D);\n            improveTwoStage(P, D, 2, stopTime); // deeper for top candidates\n            long long tc = twoStageCostExact(P, D);\n            if (tc < bestCost) {\n                bestCost = tc;\n                bestOrders = P;\n                bestRoute = buildTwoStageRoute(P, D);\n            }\n        }\n    }\n\n    // Set-level perturbation around bestOrders\n    if (chrono::steady_clock::now() < stopTime) {\n        vector<char> in(N, 0);\n        for (int v : bestOrders) in[v] = 1;\n\n        vector<int> outCand;\n        outCand.reserve(N);\n        for (int v : ids) if (!in[v]) outCand.push_back(v);\n        int OUT = min(260, (int)outCand.size());\n\n        auto bestSet = bestOrders; // permutation of chosen set; set itself\n        vector<int> curSet = bestSet;\n\n        uniform_int_distribution<int> pickPos(0, M - 1);\n\n        for (int t = 0; t < 70 && chrono::steady_clock::now() < stopTime; t++) {\n            int remCnt = (t % 10 == 0 ? 2 : 1);\n\n            vector<int> subset2 = curSet;\n            vector<char> in2 = in;\n\n            // remove remCnt highest internal positions (biased removal)\n            vector<int> pos(M);\n            iota(pos.begin(), pos.end(), 0);\n            sort(pos.begin(), pos.end(), [&](int a, int b){\n                return internal[subset2[a]] > internal[subset2[b]];\n            });\n            for (int r = 0; r < remCnt; r++) {\n                int p = pos[r];\n                in2[subset2[p]] = 0;\n                subset2[p] = -1;\n            }\n\n            // add distinct outside candidates\n            for (int r = 0; r < remCnt; r++) {\n                int add;\n                int tries = 0;\n                while (true) {\n                    add = outCand[uniform_int_distribution<int>(0, OUT-1)(rng)];\n                    if (!in2[add]) break;\n                    tries++;\n                    if (tries > 20) {\n                        // fallback: scan\n                        for (int v : outCand) if (!in2[v]) { add = v; break; }\n                        break;\n                    }\n                }\n                // place into first -1 slot\n                for (int i = 0; i < M; i++) if (subset2[i] == -1) { subset2[i] = add; break; }\n                in2[add] = 1;\n            }\n\n            // evaluate perturbed subset quickly\n            long long isum2 = internalSumOf(subset2);\n            auto seqF = buildMacroForward(subset2, true);\n            improveMacro(seqF, isum2, 1, stopTime);\n            long long cF = macroCost(seqF, isum2);\n\n            if (cF < bestCost) {\n                bestCost = cF;\n                bestOrders = seqF;\n                bestRoute = buildMacroRoute(seqF);\n                in.assign(N, 0);\n                for (int v : bestOrders) in[v] = 1;\n\n                outCand.clear();\n                for (int v : ids) if (!in[v]) outCand.push_back(v);\n                OUT = min(260, (int)outCand.size());\n                curSet = bestOrders;\n            }\n\n            // try two-stage only if macro is promising\n            if (cF <= bestCost + 35000) {\n                for (int var = 0; var < 2 && chrono::steady_clock::now() < stopTime; var++) {\n                    vector<int> P, D;\n                    buildTwoStage(seqF, var, P, D);\n                    improveTwoStage(P, D, 1, stopTime);\n                    long long tc = twoStageCostExact(P, D);\n                    if (tc < bestCost) {\n                        bestCost = tc;\n                        bestOrders = P;\n                        bestRoute = buildTwoStageRoute(P, D);\n                        in.assign(N, 0);\n                        for (int v : bestOrders) in[v] = 1;\n                        outCand.clear();\n                        for (int v : ids) if (!in[v]) outCand.push_back(v);\n                        OUT = min(260, (int)outCand.size());\n                        curSet = bestOrders;\n                    }\n                }\n            }\n        }\n    }\n\n    // Output\n    cout << M << \"\\n\";\n    for (int i = 0; i < M; i++) {\n        if (i) cout << ' ';\n        cout << (bestOrders[i] + 1);\n    }\n    cout << \"\\n\";\n\n    cout << bestRoute.size() << \"\\n\";\n    for (auto &pt : bestRoute) {\n        cout << pt.first << ' ' << pt.second << ' ';\n    }\n    cout << \"\\n\";\n    return 0;\n}","ahc007":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct DSU {\n    int n;\n    vector<int> p, sz;\n    int comps;\n    DSU() : n(0), comps(0) {}\n    explicit DSU(int n_) { init(n_); }\n\n    void init(int n_) {\n        n = n_;\n        p.resize(n);\n        sz.assign(n, 1);\n        iota(p.begin(), p.end(), 0);\n        comps = n;\n    }\n\n    inline int find(int x) {\n        while (p[x] != x) {\n            p[x] = p[p[x]];\n            x = p[x];\n        }\n        return x;\n    }\n\n    inline bool 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        comps--;\n        return true;\n    }\n};\n\n// Feasible iff (current accepted edges) + (all remaining edges remIdx..M-1) is connected.\nstatic bool feasibleSkip(int N, int remIdx, DSU &curDSU,\n                          const vector<vector<uint16_t>> &sufRoot) {\n    if (curDSU.comps == 1) return true;\n\n    vector<int> rootToId(N, -1), compId(N);\n    int k = 0;\n    for (int v = 0; v < N; v++) {\n        int r = curDSU.find(v);\n        int &id = rootToId[r];\n        if (id == -1) id = k++;\n        compId[v] = id;\n    }\n    if (k <= 1) return true;\n\n    DSU comb(k);\n    vector<int> firstA(N, -1); // suffix-root -> first component-id\n    for (int v = 0; v < N; v++) {\n        int a = compId[v];\n        int bRoot = (int)sufRoot[remIdx][v]; // [0..N-1]\n        int &f = firstA[bRoot];\n        if (f == -1) f = a;\n        else comb.unite(a, f);\n        if (comb.comps == 1) return true;\n    }\n    return comb.comps == 1;\n}\n\nstatic inline int distRound(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    double d = sqrt((double)dx * dx + (double)dy * dy);\n    return (int)llround(d);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int a, b;\n    if (!(cin >> a >> b)) return 0;\n\n    int N, M;\n    vector<int> x, y, U, V;\n\n    // Robust parsing (for safety in nonstandard local runners):\n    // In the official generator, x,y are in [0,800], so \"b>800\" won't happen.\n    if (b > 800) {\n        N = a; M = b;\n        x.assign(N, 0); y.assign(N, 0);\n        for (int i = 0; i < N; i++) cin >> x[i] >> y[i];\n        U.assign(M, 0); V.assign(M, 0);\n        for (int i = 0; i < M; i++) cin >> U[i] >> V[i];\n    } else {\n        N = 400; M = 1995;\n        x.assign(N, 0); y.assign(N, 0);\n        x[0] = a; y[0] = b;\n        for (int i = 1; i < N; i++) cin >> x[i] >> y[i];\n        U.assign(M, 0); V.assign(M, 0);\n        for (int i = 0; i < M; i++) cin >> U[i] >> V[i];\n    }\n\n    vector<int> d(M);\n    for (int i = 0; i < M; i++) {\n        d[i] = distRound(x[U[i]], y[U[i]], x[V[i]], y[V[i]]);\n        if (d[i] == 0) d[i] = 1;\n    }\n\n    // Offline MST on proxy weights d[i]\n    vector<int> ord(M);\n    iota(ord.begin(), ord.end(), 0);\n    sort(ord.begin(), ord.end(), [&](int i, int j) {\n        if (d[i] != d[j]) return d[i] < d[j];\n        return i < j;\n    });\n\n    DSU dsuTmp(N);\n    vector<char> inMST(M, 0);\n    long long mst_d_sum = 0;\n\n    for (int idx : ord) {\n        if (dsuTmp.unite(U[idx], V[idx])) {\n            inMST[idx] = 1;\n            mst_d_sum += d[idx];\n        }\n    }\n\n    double avgTargetL = 2.0 * (double)mst_d_sum / (double)(N - 1);\n\n    // Precompute suffix DSU roots for feasibility check.\n    vector<vector<uint16_t>> sufRoot(M + 1, vector<uint16_t>(N));\n    DSU sufDSU(N);\n    for (int v = 0; v < N; v++) sufRoot[M][v] = (uint16_t)v;\n\n    for (int i = M - 1; i >= 0; i--) {\n        sufDSU.unite(U[i], V[i]);\n        for (int v = 0; v < N; v++) sufRoot[i][v] = (uint16_t)sufDSU.find(v);\n    }\n\n    DSU curDSU(N);\n\n    for (int i = 0; i < M; i++) {\n        long long li;\n        cin >> li;\n\n        int ru = curDSU.find(U[i]);\n        int rv = curDSU.find(V[i]);\n\n        if (ru == rv) {\n            cout << 0 << \"\\n\" << flush;\n            continue;\n        }\n\n        double timeProg = (double)i / (double)(M - 1); // [0,1]\n        double needFrac = (double)(curDSU.comps - 1) / (double)(N - 1); // [0,1]\n        double blend = 0.6 * timeProg + 0.4 * needFrac; // responsive schedule\n\n        // Ratio threshold\n        double rThreshold = 1.52 + 1.35 * blend; // tuned from your best\n        if (inMST[i]) rThreshold += 0.20;\n        else rThreshold -= 0.06;\n        rThreshold = max(1.0, min(3.0, rThreshold));\n\n        bool acceptRatio = (long double)li <= (long double)rThreshold * (long double)d[i];\n\n        // Absolute threshold\n        double absMul = 0.93 + 0.80 * blend; // tuned\n        if (inMST[i]) absMul *= 1.05;\n        double absLimit = absMul * avgTargetL;\n        bool acceptAbs = (long double)li <= (long double)absLimit;\n\n        // Ultra-good fast accept\n        bool ultraGood = (long double)li <= (long double)1.25 * (long double)d[i];\n\n        bool accept = false;\n        if (ultraGood) {\n            accept = true;\n        } else if (acceptRatio) {\n            if (acceptAbs) accept = true;\n            else if (inMST[i]) {\n                // Slightly relax absolute gate on offline MST edges\n                accept = ((long double)li <= (long double)1.12 * (long double)absLimit);\n            }\n        }\n\n        if (!accept) {\n            bool ok = feasibleSkip(N, i + 1, curDSU, sufRoot);\n            if (!ok) accept = true; // forced for feasibility\n        }\n\n        if (accept) {\n            curDSU.unite(ru, rv);\n            cout << 1 << \"\\n\" << flush;\n        } else {\n            cout << 0 << \"\\n\" << flush;\n        }\n    }\n    return 0;\n}","ahc008":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const int H = 30, W = 30;\nstatic const int V = H * W;\n\nstatic inline int id(int x, int y) { return x * W + y; }\nstatic inline bool inb(int x, int y) { return 0 <= x && x < H && 0 <= y && y < W; }\n\nstatic const int dx4[4] = {-1, 1, 0, 0};\nstatic const int dy4[4] = {0, 0, -1, 1};\n\nstatic inline bool isAdj(int a, int b) {\n    int ax = a / W, ay = a % W;\n    int bx = b / W, by = b % W;\n    return abs(ax - bx) + abs(ay - by) == 1;\n}\n\nstatic inline char moveChar(int from, int to) {\n    int fx = from / W, fy = from % W;\n    int tx = to / W, ty = to % W;\n    if (tx == fx - 1 && ty == fy) return 'U';\n    if (tx == fx + 1 && ty == fy) return 'D';\n    if (tx == fx && ty == fy - 1) return 'L';\n    if (tx == fx && ty == fy + 1) return 'R';\n    return '.';\n}\n\nstatic inline char blockChar(int from, int to) {\n    // from -> to is adjacent; we output lowercase to block \"to\"\n    int fx = from / W, fy = from % W;\n    int tx = to / W, ty = to % W;\n    if (tx == fx - 1 && ty == fy) return 'u';\n    if (tx == fx + 1 && ty == fy) return 'd';\n    if (tx == fx && ty == fy - 1) return 'l';\n    if (tx == fx && ty == fy + 1) return 'r';\n    return '.';\n}\n\nstatic vector<int> thinWallPath(bool vertical,\n                                 const vector<char>& humanInitAt,\n                                 const vector<char>& petInitAt,\n                                 mt19937& rng) {\n    const int INF = 1e9;\n    vector<int> cost(V, 1);\n\n    for (int x = 0; x < H; x++) for (int y = 0; y < W; y++) {\n        int c = id(x, y);\n        if (humanInitAt[c]) { cost[c] = INF; continue; }\n\n        int w = 1;\n        if (petInitAt[c]) w += 320;\n\n        int petAdj = 0;\n        for (int k = 0; k < 4; k++) {\n            int nx = x + dx4[k], ny = y + dy4[k];\n            if (!inb(nx, ny)) continue;\n            if (petInitAt[id(nx, ny)]) petAdj++;\n        }\n        w += petAdj * 90;\n        w += (int)(rng() % 3);\n        cost[c] = w;\n    }\n\n    using P = pair<long long,int>;\n    vector<long long> dist(V, (long long)INF * INF);\n    vector<int> parent(V, -1);\n    priority_queue<P, vector<P>, greater<P>> pq;\n\n    if (vertical) {\n        for (int y = 0; y < W; y++) {\n            int s = id(0, y);\n            if (cost[s] >= INF) continue;\n            dist[s] = cost[s];\n            parent[s] = -2;\n            pq.push({dist[s], s});\n        }\n    } else {\n        for (int x = 0; x < H; x++) {\n            int s = id(x, 0);\n            if (cost[s] >= INF) continue;\n            dist[s] = cost[s];\n            parent[s] = -2;\n            pq.push({dist[s], s});\n        }\n    }\n\n    int bestGoal = -1;\n    long long bestDist = (long long)INF * INF;\n\n    while (!pq.empty()) {\n        auto [d, u] = pq.top(); pq.pop();\n        if (d != dist[u]) continue;\n\n        int ux = u / W, uy = u % W;\n        if (vertical) {\n            if (ux == H - 1 && d < bestDist) bestDist = d, bestGoal = u;\n        } else {\n            if (uy == W - 1 && d < bestDist) bestDist = d, bestGoal = u;\n        }\n\n        int x = ux, y = uy;\n        for (int k = 0; k < 4; k++) {\n            int nx = x + dx4[k], ny = y + dy4[k];\n            if (!inb(nx, ny)) continue;\n            int v = id(nx, ny);\n            if (cost[v] >= INF) continue;\n            long long nd = d + cost[v];\n            if (nd < dist[v]) {\n                dist[v] = nd;\n                parent[v] = u;\n                pq.push({nd, v});\n            }\n        }\n    }\n\n    if (bestGoal == -1) {\n        // fallback middle-ish wall\n        vector<int> path;\n        if (vertical) {\n            int ymid = W / 2;\n            for (int x = 0; x < H; x++) path.push_back(id(x, ymid));\n        } else {\n            int xmid = H / 2;\n            for (int y = 0; y < W; y++) path.push_back(id(xmid, y));\n        }\n        return path;\n    }\n\n    vector<int> path;\n    for (int cur = bestGoal;;) {\n        path.push_back(cur);\n        int p = parent[cur];\n        if (p == -2) break;\n        cur = p;\n        if (cur < 0) break;\n    }\n    reverse(path.begin(), path.end());\n    return path;\n}\n\nstatic vector<int> buildCorridor2thickOrdered(const vector<int>& thinWall,\n                                             const vector<char>& humanInitAt,\n                                             const vector<char>& petInitAt) {\n    int L = (int)thinWall.size();\n    const int KEYINF = 1e9;\n    vector<int> keyForCell(V, KEYINF);\n\n    auto petAdjCount = [&](int c)->int{\n        int x = c / W, y = c % W;\n        int cnt = 0;\n        for (int k = 0; k < 4; k++) {\n            int nx = x + dx4[k], ny = y + dy4[k];\n            if (!inb(nx, ny)) continue;\n            if (petInitAt[id(nx, ny)]) cnt++;\n        }\n        return cnt;\n    };\n\n    for (int i = 0; i < L; i++) {\n        int c = thinWall[i];\n        int x = c / W, y = c % W;\n\n        // primary\n        if (!humanInitAt[c]) keyForCell[c] = min(keyForCell[c], 2 * i);\n\n        // direction along thin wall\n        int dxdir = 0, dydir = 0;\n        if (i + 1 < L) {\n            int nc = thinWall[i + 1];\n            dxdir = nc / W - x;\n            dydir = nc % W - y;\n        } else if (i - 1 >= 0) {\n            int pc = thinWall[i - 1];\n            dxdir = x - pc / W;\n            dydir = y - pc % W;\n        }\n\n        // perpendicular candidates:\n        // p1 = (-dydir, dxdir), p2 = (dydir, -dxdir)\n        int px1 = x - dydir, py1 = y + dxdir;\n        int px2 = x + dydir, py2 = y - dxdir;\n\n        bool ok1 = inb(px1, py1) && !humanInitAt[id(px1, py1)];\n        bool ok2 = inb(px2, py2) && !humanInitAt[id(px2, py2)];\n\n        int chosen = -1;\n        if (ok1 && ok2) {\n            int c1 = id(px1, py1), c2 = id(px2, py2);\n            chosen = (petAdjCount(c1) <= petAdjCount(c2) ? c1 : c2);\n        } else if (ok1) {\n            chosen = id(px1, py1);\n        } else if (ok2) {\n            chosen = id(px2, py2);\n        }\n\n        if (chosen != -1) keyForCell[chosen] = min(keyForCell[chosen], 2 * i + 1);\n    }\n\n    vector<pair<int,int>> keyed;\n    keyed.reserve(V);\n    for (int c = 0; c < V; c++) if (keyForCell[c] != KEYINF) keyed.push_back({keyForCell[c], c});\n    sort(keyed.begin(), keyed.end());\n\n    vector<int> ordered;\n    ordered.reserve(keyed.size());\n    for (auto &kv : keyed) ordered.push_back(kv.second);\n    return ordered;\n}\n\nstatic double evalCorridor(const vector<int>& wallTargets,\n                           const vector<int>& petPos,\n                           int M) {\n    vector<char> blocked(V, 0);\n    for (int c : wallTargets) blocked[c] = 1;\n\n    // components in final passable world\n    vector<int> compId(V, -1);\n    vector<int> compSize;\n    queue<int> q;\n\n    for (int s = 0; s < V; s++) {\n        if (blocked[s] || compId[s] != -1) continue;\n        int cid = (int)compSize.size();\n        compSize.push_back(0);\n        compId[s] = cid;\n        q.push(s);\n        while (!q.empty()) {\n            int u = q.front(); q.pop();\n            compSize[cid]++;\n            int ux = u / W, uy = u % W;\n            for (int k = 0; k < 4; k++) {\n                int vx = ux + dx4[k], vy = uy + dy4[k];\n                if (!inb(vx, vy)) continue;\n                int v = id(vx, vy);\n                if (blocked[v] || compId[v] != -1) continue;\n                compId[v] = cid;\n                q.push(v);\n            }\n        }\n    }\n\n    int compCnt = (int)compSize.size();\n    vector<int> petCnt(compCnt, 0);\n    for (int p : petPos) {\n        if (blocked[p]) continue;\n        int c = compId[p];\n        if (c >= 0) petCnt[c]++;\n    }\n\n    // exact score contribution per component\n    vector<double> compScore(compCnt, 0.0);\n    for (int c = 0; c < compCnt; c++) {\n        int n = petCnt[c];\n        compScore[c] = (double)compSize[c] / 900.0 * pow(0.5, n);\n    }\n\n    sort(compScore.begin(), compScore.end(), greater<double>());\n\n    int use = min(M, (int)compScore.size());\n    double sum = 0;\n    for (int i = 0; i < use; i++) sum += compScore[i];\n    for (int i = use; i < M; i++) sum += (compScore.empty() ? 0 : compScore[0]);\n\n    return sum / M;\n}\n\nstatic bool barrierSeparated(bool vertical, const vector<char>& blocked) {\n    vector<char> vis(V, 0);\n    queue<int> q;\n\n    if (vertical) {\n        // top->bottom reachability\n        for (int y = 0; y < W; y++) {\n            int s = id(0, y);\n            if (!blocked[s]) { vis[s] = 1; q.push(s); }\n        }\n        while (!q.empty()) {\n            int u = q.front(); q.pop();\n            int ux = u / W;\n            if (ux == H - 1) return false;\n            int uy = u % W;\n            (void)uy;\n            int x = ux;\n            int y = u % W;\n            (void)x; (void)y;\n            for (int k = 0; k < 4; k++) {\n                int vx = ux + dx4[k], vy = (u % W) + dy4[k];\n                if (!inb(vx, vy)) continue;\n                int v = id(vx, vy);\n                if (blocked[v] || vis[v]) continue;\n                vis[v] = 1;\n                q.push(v);\n            }\n        }\n        return true;\n    } else {\n        // left->right reachability\n        for (int x = 0; x < H; x++) {\n            int s = id(x, 0);\n            if (!blocked[s]) { vis[s] = 1; q.push(s); }\n        }\n        while (!q.empty()) {\n            int u = q.front(); q.pop();\n            int uy = u % W;\n            if (uy == W - 1) return false;\n            int ux = u / W;\n            for (int k = 0; k < 4; k++) {\n                int vx = ux + dx4[k], vy = uy + dy4[k];\n                if (!inb(vx, vy)) continue;\n                int v = id(vx, vy);\n                if (blocked[v] || vis[v]) continue;\n                vis[v] = 1;\n                q.push(v);\n            }\n        }\n        return true;\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    mt19937 rng((uint32_t)chrono::steady_clock::now().time_since_epoch().count());\n\n    int N;\n    cin >> N;\n    vector<int> petPos(N);\n    vector<char> petInitAt(V, 0);\n\n    for (int i = 0; i < N; i++) {\n        int px, py, pt;\n        cin >> px >> py >> pt;\n        --px; --py;\n        petPos[i] = id(px, py);\n        petInitAt[petPos[i]] = 1;\n    }\n\n    int M;\n    cin >> M;\n    vector<int> humanPos(M);\n    vector<char> humanInitAt(V, 0);\n\n    for (int i = 0; i < M; i++) {\n        int hx, hy;\n        cin >> hx >> hy;\n        --hx; --hy;\n        humanPos[i] = id(hx, hy);\n        humanInitAt[humanPos[i]] = 1;\n    }\n\n    // Choose corridor orientation\n    auto thinV = thinWallPath(true, humanInitAt, petInitAt, rng);\n    auto thinH = thinWallPath(false, humanInitAt, petInitAt, rng);\n\n    auto corrV = buildCorridor2thickOrdered(thinV, humanInitAt, petInitAt);\n    auto corrH = buildCorridor2thickOrdered(thinH, humanInitAt, petInitAt);\n\n    double scoreV = evalCorridor(corrV, petPos, M);\n    double scoreH = evalCorridor(corrH, petPos, M);\n\n    bool vertical = (scoreV >= scoreH);\n    vector<int> wallTargets = vertical ? corrV : corrH;\n    int T = (int)wallTargets.size();\n\n    vector<char> wallSet(V, 0);\n    vector<int> wallIndex(V, -1);\n    for (int i = 0; i < T; i++) {\n        wallSet[wallTargets[i]] = 1;\n        wallIndex[wallTargets[i]] = i;\n    }\n\n    // Builders split\n    int K = min(M, 10);\n    if (K < 1) K = 1;\n\n    vector<int> segL(K), segR(K), ptr(K);\n    for (int k = 0; k < K; k++) {\n        segL[k] = (long long)k * T / K;\n        segR[k] = (long long)(k + 1) * T / K;\n        ptr[k] = segL[k];\n    }\n\n    // Assign builders to segments\n    vector<int> builderHuman(K, -1);\n    vector<char> usedHuman(M, 0);\n    vector<int> ord(K);\n    iota(ord.begin(), ord.end(), 0);\n    sort(ord.begin(), ord.end(), [&](int a, int b) {\n        return (segR[a] - segL[a]) > (segR[b] - segL[b]);\n    });\n\n    for (int idx = 0; idx < K; idx++) {\n        int k = ord[idx];\n        int midIdx = (segL[k] + segR[k]) / 2;\n        if (midIdx >= T) midIdx = T - 1;\n        int keyCell = wallTargets[midIdx];\n\n        int best = -1, bestD = INT_MAX;\n        for (int h = 0; h < M; h++) if (!usedHuman[h]) {\n            int hx = humanPos[h] / W, hy = humanPos[h] % W;\n            int cx = keyCell / W, cy = keyCell % W;\n            int d = abs(hx - cx) + abs(hy - cy);\n            if (d < bestD) { bestD = d; best = h; }\n        }\n        if (best == -1) best = 0;\n        builderHuman[k] = best;\n        usedHuman[best] = 1;\n    }\n\n    vector<char> isBuilder(M, 0);\n    for (int k = 0; k < K; k++) isBuilder[builderHuman[k]] = 1;\n\n    vector<char> blockedActual(V, 0);\n    vector<char> petAt(V, 0), humanAt(V, 0);\n\n    // canBlock legality for a target wall cell\n    auto canBlockNow = [&](int targetCell) -> bool {\n        if (targetCell < 0 || targetCell >= V) return false;\n        if (blockedActual[targetCell]) return false;\n\n        if (petAt[targetCell]) return false;\n        if (humanAt[targetCell]) return false;\n\n        int x = targetCell / W, y = targetCell % W;\n        for (int d = 0; d < 4; d++) {\n            int nx = x + dx4[d], ny = y + dy4[d];\n            if (!inb(nx, ny)) continue;\n            if (petAt[id(nx, ny)]) return false; // adjacent cell contains a pet => cannot block\n        }\n        return true;\n    };\n\n    auto builderMoveNext = [&](int k, int bpos, int targetCell,\n                                const vector<char>& plannedBlocked) -> int {\n        // candidate destinations = passable neighbors of targetCell\n        int tx = targetCell / W, ty = targetCell % W;\n\n        vector<int> candidates;\n        candidates.reserve(4);\n\n        // ahead limit: relaxed to avoid stalling\n        int aheadLimit = ptr[k] + 12;\n\n        auto allowedWallStep = [&](int cell)->bool{\n            if (!wallSet[cell]) return true;\n            int wi = wallIndex[cell];\n            if (wi < 0) return false;\n\n            // Only allow wall cells within this segment\n            if (!(segL[k] <= wi && wi < segR[k])) return false;\n\n            // Avoid far-future targets too much\n            if (wi > aheadLimit) return false;\n            return true;\n        };\n\n        for (int d = 0; d < 4; d++) {\n            int nx = tx + dx4[d], ny = ty + dy4[d];\n            if (!inb(nx, ny)) continue;\n            int c = id(nx, ny);\n            if (c == targetCell) continue;\n            if (blockedActual[c] || plannedBlocked[c]) continue;\n            if (!allowedWallStep(c)) continue;\n            candidates.push_back(c);\n        }\n        if (candidates.empty()) return bpos;\n\n        // BFS from bpos to reach nearest candidate\n        vector<int> dist(V, -1), parent(V, -1);\n        queue<int> q;\n        dist[bpos] = 0;\n        q.push(bpos);\n\n        vector<char> isCand(V, 0);\n        for (int c : candidates) isCand[c] = 1;\n\n        int bestCand = -1;\n        int bestDist = INT_MAX;\n\n        auto forbidden = [&](int cell)->bool{\n            if (blockedActual[cell] || plannedBlocked[cell]) return true;\n            if (cell != bpos && wallSet[cell] && !allowedWallStep(cell)) return true;\n            return false;\n        };\n\n        while (!q.empty()) {\n            int u = q.front(); q.pop();\n            if (bestCand != -1 && dist[u] >= bestDist) continue;\n\n            if (isCand[u]) {\n                bestCand = u;\n                bestDist = dist[u];\n                continue;\n            }\n\n            int ux = u / W, uy = u % W;\n            for (int d = 0; d < 4; d++) {\n                int vx = ux + dx4[d], vy = uy + dy4[d];\n                if (!inb(vx, vy)) continue;\n                int v = id(vx, vy);\n                if (forbidden(v)) continue;\n                if (dist[v] != -1) continue;\n                dist[v] = dist[u] + 1;\n                parent[v] = u;\n                q.push(v);\n            }\n        }\n\n        if (bestCand == -1) return bpos;\n\n        // reconstruct next step from bpos toward bestCand\n        int cur = bestCand;\n        while (parent[cur] != -1 && parent[cur] != bpos) cur = parent[cur];\n        if (parent[cur] == -1) return bpos;\n        return cur;\n    };\n\n    bool released = false;\n\n    for (int turn = 0; turn < 300; turn++) {\n        // update occupancy\n        fill(petAt.begin(), petAt.end(), 0);\n        for (int i = 0; i < N; i++) petAt[petPos[i]] = 1;\n\n        fill(humanAt.begin(), humanAt.end(), 0);\n        for (int i = 0; i < M; i++) humanAt[humanPos[i]] = 1;\n\n        vector<char> action(M, '.');\n        vector<char> plannedBlocked(V, 0);\n\n        if (!released) {\n            if (barrierSeparated(vertical, blockedActual)) {\n                released = true;\n            } else {\n                // construction turn: only builders act (two-phase for legality)\n                vector<char> willBlock(K, 0);\n\n                // Pass 1: decide blocks\n                for (int k = 0; k < K; k++) {\n                    int h = builderHuman[k];\n                    if (h < 0) continue;\n\n                    while (ptr[k] < segR[k] && blockedActual[wallTargets[ptr[k]]]) ptr[k]++;\n\n                    if (ptr[k] >= segR[k]) continue;\n\n                    int targetCell = wallTargets[ptr[k]];\n                    int bpos = humanPos[h];\n\n                    if (isAdj(bpos, targetCell)) {\n                        if (!plannedBlocked[targetCell] && canBlockNow(targetCell)) {\n                            action[h] = blockChar(bpos, targetCell);\n                            plannedBlocked[targetCell] = 1;\n                            willBlock[k] = 1;\n                        } else {\n                            action[h] = '.';\n                        }\n                    } else {\n                        action[h] = '.';\n                    }\n                }\n\n                // Pass 2: moves for non-blocking builders\n                for (int k = 0; k < K; k++) {\n                    int h = builderHuman[k];\n                    if (h < 0) continue;\n\n                    while (ptr[k] < segR[k] && blockedActual[wallTargets[ptr[k]]]) ptr[k]++;\n                    if (ptr[k] >= segR[k]) continue;\n\n                    if (willBlock[k]) continue;\n\n                    int targetCell = wallTargets[ptr[k]];\n                    int bpos = humanPos[h];\n\n                    if (isAdj(bpos, targetCell)) {\n                        // Adjacent but not blockable now => wait\n                        action[h] = '.';\n                    } else {\n                        int nxt = builderMoveNext(k, bpos, targetCell, plannedBlocked);\n                        if (nxt != bpos) action[h] = moveChar(bpos, nxt);\n                        else action[h] = '.';\n                    }\n                }\n\n                // Non-builders stay '.'\n                for (int i = 0; i < M; i++) if (!isBuilder[i]) action[i] = '.';\n            }\n        }\n\n        // After release: freeze everyone ('.') => score depends only on components, not motion\n        if (released) {\n            for (int i = 0; i < M; i++) action[i] = '.';\n        }\n\n        // output\n        string out(M, '.');\n        for (int i = 0; i < M; i++) out[i] = action[i];\n        cout << out << \"\\n\" << flush;\n\n        // apply human actions\n        for (int i = 0; i < M; i++) {\n            char a = action[i];\n            if (a == '.') continue;\n\n            int pos = humanPos[i];\n            int x = pos / W, y = pos % W;\n\n            if (a == 'U') { x--; humanPos[i] = id(x, y); }\n            else if (a == 'D') { x++; humanPos[i] = id(x, y); }\n            else if (a == 'L') { y--; humanPos[i] = id(x, y); }\n            else if (a == 'R') { y++; humanPos[i] = id(x, y); }\n            else {\n                // lowercase: block adjacent cell in direction of the lowercase\n                int bx = x, by = y;\n                if (a == 'u') bx--;\n                else if (a == 'd') bx++;\n                else if (a == 'l') by--;\n                else if (a == 'r') by++;\n                if (inb(bx, by)) blockedActual[id(bx, by)] = 1;\n            }\n        }\n\n        // advance ptr for builders (if their target got blocked)\n        for (int k = 0; k < K; k++) {\n            while (ptr[k] < segR[k] && blockedActual[wallTargets[ptr[k]]]) ptr[k]++;\n        }\n\n        // read pet movements\n        for (int i = 0; i < N; i++) {\n            string mv;\n            cin >> mv;\n            int p = petPos[i];\n            int x = p / W, y = p % W;\n            if (mv != \".\") {\n                for (char c : mv) {\n                    if (c == 'U') x--;\n                    else if (c == 'D') x++;\n                    else if (c == 'L') y--;\n                    else if (c == 'R') y++;\n                }\n                petPos[i] = id(x, y);\n            }\n        }\n    }\n\n    return 0;\n}","ahc009":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int H = 20;\nstatic constexpr int W = 20;\nstatic constexpr int N = H * W;\nstatic constexpr int L = 200;\n\nusing ld = long double;\nusing db = double;\n\nstruct Node {\n    array<db, N> dp; // probability mass on non-target cells\n    db score;        // exact accumulated expected reward up to current step\n    int parent;\n    char act;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int si, sj, ti, tj;\n    double p_in;\n    cin >> si >> sj >> ti >> tj >> p_in;\n\n    vector<string> hwall(H);\n    for (int i = 0; i < H; i++) cin >> hwall[i]; // 19 chars\n\n    vector<string> vwall(H - 1);\n    for (int i = 0; i < H - 1; i++) cin >> vwall[i]; // 20 chars\n\n    auto id = [&](int r, int c) { return r * W + c; };\n    int start = id(si, sj);\n    int target = id(ti, tj);\n\n    const db Pforget = (db)p_in;\n    const db Qmove = (db)(1.0 - p_in);\n\n    // Precompute transition with remembered-action attempt (ignoring forgetting)\n    static int moveTo[N][4]; // 0=U,1=D,2=L,3=R\n    for (int r = 0; r < H; r++) {\n        for (int c = 0; c < W; c++) {\n            int v = id(r, c);\n            // U\n            if (r == 0) moveTo[v][0] = v;\n            else moveTo[v][0] = (vwall[r - 1][c] == '1') ? v : id(r - 1, c);\n            // D\n            if (r == H - 1) moveTo[v][1] = v;\n            else moveTo[v][1] = (vwall[r][c] == '1') ? v : id(r + 1, c);\n            // L\n            if (c == 0) moveTo[v][2] = v;\n            else moveTo[v][2] = (hwall[r][c - 1] == '1') ? v : id(r, c - 1);\n            // R\n            if (c == W - 1) moveTo[v][3] = v;\n            else moveTo[v][3] = (hwall[r][c] == '1') ? v : id(r, c + 1);\n        }\n    }\n\n    // BFS distances in static graph\n    const int INF = 1e9;\n    vector<int> dist(N, INF);\n    queue<int> q;\n    dist[target] = 0;\n    q.push(target);\n\n    while (!q.empty()) {\n        int v = q.front(); q.pop();\n        int dv = dist[v];\n        for (int a = 0; a < 4; a++) {\n            int u = moveTo[v][a];\n            if (u == v) continue; // blocked edge / no progress\n            if (dist[u] > dv + 1) {\n                dist[u] = dv + 1;\n                q.push(u);\n            }\n        }\n    }\n\n    int distMaxFin = 0;\n    for (int v = 0; v < N; v++) if (dist[v] < INF) distMaxFin = max(distMaxFin, dist[v]);\n\n    // clamp dist for unreachable (shouldn't happen by statement)\n    vector<int> distClamped(N);\n    for (int v = 0; v < N; v++) {\n        if (dist[v] >= INF) distClamped[v] = distMaxFin + 10;\n        else distClamped[v] = dist[v];\n    }\n\n    // rewardAt[t]: reach target at turn t+1 => 401-(t+1)\n    vector<db> rewardAt(L);\n    for (int t = 0; t < L; t++) rewardAt[t] = (db)(401 - (t + 1));\n\n    static const char dirChar[4] = {'U','D','L','R'};\n\n    // Build heuristic table using negative-binomial-ish approximation\n    auto buildHeuristic = [&](db qHeur) -> vector<db> {\n        qHeur = max<db>(1e-6, min<db>(0.9999, qHeur));\n        ld qFail = (ld)1.0 - (ld)qHeur;\n\n        vector<db> Hh((L + 1) * N, 0.0);\n\n        for (int t = 0; t < L; t++) {\n            int rem = L - t;\n            vector<ld> E(rem + 1, 0.0);\n\n            for (int k = 1; k <= rem; k++) {\n                ld pj = pow((ld)qHeur, k); // P(J=k) with simplistic model\n                ld expected = 0.0;\n\n                for (int j = k; j <= rem; j++) {\n                    // completion reward at absolute turn (t+j)\n                    ld r = (ld)(401 - (t + j));\n                    if (r > 0) expected += r * pj;\n\n                    if (j == rem) break;\n                    ld ratio = (ld)j / (ld)(j - k + 1);\n                    pj = pj * ratio * qFail;\n                    if (pj < 1e-18L) break;\n                }\n                E[k] = expected;\n            }\n\n            for (int v = 0; v < N; v++) {\n                if (v == target) continue;\n                int k = dist[v];\n                if (k <= 0 || k >= INF || k > rem) Hh[(size_t)t * N + v] = 0.0;\n                else Hh[(size_t)t * N + v] = (db)E[k];\n            }\n        }\n        return Hh;\n    };\n\n    auto runBeam = [&](db qHeur, int beamW, uint64_t seed) -> pair<string, db> {\n        vector<db> Hh = buildHeuristic(qHeur);\n        auto Hptr = [&](int tNext) -> const db* {\n            return &Hh[(size_t)tNext * N];\n        };\n\n        vector<Node> pool;\n        pool.reserve((L + 1) * beamW + 16);\n\n        Node root;\n        root.dp.fill(0.0);\n        root.dp[start] = 1.0;\n        root.score = 0.0;\n        root.parent = -1;\n        root.act = '?';\n        pool.push_back(root);\n\n        vector<int> beamIdx;\n        beamIdx.reserve(beamW);\n        beamIdx.push_back(0);\n\n        mt19937_64 rng(seed);\n        normal_distribution<db> gauss(0.0, 1.0);\n        uniform_real_distribution<db> uni(0.0, 1.0);\n\n        // diversity bins\n        int numBins = 10;\n        db binWidth = max<db>(1.0, (db)distMaxFin / (db)numBins);\n        if (binWidth < 1.0) binWidth = 1.0;\n\n        vector<db> bestEst(beamW, -1e300);\n        vector<db> bestScore(beamW, 0.0);\n        vector<int> bestParent(beamW, -1);\n        vector<char> bestAct(beamW, '?');\n        vector<int> bestBucket(beamW, -1);\n        vector<array<db, N>> bestDp(beamW);\n\n        // workspace dpNext\n        array<db, N> dpNext;\n\n        auto bucketOfDist = [&](double d) -> int {\n            int b = (int)(d / binWidth);\n            if (b < 0) b = 0;\n            if (b >= numBins) b = numBins - 1;\n            return b;\n        };\n\n        for (int t = 0; t < L; t++) {\n            int tNext = t + 1;\n            const db* Hnext = Hptr(tNext);\n            db rwd = rewardAt[t];\n\n            int curSize = 0;\n\n            auto insertCandidate = [&](db est, db exactScore, int parent, char act,\n                                        const array<db, N>& dpCand, int candBucket) {\n                if (curSize < beamW) {\n                    bestEst[curSize] = est;\n                    bestScore[curSize] = exactScore;\n                    bestParent[curSize] = parent;\n                    bestAct[curSize] = act;\n                    bestBucket[curSize] = candBucket;\n                    bestDp[curSize] = dpCand;\n                    curSize++;\n                    return;\n                }\n\n                // locate worst overall\n                int worstAll = 0;\n                for (int i = 1; i < beamW; i++) if (bestEst[i] < bestEst[worstAll]) worstAll = i;\n\n                // locate worst inside same bucket\n                int worstB = -1;\n                db worstBVal = 1e300;\n                for (int i = 0; i < beamW; i++) {\n                    if (bestBucket[i] == candBucket && bestEst[i] < worstBVal) {\n                        worstBVal = bestEst[i];\n                        worstB = i;\n                    }\n                }\n\n                int repl = (worstB == -1 ? worstAll : worstB);\n\n                if (est > bestEst[repl]) {\n                    bestEst[repl] = est;\n                    bestScore[repl] = exactScore;\n                    bestParent[repl] = parent;\n                    bestAct[repl] = act;\n                    bestBucket[repl] = candBucket;\n                    bestDp[repl] = dpCand;\n                } else {\n                    // stochastic keep if close (prevents deterministic collapse)\n                    db diff = bestEst[repl] - est; // positive if worse\n                    db scale = 1.0 + fabsl(bestEst[repl]);\n                    if (diff < 0.01 * scale) {\n                        // ~10% chance to replace among near ties\n                        if (uni(rng) < 0.10) {\n                            bestEst[repl] = est;\n                            bestScore[repl] = exactScore;\n                            bestParent[repl] = parent;\n                            bestAct[repl] = act;\n                            bestBucket[repl] = candBucket;\n                            bestDp[repl] = dpCand;\n                        }\n                    }\n                }\n            };\n\n            vector<int> nextBeamIdx;\n            nextBeamIdx.reserve(beamW);\n\n            for (int idx : beamIdx) {\n                const Node& nd = pool[idx];\n\n                for (int a = 0; a < 4; a++) {\n                    dpNext.fill(0.0);\n\n                    db probReach = 0.0; // mass reaching target at this turn (remembered)\n                    db future = 0.0;    // sum dpNext[v]*Hnext[v] excluding target\n                    db sumProb = 0.0;\n                    db sumWD = 0.0;\n\n                    // modal tracking: state with highest dpNext probability mass\n                    db maxVal = -1.0;\n                    int modalDist = distMaxFin + 10;\n\n                    for (int v = 0; v < N; v++) {\n                        if (v == target) continue;\n                        db dv = nd.dp[v];\n                        if (dv == 0.0) continue;\n\n                        int w = moveTo[v][a];\n\n                        if (w == target) {\n                            probReach += dv * Qmove;\n                            db addStay = dv * Pforget;\n                            dpNext[v] += addStay;\n                            db addDist = addStay;\n\n                            future += addStay * Hnext[v];\n                            sumProb += addDist;\n                            sumWD += (db)addDist * (db)distClamped[v];\n\n                            if (dpNext[v] > maxVal) {\n                                maxVal = dpNext[v];\n                                modalDist = distClamped[v];\n                            }\n                        } else {\n                            db addMove = dv * Qmove;\n                            dpNext[w] += addMove;\n                            future += addMove * Hnext[w];\n                            sumProb += addMove;\n                            sumWD += (db)addMove * (db)distClamped[w];\n\n                            if (dpNext[w] > maxVal) {\n                                maxVal = dpNext[w];\n                                modalDist = distClamped[w];\n                            }\n\n                            db addStay = dv * Pforget;\n                            dpNext[v] += addStay;\n                            future += addStay * Hnext[v];\n                            sumProb += addStay;\n                            sumWD += (db)addStay * (db)distClamped[v];\n\n                            if (dpNext[v] > maxVal) {\n                                maxVal = dpNext[v];\n                                modalDist = distClamped[v];\n                            }\n                        }\n                    }\n\n                    db gain = probReach * rwd;\n                    db newScore = nd.score + gain;\n                    db est = newScore + future + (db)1e-7 * gauss(rng);\n\n                    // decide bucket: prefer modal if distribution is not too spread\n                    double meanDist = (sumProb > 1e-18 ? (double)(sumWD / sumProb) : (double)(distMaxFin + 10));\n                    double modalRatio = (sumProb > 1e-18 ? (double)(maxVal / sumProb) : 0.0);\n\n                    double useDist = (modalRatio >= 0.15 ? (double)modalDist : meanDist);\n                    int candBucket = bucketOfDist(useDist);\n\n                    insertCandidate(est, newScore, idx, dirChar[a], dpNext, candBucket);\n                }\n            }\n\n            // collect kept candidates and form next beam sorted by est\n            vector<int> order(curSize);\n            iota(order.begin(), order.end(), 0);\n            sort(order.begin(), order.end(), [&](int i, int j) { return bestEst[i] > bestEst[j]; });\n\n            nextBeamIdx.clear();\n            for (int i = 0; i < curSize; i++) {\n                int k = order[i];\n                Node nn;\n                nn.dp = bestDp[k];\n                nn.score = bestScore[k];\n                nn.parent = bestParent[k];\n                nn.act = bestAct[k];\n                pool.push_back(std::move(nn));\n                nextBeamIdx.push_back((int)pool.size() - 1);\n            }\n\n            beamIdx.swap(nextBeamIdx);\n        }\n\n        // choose best by exact score\n        int bestNode = beamIdx[0];\n        for (int idx : beamIdx) if (pool[idx].score > pool[bestNode].score) bestNode = idx;\n\n        // reconstruct string\n        string ans;\n        ans.reserve(L);\n        int cur = bestNode;\n        while (pool[cur].parent != -1) {\n            ans.push_back(pool[cur].act);\n            cur = pool[cur].parent;\n        }\n        reverse(ans.begin(), ans.end());\n        if ((int)ans.size() != L) {\n            if ((int)ans.size() > L) ans.resize(L);\n            else while ((int)ans.size() < L) ans.push_back('U');\n        }\n        return {ans, pool[bestNode].score};\n    };\n\n    // multiple heuristic variants\n    vector<db> mult = {0.70, 0.82, 0.95, 1.05, 1.18, 1.32};\n    int beamW = 58;\n\n    // base seed from input\n    uint64_t baseSeed = 0x9e3779b97f4a7c15ULL;\n    baseSeed ^= (uint64_t)si * 10007ULL + (uint64_t)sj * 1009ULL;\n    baseSeed ^= (uint64_t)ti * 10037ULL + (uint64_t)tj * 997ULL;\n    baseSeed ^= (uint64_t)llround(p_in * 100000.0);\n\n    string bestS;\n    db bestVal = -1e300;\n\n    for (int i = 0; i < (int)mult.size(); i++) {\n        db qHeur = Qmove * mult[i];\n        uint64_t seed = baseSeed ^ (uint64_t)(i + 1) * 0x1000003ULL ^ (uint64_t)(beamW * 10007);\n        auto [s, sc] = runBeam(qHeur, beamW, seed);\n        if (sc > bestVal) {\n            bestVal = sc;\n            bestS = std::move(s);\n        }\n    }\n\n    cout << bestS << \"\\n\";\n    return 0;\n}","ahc010":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 30;\nstatic constexpr int CELLS = N * N;          // 900\nstatic constexpr int DIRS = 4;\nstatic constexpr int STATES = CELLS * DIRS; // 3600\n\n// Directions: 0=left, 1=up, 2=right, 3=down\nstatic constexpr int di[4] = {0, -1, 0, 1};\nstatic constexpr int dj[4] = {-1, 0, 1, 0};\n\n// toBase[t][entryDir] = exitDir or -1 for the tile in its base orientation\nstatic const int8_t toBase[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\nstatic int8_t toRot[8][4][4]; // toRot[type][rotCCW][entryDir] -> exitDir or -1\n\nstatic uint8_t tileType[CELLS];\nstatic int16_t neighCell[CELLS][4]; // neighbor cell for exitDir or -1\nstatic int16_t exitNb[CELLS][4][4]; // exitNb[c][rot][entryDir] -> neighbor cell (cell index) or -1\nstatic uint8_t needEntryDir[CELLS][4][4]; // needEntryDir[c][rot][entryDir] -> entryDir at neighbor (0..3)\nstatic bool acceptEnter[8][4][4]; // acceptEnter[nbType][nbRot][needDir]\n\nstatic int32_t nextTable[CELLS][4][4]; // nextTable[c][rot][entryDir] -> nextState or -1\nstatic int32_t nextState[STATES];      // functional graph edges on states\n\nstatic uint8_t rotCurr[CELLS];\nstatic uint8_t rotBest[CELLS];\n\nstruct EvalResult {\n    long long score = 0;\n    int best1 = 0;\n    int best2 = 0;\n};\n\n// Stamp arrays for cycle detection\nstatic uint32_t doneStamp[STATES];\nstatic uint32_t inStackStamp[STATES];\nstatic uint32_t evalId = 1;\nstatic uint32_t stackId = 1;\nstatic int posInPath[STATES];\nstatic int pathArr[STATES];\n\nstatic inline void applyRotation(int c, uint8_t newR) {\n    rotCurr[c] = newR;\n    int base = c * 4;\n    for (int entry = 0; entry < 4; entry++) {\n        nextState[base + entry] = nextTable[c][newR][entry];\n    }\n}\n\nstatic inline int localCompatCell(int c, uint8_t r) {\n    int sum = 0;\n    int t = tileType[c];\n    for (int entry = 0; entry < 4; entry++) {\n        int nb = exitNb[c][r][entry];\n        if (nb < 0) continue;\n        uint8_t needDir = needEntryDir[c][r][entry];\n        uint8_t nbR = rotCurr[nb];\n        if (acceptEnter[tileType[nb]][nbR][needDir]) sum++;\n    }\n    return sum;\n}\n\nstatic inline EvalResult evaluateCurrent() {\n    if (++evalId == UINT32_MAX - 2) {\n        memset(doneStamp, 0, sizeof(doneStamp));\n        memset(inStackStamp, 0, sizeof(inStackStamp));\n        evalId = 1;\n        stackId = 1;\n    }\n\n    int best1 = 0, best2 = 0;\n    int cntBest1 = 0;\n\n    for (int v0 = 0; v0 < STATES; v0++) {\n        if (doneStamp[v0] == evalId) continue;\n\n        if (++stackId == UINT32_MAX - 2) {\n            memset(inStackStamp, 0, sizeof(inStackStamp));\n            stackId = 1;\n        }\n\n        int cur = v0;\n        int pathLen = 0;\n\n        while (cur != -1 &&\n               doneStamp[cur] != evalId &&\n               inStackStamp[cur] != stackId) {\n            inStackStamp[cur] = stackId;\n            posInPath[cur] = pathLen;\n            pathArr[pathLen++] = cur;\n            cur = nextState[cur];\n        }\n\n        if (cur != -1 && inStackStamp[cur] == stackId && doneStamp[cur] != evalId) {\n            int startIdx = posInPath[cur];\n            int len = pathLen - startIdx;\n\n            if (len > best1) {\n                best2 = best1;\n                best1 = len;\n                cntBest1 = 1;\n            } else if (len == best1) {\n                cntBest1++;\n                if (cntBest1 >= 2) best2 = best1; // multiplicity rule\n            } else if (len > best2) {\n                best2 = len;\n            }\n        }\n\n        for (int i = 0; i < pathLen; i++) doneStamp[pathArr[i]] = evalId;\n    }\n\n    EvalResult res;\n    res.best1 = best1;\n    res.best2 = best2;\n    res.score = (best2 > 0) ? 1LL * best1 * best2 : 0LL;\n    return res;\n}\n\nstatic inline void buildNextStateFromCurr() {\n    for (int c = 0; c < CELLS; c++) {\n        int base = c * 4;\n        uint8_t r = rotCurr[c];\n        for (int entry = 0; entry < 4; entry++) {\n            nextState[base + entry] = nextTable[c][r][entry];\n        }\n    }\n}\n\n// Final best-first exact intensification (NO pointer-ref bug: operates on globals)\nstatic void finalIntensify(double timeLimit, int evalLimit, long long &bestScore) {\n    // Start from best\n    memcpy(rotCurr, rotBest, CELLS);\n    buildNextStateFromCurr();\n\n    EvalResult cur = evaluateCurrent();\n    long long curScore = cur.score;\n    if (curScore > bestScore) {\n        bestScore = curScore;\n        memcpy(rotBest, rotCurr, CELLS);\n    }\n\n    static uint8_t topR[CELLS][3];\n    static int topV[CELLS][3];\n    static int topGain[CELLS];\n    static int ver[CELLS];\n    int globalVer = 1;\n\n    auto recomputeCell = [&](int c) {\n        uint8_t oldR = rotCurr[c];\n        int vals[4];\n        for (uint8_t r = 0; r < 4; r++) vals[r] = localCompatCell(c, r);\n\n        // get top 3 rotations by vals\n        int idx[4] = {0, 1, 2, 3};\n        for (int i = 0; i < 4; i++) {\n            for (int j = i + 1; j < 4; j++) {\n                if (vals[idx[j]] > vals[idx[i]]) swap(idx[i], idx[j]);\n            }\n        }\n\n        for (int k = 0; k < 3; k++) {\n            topR[c][k] = (uint8_t)idx[k];\n            topV[c][k] = vals[idx[k]];\n        }\n        int curV = vals[oldR];\n        topGain[c] = max(0, topV[c][0] - curV);\n\n        ver[c] = ++globalVer;\n    };\n\n    for (int c = 0; c < CELLS; c++) recomputeCell(c);\n\n    struct Node {\n        int prio;\n        int c;\n        int tag;\n        bool operator<(Node const& o) const {\n            if (prio != o.prio) return prio < o.prio; // max-heap\n            return c > o.c;\n        }\n    };\n\n    priority_queue<Node> pq;\n    for (int c = 0; c < CELLS; c++) if (topGain[c] > 0) pq.push({topGain[c], c, ver[c]});\n\n    auto tnow = chrono::steady_clock::now();\n    auto elapsed = [&]() -> double {\n        return chrono::duration<double>(chrono::steady_clock::now() - tnow).count();\n    };\n\n    int evalCount = 0;\n\n    auto pushCell = [&](int c) {\n        if (topGain[c] > 0) pq.push({topGain[c], c, ver[c]});\n    };\n\n    while (!pq.empty() && elapsed() < timeLimit && evalCount < evalLimit) {\n        auto nd = pq.top(); pq.pop();\n        int c = nd.c;\n        if (ver[c] != nd.tag) continue;\n        if (topGain[c] <= 0) continue;\n\n        uint8_t oldR = rotCurr[c];\n        bool improved = false;\n\n        // try up to top3 rotations\n        for (int k = 0; k < 3 && evalCount < evalLimit; k++) {\n            uint8_t nr = topR[c][k];\n            if (nr == oldR) continue;\n\n            applyRotation(c, nr);\n            EvalResult nxt = evaluateCurrent();\n            evalCount++;\n\n            if (nxt.score > curScore) {\n                curScore = nxt.score;\n                if (curScore > bestScore) {\n                    bestScore = curScore;\n                    memcpy(rotBest, rotCurr, CELLS);\n                }\n                improved = true;\n\n                // recompute c and its neighbors (localCompat changes only there)\n                recomputeCell(c);\n                int i0 = c / N, j0 = c % N;\n                for (int dir = 0; dir < 4; dir++) {\n                    int ni = i0 + di[dir], nj = j0 + dj[dir];\n                    if (0 <= ni && ni < N && 0 <= nj && nj < N) {\n                        int cc = ni * N + nj;\n                        recomputeCell(cc);\n                        pushCell(cc);\n                    }\n                }\n                pushCell(c);\n                break;\n            } else {\n                applyRotation(c, oldR); // revert\n            }\n\n            if (elapsed() >= timeLimit) break;\n        }\n\n        if (!improved && elapsed() > timeLimit * 0.98) break;\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // Build toRot mapping:\n    // rotate tile CCW by rot:\n    // original entryDir = (entryDir + rot) mod 4\n    // exit direction rotates by -rot\n    for (int t = 0; t < 8; t++) {\n        for (int rot = 0; rot < 4; rot++) {\n            for (int entry = 0; entry < 4; entry++) {\n                int d_orig = (entry + rot) & 3;\n                int exit_orig = toBase[t][d_orig];\n                toRot[t][rot][entry] = (exit_orig < 0) ? -1 : ((exit_orig - rot + 4) & 3);\n            }\n        }\n    }\n\n    // Read input\n    for (int i = 0; i < N; i++) {\n        string s;\n        cin >> s;\n        for (int j = 0; j < N; j++) tileType[i * N + j] = (uint8_t)(s[j] - '0');\n    }\n\n    // Neighbors\n    for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) {\n        int c = i * N + j;\n        for (int outDir = 0; outDir < 4; outDir++) {\n            int ni = i + di[outDir], nj = j + dj[outDir];\n            neighCell[c][outDir] = (0 <= ni && ni < N && 0 <= nj && nj < N) ? (ni * N + nj) : -1;\n        }\n    }\n\n    // Precompute acceptEnter, exitNb/needEntryDir, nextTable\n    for (int nbT = 0; nbT < 8; nbT++) {\n        for (int nbRot = 0; nbRot < 4; nbRot++) {\n            for (int needDir = 0; needDir < 4; needDir++) {\n                acceptEnter[nbT][nbRot][needDir] = (toRot[nbT][nbRot][needDir] >= 0);\n            }\n        }\n    }\n\n    for (int c = 0; c < CELLS; c++) {\n        int t = tileType[c];\n        for (int rot = 0; rot < 4; rot++) {\n            for (int entry = 0; entry < 4; entry++) {\n                int exitDir = toRot[t][rot][entry];\n                if (exitDir < 0) {\n                    exitNb[c][rot][entry] = -1;\n                    needEntryDir[c][rot][entry] = 0;\n                    nextTable[c][rot][entry] = -1;\n                    continue;\n                }\n                int nb = neighCell[c][exitDir];\n                if (nb < 0) {\n                    exitNb[c][rot][entry] = -1;\n                    needEntryDir[c][rot][entry] = 0;\n                    nextTable[c][rot][entry] = -1;\n                    continue;\n                }\n                uint8_t needDir = (exitDir + 2) & 3;\n                exitNb[c][rot][entry] = (int16_t)nb;\n                needEntryDir[c][rot][entry] = needDir;\n                nextTable[c][rot][entry] = nb * 4 + (int)needDir;\n            }\n        }\n    }\n\n    mt19937_64 rng((uint64_t)chrono::steady_clock::now().time_since_epoch().count());\n    auto randInt = [&](int L, int R) -> int {\n        return uniform_int_distribution<int>(L, R)(rng);\n    };\n    auto rand01 = [&]() -> double {\n        return uniform_real_distribution<double>(0.0, 1.0)(rng);\n    };\n\n    // Time control\n    const double TL = 1.995;\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    long long bestScore = -1;\n    vector<int> allCells(CELLS);\n    iota(allCells.begin(), allCells.end(), 0);\n\n    // SA parameters\n    int restarts = 26;\n    for (int rs = 0; rs < restarts; rs++) {\n        if (elapsed() > TL - 0.05) break;\n\n        // init\n        for (int c = 0; c < CELLS; c++) {\n            rotCurr[c] = (rs == 0 ? 0 : (uint8_t)randInt(0, 3));\n        }\n        buildNextStateFromCurr();\n\n        // greedy tightening (few sweeps)\n        shuffle(allCells.begin(), allCells.end(), rng);\n        int sweeps = 2 + (rs % 3 == 0);\n        for (int sw = 0; sw < sweeps; sw++) {\n            shuffle(allCells.begin(), allCells.end(), rng);\n            for (int c : allCells) {\n                uint8_t oldR = rotCurr[c];\n                int bestR = oldR;\n                int bestV = localCompatCell(c, oldR);\n                for (uint8_t r = 0; r < 4; r++) if (r != oldR) {\n                    int v = localCompatCell(c, r);\n                    if (v > bestV) { bestV = v; bestR = r; }\n                }\n                if ((uint8_t)bestR != oldR && rand01() < 0.90) applyRotation(c, (uint8_t)bestR);\n            }\n        }\n\n        EvalResult cur = evaluateCurrent();\n        long long curScore = cur.score;\n        if (curScore > bestScore) {\n            bestScore = curScore;\n            memcpy(rotBest, rotCurr, CELLS);\n        }\n\n        // SA loop until leaving time for final intensification\n        int noImprove = 0;\n        const int kickPeriod = 7600;\n\n        const double TL_SA_END = TL - 0.05;\n        double Tstart = 6.5e6, Tend = 200.0;\n\n        while (elapsed() < TL_SA_END) {\n            double prog = elapsed() / TL;\n            double T = Tend + (Tstart - Tend) * (1.0 - prog);\n            if (T < 1.0) T = 1.0;\n\n            // pick a cell by sampled localCompat\n            int K = (prog < 0.35 ? 30 : 14);\n            int bestCell = randInt(0, CELLS - 1);\n            int bestVal = localCompatCell(bestCell, rotCurr[bestCell]);\n            if (rand01() < 0.85) {\n                for (int it = 1; it < K; it++) {\n                    int c = randInt(0, CELLS - 1);\n                    int v = localCompatCell(c, rotCurr[c]);\n                    if (v > bestVal) { bestVal = v; bestCell = c; }\n                }\n            }\n            int c = (rand01() < 0.12 ? randInt(0, CELLS - 1) : bestCell);\n\n            uint8_t oldR = rotCurr[c];\n            int ls[4];\n            int mx = -1;\n            for (int r = 0; r < 4; r++) {\n                ls[r] = localCompatCell(c, (uint8_t)r);\n                mx = max(mx, ls[r]);\n            }\n\n            int thr = (T > 25000 ? 2 : (T > 9000 ? 1 : 0));\n            uint8_t cand[3];\n            int candCnt = 0;\n            for (uint8_t r = 0; r < 4; r++) if (r != oldR) {\n                if (ls[r] >= mx - thr) cand[candCnt++] = r;\n            }\n            if (candCnt == 0) {\n                for (uint8_t r = 0; r < 4; r++) if (r != oldR) cand[candCnt++] = r;\n            }\n\n            uint8_t newR;\n            double greedyProb = (T < 1200 ? 0.85 : 0.46);\n            if (rand01() < greedyProb) {\n                int bestRot = cand[0];\n                for (int i = 1; i < candCnt; i++) if (ls[cand[i]] > ls[bestRot]) bestRot = cand[i];\n                newR = (uint8_t)bestRot;\n            } else {\n                long long sumw = 0;\n                for (int i = 0; i < candCnt; i++) sumw += max(1, ls[cand[i]] + 1);\n                unsigned long long x = (unsigned long long)(rng() % (unsigned long long)sumw);\n                long long acc = 0;\n                int chosen = cand[0];\n                for (int i = 0; i < candCnt; i++) {\n                    acc += max(1, ls[cand[i]] + 1);\n                    if (x < acc) { chosen = cand[i]; break; }\n                }\n                newR = (uint8_t)chosen;\n            }\n\n            if (newR == oldR) continue;\n\n            applyRotation(c, newR);\n            EvalResult nxt = evaluateCurrent();\n            long long newScore = nxt.score;\n\n            long long delta = newScore - curScore;\n            bool accept = false;\n            if (delta >= 0) accept = true;\n            else {\n                double prob = exp((double)delta / T);\n                if (rand01() < prob) accept = true;\n            }\n\n            if (accept) {\n                curScore = newScore;\n                if (curScore > bestScore) {\n                    bestScore = curScore;\n                    memcpy(rotBest, rotCurr, CELLS);\n                    noImprove = 0;\n                } else {\n                    noImprove++;\n                }\n            } else {\n                applyRotation(c, oldR);\n                noImprove++;\n            }\n\n            if (noImprove > kickPeriod) {\n                // Kick: random re-rotations\n                int flips = 24;\n                for (int k = 0; k < flips; k++) {\n                    int cc = randInt(0, CELLS - 1);\n                    uint8_t nr = (uint8_t)randInt(0, 3);\n                    applyRotation(cc, nr);\n                }\n                cur = evaluateCurrent();\n                curScore = cur.score;\n                if (curScore > bestScore) {\n                    bestScore = curScore;\n                    memcpy(rotBest, rotCurr, CELLS);\n                }\n                noImprove = 0;\n            }\n        }\n    }\n\n    // Final intensification (fix compilation issue by not passing pointers by ref)\n    finalIntensify(0.045, 1800, bestScore);\n\n    // Output\n    string out;\n    out.reserve(CELLS);\n    for (int c = 0; c < CELLS; c++) out.push_back(char('0' + (int)rotBest[c]));\n    cout << out << \"\\n\";\n    return 0;\n}","ahc011":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct DSUFixed {\n    int M;\n    int parent[100], sz[100];\n    void init(int m) { M = m; reset(); }\n    void reset() {\n        for (int i = 0; i < M; i++) parent[i] = i, sz[i] = 1;\n    }\n    int find(int a) {\n        while (parent[a] != a) {\n            parent[a] = parent[parent[a]];\n            a = parent[a];\n        }\n        return a;\n    }\n    void unite(int a, int b) {\n        a = find(a); b = find(b);\n        if (a == b) return;\n        if (sz[a] < sz[b]) swap(a, b);\n        parent[b] = a;\n        sz[a] += sz[b];\n    }\n};\n\nstruct Evaluator {\n    int N, M;\n    DSUFixed dsu;\n    // indices for fixed adjacency pairs\n    vector<int> vertTop, vertBot;\n    vector<int> horL, horR;\n\n    // compatibility for masks 0..15\n    bool vertOk[16][16];\n    bool horOk[16][16];\n\n    int compVerts[100], compEdges[100];\n\n    Evaluator(int N_) : N(N_), M(N_ * N_) {\n        dsu.init(M);\n\n        for (int a = 0; a < 16; a++) for (int b = 0; b < 16; b++) {\n            // vertical: top needs DOWN(8), bottom needs UP(2)\n            vertOk[a][b] = ((a & 8) && (b & 2));\n            // horizontal: left needs RIGHT(4), right needs LEFT(1)\n            horOk[a][b] = ((a & 4) && (b & 1));\n        }\n\n        for (int i = 0; i < N - 1; i++) for (int j = 0; j < N; j++) {\n            int top = i * N + j;\n            int bot = (i + 1) * N + j;\n            vertTop.push_back(top);\n            vertBot.push_back(bot);\n        }\n        for (int i = 0; i < N; i++) for (int j = 0; j < N - 1; j++) {\n            int L = i * N + j;\n            int R = i * N + (j + 1);\n            horL.push_back(L);\n            horR.push_back(R);\n        }\n    }\n\n    struct Res {\n        int bestTree;     // exact largest tree component size\n        int bestFitness;  // smoother metric\n    };\n\n    Res eval(const vector<uint8_t>& b) {\n        dsu.reset();\n\n        // Build components via existing edges\n        for (size_t k = 0; k < vertTop.size(); k++) {\n            int top = vertTop[k], bot = vertBot[k];\n            uint8_t mt = b[top], mb = b[bot];\n            if (vertOk[mt][mb]) dsu.unite(top, bot);\n        }\n        for (size_t k = 0; k < horL.size(); k++) {\n            int L = horL[k], R = horR[k];\n            uint8_t mL = b[L], mR = b[R];\n            if (horOk[mL][mR]) dsu.unite(L, R);\n        }\n\n        for (int i = 0; i < M; i++) compVerts[i] = 0;\n        for (int v = 0; v < M; v++) {\n            if (b[v] == 0) continue;\n            compVerts[dsu.find(v)]++;\n        }\n        for (int i = 0; i < M; i++) compEdges[i] = 0;\n\n        // Count edges per component root\n        for (size_t k = 0; k < vertTop.size(); k++) {\n            int top = vertTop[k], bot = vertBot[k];\n            uint8_t mt = b[top], mb = b[bot];\n            if (vertOk[mt][mb]) compEdges[dsu.find(top)]++;\n        }\n        for (size_t k = 0; k < horL.size(); k++) {\n            int L = horL[k], R = horR[k];\n            uint8_t mL = b[L], mR = b[R];\n            if (horOk[mL][mR]) compEdges[dsu.find(L)]++;\n        }\n\n        int bestTree = 0;\n        int bestFitness = 0;\n        // fitness = v - extraCycles, where extra = edges - (v-1)\n        for (int r = 0; r < M; r++) {\n            int vcnt = compVerts[r];\n            if (vcnt == 0) continue;\n            int ecnt = compEdges[r];\n            int extra = ecnt - (vcnt - 1); // >= 0\n            if (extra == 0) bestTree = max(bestTree, vcnt);\n            int fitness = vcnt - extra;\n            if (fitness < 0) fitness = 0;\n            bestFitness = max(bestFitness, fitness);\n        }\n        return {bestTree, bestFitness};\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    long long T;\n    cin >> N >> T;\n\n    vector<string> s(N);\n    for (int i = 0; i < N; i++) cin >> s[i];\n\n    int M = N * N;\n    vector<uint8_t> b(M);\n    int emptyIdx = -1;\n\n    auto hexToVal = [&](char c) -> int {\n        if ('0' <= c && c <= '9') return c - '0';\n        return 10 + (c - 'a');\n    };\n\n    for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) {\n        int v = hexToVal(s[i][j]);\n        b[i * N + j] = (uint8_t)v;\n        if (v == 0) emptyIdx = i * N + j;\n    }\n\n    Evaluator evaluator(N);\n    const int FULLTREE = N * N - 1;\n\n    auto valForSelect = [&](const Evaluator::Res& r) -> int {\n        // normalized numeric value (avoid huge scaling so selection remains explorative)\n        // bestTree dominates, bestFitness refines.\n        return r.bestTree * 200 + r.bestFitness; // range ~ 0..~2e4\n    };\n\n    int dr[4] = {-1, 1, 0, 0};\n    int dc[4] = {0, 0, -1, 1};\n    char dirChar[4] = {'U', 'D', 'L', 'R'};\n    int opp[4] = {1, 0, 3, 2};\n\n    auto inBounds = [&](int r, int c) {\n        return 0 <= r && r < N && 0 <= c && c < N;\n    };\n\n    uint64_t seed = (uint64_t)chrono::steady_clock::now().time_since_epoch().count();\n    seed ^= 0x9e3779b97f4a7c15ULL * (uint64_t)N;\n    for (int i = 0; i < M; i++) seed = seed * 1315423911u + b[i] + 7;\n    seed ^= (uint64_t)emptyIdx * 1234567ULL;\n    mt19937_64 rng(seed);\n\n    auto start = chrono::steady_clock::now();\n    auto elapsedSec = [&]() -> double {\n        return chrono::duration<double>(chrono::steady_clock::now() - start).count();\n    };\n\n    int bestTreeGlobal = evaluator.eval(b).bestTree;\n    vector<char> bestMovesGlobal;\n    int bestKGlobal = (int)bestMovesGlobal.size();\n\n    const double LIMIT = 2.92;\n    const int maxRestarts = 26;\n    const int STAG = 600;\n\n    for (int restart = 0; restart < maxRestarts; restart++) {\n        if (elapsedSec() > LIMIT) break;\n\n        vector<uint8_t> curB = b;\n        int e = emptyIdx;\n        vector<char> moves;\n        moves.reserve((size_t)T);\n\n        auto curEval = evaluator.eval(curB);\n        int bestTreeRun = curEval.bestTree;\n        vector<char> bestMovesRun = moves;\n        int bestKRun = 0;\n        int stagnation = 0;\n        int prevDir = -1;\n\n        for (long long step = 0; step < T; step++) {\n            if (curEval.bestTree == FULLTREE) break;\n            if (elapsedSec() > LIMIT) break;\n            if (stagnation >= STAG) break;\n\n            int er = e / N, ec = e % N;\n\n            struct Cand {\n                int dir;\n                int nei;          // new empty index after move1\n                Evaluator::Res r1;\n                int lookVal;      // best val over move2\n            };\n\n            vector<Cand> cands;\n            cands.reserve(4);\n\n            for (int dir = 0; dir < 4; dir++) {\n                // mild anti-backtracking\n                if (prevDir != -1 && dir == opp[prevDir]) {\n                    // don't forbid; just reduce probability by skipping some\n                    if ((rng() % 10) < 7) continue;\n                }\n                int nr = er + dr[dir], nc = ec + dc[dir];\n                if (!inBounds(nr, nc)) continue;\n                int nei = nr * N + nc;\n\n                swap(curB[e], curB[nei]);\n                auto r1 = evaluator.eval(curB);\n                swap(curB[e], curB[nei]);\n\n                Cand c;\n                c.dir = dir;\n                c.nei = nei;\n                c.r1 = r1;\n                c.lookVal = valForSelect(r1); // at least move2=none\n                cands.push_back(c);\n            }\n            if (cands.empty()) break;\n\n            // 2-step lookahead: compute best val over all move2 for each move1 cand\n            for (auto& c : cands) {\n                // apply move1\n                swap(curB[e], curB[c.nei]);\n                int e1 = c.nei;\n                int r1p = e1 / N, c1p = e1 % N;\n\n                int bestLookVal = valForSelect(c.r1);\n\n                for (int dir2 = 0; dir2 < 4; dir2++) {\n                    int nr = r1p + dr[dir2], nc = c1p + dc[dir2];\n                    if (!inBounds(nr, nc)) continue;\n                    int e2 = nr * N + nc;\n\n                    swap(curB[e1], curB[e2]);\n                    auto r2 = evaluator.eval(curB);\n                    swap(curB[e1], curB[e2]);\n\n                    bestLookVal = max(bestLookVal, valForSelect(r2));\n                }\n                // undo move1\n                swap(curB[e], curB[c.nei]);\n\n                c.lookVal = bestLookVal;\n            }\n\n            int curBestTree = curEval.bestTree;\n\n            // If there is any improving 1-step bestTree, pick among them using 2-step lookVal.\n            int bestTree1 = curBestTree;\n            for (auto &c : cands) bestTree1 = max(bestTree1, c.r1.bestTree);\n\n            int chosenIdx = 0;\n            if (bestTree1 > curBestTree) {\n                // among candidates with max r1.bestTree pick max lookVal\n                int bestLook = -1;\n                for (int i = 0; i < (int)cands.size(); i++) {\n                    if (cands[i].r1.bestTree == bestTree1) {\n                        if (cands[i].lookVal > bestLook) {\n                            bestLook = cands[i].lookVal;\n                            chosenIdx = i;\n                        }\n                    }\n                }\n            } else {\n                // epsilon-greedy on lookVal to avoid too-greedy softmax\n                // eps decreases as step advances\n                double eps = 0.30 * (1.0 - (double)step / (double)T) + 0.08;\n                if (eps < 0.05) eps = 0.05;\n\n                // rank by lookVal\n                vector<int> ord(cands.size());\n                iota(ord.begin(), ord.end(), 0);\n                sort(ord.begin(), ord.end(), [&](int i, int j){\n                    if (cands[i].lookVal != cands[j].lookVal) return cands[i].lookVal > cands[j].lookVal;\n                    return cands[i].r1.bestTree > cands[j].r1.bestTree;\n                });\n\n                uniform_real_distribution<double> uni(0.0, 1.0);\n                double r01 = uni(rng);\n\n                if (r01 > eps) {\n                    chosenIdx = ord[0];\n                } else {\n                    int pickBand = min<int>(3, (int)cands.size());\n                    chosenIdx = ord[rng() % pickBand];\n                }\n            }\n\n            // execute chosen move1\n            auto ch = cands[chosenIdx];\n            swap(curB[e], curB[ch.nei]);\n            e = ch.nei;\n            moves.push_back(dirChar[ch.dir]);\n            prevDir = ch.dir;\n            curEval = ch.r1;\n\n            // update run best\n            if (curEval.bestTree > bestTreeRun) {\n                bestTreeRun = curEval.bestTree;\n                bestMovesRun = moves;\n                bestKRun = (int)moves.size();\n                stagnation = 0;\n            } else {\n                stagnation++;\n            }\n\n            // update global best (tie-break smaller K)\n            if (bestTreeRun > bestTreeGlobal) {\n                bestTreeGlobal = bestTreeRun;\n                bestMovesGlobal = bestMovesRun;\n                bestKGlobal = bestKRun;\n            } else if (bestTreeRun == bestTreeGlobal && bestKRun < bestKGlobal) {\n                bestMovesGlobal = bestMovesRun;\n                bestKGlobal = bestKRun;\n            }\n        }\n\n        if (bestTreeGlobal == FULLTREE) {\n            // can't do better on S; sometimes still improve K via more restarts, but stop for time.\n            break;\n        }\n    }\n\n    string out;\n    out.reserve(bestMovesGlobal.size());\n    for (char c : bestMovesGlobal) out.push_back(c);\n    cout << out << \"\\n\";\n    return 0;\n}","ahc012":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\n\nstatic const ll LIM = 1'000'000'000LL;\nstatic const ll CLIP_L = -LIM + 5;\nstatic const ll CLIP_R = LIM - 5;\n\nstruct Point { ll x, y; };\n\nstruct RNG {\n    uint64_t s;\n    explicit RNG(uint64_t seed) : s(seed) {}\n    static uint64_t splitmix64(uint64_t &x) {\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    ll nextLL(ll l, ll r) { // inclusive\n        return (ll)(splitmix64(s) % (uint64_t)(r - l + 1)) + l;\n    }\n    int nextInt(int l, int r) { return (int)nextLL(l, r); }\n    bool chance(int p_per_1000) { return nextInt(1, 1000) <= p_per_1000; }\n};\n\nstatic inline bool in_clip(ll v) { return CLIP_L <= v && v <= CLIP_R; }\n\n// Families: 0:x, 1:y, 2:x+y, 3:x-y\nstatic inline ll familyProj(int fam, const Point& p) {\n    if (fam == 0) return p.x;\n    if (fam == 1) return p.y;\n    if (fam == 2) return p.x + p.y;\n    return p.x - p.y; // fam==3\n}\n\nstatic void outputLineForFamily(int fam, ll C, ostream& out) {\n    // C is guaranteed within [CLIP_L, CLIP_R]\n    if (fam == 0) { // x=C\n        out << C << \" \" << -LIM << \" \" << C << \" \" << LIM << \"\\n\";\n    } else if (fam == 1) { // y=C\n        out << -LIM << \" \" << C << \" \" << LIM << \" \" << C << \"\\n\";\n    } else if (fam == 2) { // x+y=C\n        // (0,C) and (1,C-1)\n        out << 0 << \" \" << C << \" \" << 1 << \" \" << (C - 1) << \"\\n\";\n    } else { // fam==3: x-y=C\n        // (C,0) and (C+1,1)\n        out << C << \" \" << 0 << \" \" << (C + 1) << \" \" << 1 << \"\\n\";\n    }\n}\n\n// Robust choose: handles all cases (including \"gap exists but all inside occupied\" properly).\nstatic ll chooseCutBetween(\n    ll low, ll high, ll prev,\n    const unordered_set<ll>& occ,\n    RNG& rng,\n    bool allowOnPoint\n) {\n    if (low > high) swap(low, high);\n\n    auto isFree = [&](ll c) -> bool {\n        if (!in_clip(c)) return false;\n        if (allowOnPoint) return true;\n        return occ.find(c) == occ.end();\n    };\n\n    // Ensure we must return strictly > prev.\n    auto okGTprev = [&](ll c)->bool { return c > prev && in_clip(c); };\n\n    if (high - low >= 2) {\n        ll mid = (low + high) / 2;\n\n        // Prefer inside when possible.\n        // If allowOnPoint==false: require free (not equal to any projection value).\n        // If allowOnPoint==true: allow occupied too.\n        // Search near mid first.\n        int window = 1000;\n        for (int d = 0; d <= window; d++) {\n            ll c1 = mid + d;\n            if (okGTprev(c1) && low < c1 && c1 < high && isFree(c1)) return c1;\n            if (d != 0) {\n                ll c2 = mid - d;\n                if (okGTprev(c2) && low < c2 && c2 < high && isFree(c2)) return c2;\n            }\n        }\n\n        // If we couldn't find a free inside point:\n        // - if allowOnPoint: choose any inside point near mid that is > prev\n        // - otherwise: pick outside (to keep occ-free).\n        if (allowOnPoint) {\n            // choose near mid but inside\n            for (int d = 0; d <= window; d++) {\n                ll c1 = mid + d;\n                if (okGTprev(c1) && low < c1 && c1 < high) return c1;\n                if (d != 0) {\n                    ll c2 = mid - d;\n                    if (okGTprev(c2) && low < c2 && c2 < high) return c2;\n                }\n            }\n        }\n\n        // occ-free outside choice\n        ll cHigh = high + 1;\n        if (cHigh > prev && isFree(cHigh)) return cHigh;\n\n        ll cLow = low - 1;\n        if (cLow > prev && isFree(cLow)) return cLow;\n\n        // scan upward for an occ-free integer\n        ll c = max(prev + 1, CLIP_L);\n        for (int it = 0; it < 200000 && c <= CLIP_R; it++, c++) {\n            if (isFree(c)) return c;\n        }\n        // last resort\n        return min(CLIP_R, prev + 1);\n    }\n\n    // Now high==low or high==low+1\n    if (high == low) {\n        if (allowOnPoint && low > prev && isFree(low)) return low;\n        ll c = max(prev + 1, CLIP_L);\n        for (int it = 0; it < 200000 && c <= CLIP_R; it++, c++) {\n            if (isFree(c)) return c;\n        }\n        return min(CLIP_R, prev + 1);\n    }\n\n    // high == low + 1\n    if (allowOnPoint) {\n        // try low/high if ok\n        if (low > prev && isFree(low) && in_clip(low)) {\n            if (rng.chance(500)) return low;\n        }\n        if (high > prev && isFree(high) && in_clip(high)) return high;\n        if (low > prev && isFree(low) && in_clip(low)) return low;\n        return min(CLIP_R, prev + 1);\n    } else {\n        // occ-free outside\n        ll c1 = high + 1;\n        if (c1 > prev && isFree(c1)) return c1;\n\n        ll c2 = low - 1;\n        if (c2 > prev && isFree(c2)) return c2;\n\n        ll c = max(prev + 1, CLIP_L);\n        for (int it = 0; it < 200000 && c <= CLIP_R; it++, c++) {\n            if (isFree(c)) return c;\n        }\n        return min(CLIP_R, prev + 1);\n    }\n}\n\n// Generate numCuts increasing cut constants in projection space.\nstatic vector<ll> makeCutsByQuantiles(\n    const vector<ll>& sortedProj,\n    const unordered_set<ll>& occ,\n    int numCuts,\n    RNG& rng,\n    bool allowOnPoint\n) {\n    vector<ll> cuts;\n    cuts.reserve(numCuts);\n    if (numCuts == 0) return cuts;\n\n    int N = (int)sortedProj.size();\n    int cols = numCuts + 1;\n    ll prev = CLIP_L - 3;\n\n    for (int t = 1; t <= numCuts; t++) {\n        ll desiredLeft = (ll)t * N / cols;\n        int idx = (int)desiredLeft;\n        idx = max(1, min(N - 1, idx));\n\n        int off = rng.nextInt(-2, 2);\n        int idx2 = max(1, min(N - 1, idx + off));\n\n        ll low = sortedProj[idx2 - 1];\n        ll high = sortedProj[idx2];\n\n        ll c = chooseCutBetween(low, high, prev, occ, rng, allowOnPoint);\n        if (c <= prev) c = prev + 1;\n        if (!in_clip(c)) c = min(max(c, CLIP_L), CLIP_R);\n\n        if (!allowOnPoint) {\n            while (c <= CLIP_R && occ.find(c) != occ.end()) c++;\n            if (c > CLIP_R) c = prev + 1;\n            if (!in_clip(c)) c = CLIP_L;\n        }\n\n        cuts.push_back(c);\n        prev = c;\n    }\n\n    // Repair strict increasing & occ-free if disallow\n    for (int i = 1; i < (int)cuts.size(); i++) {\n        if (cuts[i] <= cuts[i - 1]) cuts[i] = cuts[i - 1] + 1;\n        if (!allowOnPoint) {\n            while (i < (int)cuts.size() && cuts[i] <= CLIP_R && occ.find(cuts[i]) != occ.end())\n                cuts[i]++;\n            if (cuts[i] > CLIP_R) {\n                // best-effort: clamp then ensure increasing\n                cuts[i] = cuts[i - 1] + 1;\n                if (cuts[i] > CLIP_R) cuts[i] = CLIP_R;\n            }\n        }\n        if (cuts[i] > CLIP_R) cuts[i] = CLIP_R;\n    }\n    // Final monotonic fix\n    for (int i = 1; i < (int)cuts.size(); i++) {\n        if (cuts[i] <= cuts[i - 1]) cuts[i] = cuts[i - 1] + 1;\n        if (cuts[i] > CLIP_R) cuts[i] = CLIP_R;\n    }\n    return cuts;\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    int A_sum = 0;\n    for (int d = 1; d <= 10; d++) {\n        cin >> a[d];\n        A_sum += a[d];\n    }\n\n    vector<Point> pts(N);\n    for (int i = 0; i < N; i++) cin >> pts[i].x >> pts[i].y;\n\n    // Precompute for 4 families:\n    const int F = 4;\n    vector<vector<ll>> proj(F, vector<ll>(N));\n    vector<vector<ll>> sortedVal(F);\n    vector<vector<int>> ord(F, vector<int>(N));\n    vector<unordered_set<ll>> occ(F);\n\n    for (int fam = 0; fam < F; fam++) {\n        occ[fam].reserve((size_t)N * 2);\n        sortedVal[fam].reserve(N);\n        for (int i = 0; i < N; i++) {\n            proj[fam][i] = familyProj(fam, pts[i]);\n            sortedVal[fam].push_back(proj[fam][i]);\n            occ[fam].insert(proj[fam][i]);\n            ord[fam][i] = i;\n        }\n        sort(sortedVal[fam].begin(), sortedVal[fam].end());\n        sort(ord[fam].begin(), ord[fam].end(), [&](int i, int j) {\n            return proj[fam][i] < proj[fam][j];\n        });\n    }\n\n    // Orientation pairs: choose two distinct families (unordered).\n    vector<pair<int,int>> orientPairs;\n    for (int A = 0; A < F; A++)\n        for (int B = A + 1; B < F; B++)\n            orientPairs.push_back({A, B}); // 6 pairs\n\n    // Proxy score for (V,H)\n    auto proxyScore = [&](int V, int H) -> long double {\n        int cells = (V + 1) * (H + 1);\n        long double lambda = (long double)N / (long double)cells;\n        if (lambda < 0.22L || lambda > 13.0L) return -1e50L;\n\n        long double p = expl(-lambda); // P(0)\n        long double proxy = 0.0L;\n        long double exp1to10 = 0.0L;\n        for (int d = 1; d <= 10; d++) {\n            p = p * lambda / (long double)d; // P(d)\n            long double expected = (long double)cells * p; // E[b_d]\n            proxy += min((long double)a[d], expected);\n            exp1to10 += expected;\n        }\n        // Penalty: align expected usable pieces with attendee count\n        long double pen = 0.30L * fabsl(exp1to10 - (long double)A_sum) / max(1.0L, (long double)A_sum);\n        // tiny reward for more cells\n        proxy += 0.001L * (long double)cells;\n        return proxy - pen;\n    };\n\n    // Timestamp-based evaluation buffers\n    int maxCells = (K + 1) * (K + 1) + 5;\n    vector<int> cnt(maxCells, 0);\n    vector<int> lastSeen(maxCells, 0);\n    int stamp = 1;\n    vector<int> touched;\n    touched.reserve(N);\n\n    auto eval2 = [&](int famA, int famB,\n                     const vector<ll>& cutsA, const vector<ll>& cutsB) -> int {\n        int V = (int)cutsA.size();\n        int H = (int)cutsB.size();\n        int cols = V + 1;\n        int rows = H + 1;\n        int cells = cols * rows;\n\n        // stamp++\n        stamp++;\n        if (stamp == INT_MAX) {\n            fill(lastSeen.begin(), lastSeen.end(), 0);\n            stamp = 1;\n        }\n\n        touched.clear();\n\n        // Compute col index or excluded (-1) for each point in ord[famA]\n        // We'll store in temporary arrays sized N.\n        // Use static vectors to avoid reallocation.\n        static vector<int> colBuf, rowBuf;\n        if ((int)colBuf.size() != N) {\n            colBuf.assign(N, 0);\n            rowBuf.assign(N, 0);\n        }\n\n        int ptr = 0;\n        for (int id : ord[famA]) {\n            ll u = proj[famA][id];\n            while (ptr < V && u > cutsA[ptr]) ptr++;\n            if (ptr < V && u == cutsA[ptr]) colBuf[id] = -1;\n            else colBuf[id] = ptr;\n        }\n\n        ptr = 0;\n        for (int id : ord[famB]) {\n            ll v = proj[famB][id];\n            while (ptr < H && v > cutsB[ptr]) ptr++;\n            if (ptr < H && v == cutsB[ptr]) rowBuf[id] = -1;\n            else rowBuf[id] = ptr;\n        }\n\n        // Fill counts\n        for (int i = 0; i < N; i++) {\n            int c = colBuf[i], r = rowBuf[i];\n            if (c < 0 || r < 0) continue;\n            int idx = c * rows + r; // < cells\n            if (lastSeen[idx] != stamp) {\n                lastSeen[idx] = stamp;\n                cnt[idx] = 1;\n                touched.push_back(idx);\n            } else {\n                cnt[idx]++;\n            }\n        }\n\n        array<int, 11> b{};\n        b.fill(0);\n        for (int idx : touched) {\n            int x = cnt[idx];\n            if (1 <= x && x <= 10) b[x]++;\n        }\n\n        int matched = 0;\n        for (int d = 1; d <= 10; d++) matched += min(a[d], b[d]);\n        return matched;\n    };\n\n    // Candidate (V,H)\n    vector<tuple<long double,int,int>> cand;\n    cand.reserve(2000);\n    for (int V = 0; V <= K; V++) {\n        for (int H = 0; H + V <= K; H++) {\n            int cells = (V + 1) * (H + 1);\n            if (cells < 1 || cells > maxCells) continue;\n            long double sc = proxyScore(V, H);\n            if (sc < -1e40L) continue;\n            cand.emplace_back(sc, V, H);\n        }\n    }\n    sort(cand.begin(), cand.end(), [&](auto &x, auto &y) { return get<0>(x) > get<0>(y); });\n    int TOP = min<int>(45, (int)cand.size());\n    if (TOP <= 0) { cand = {{0.0L, 0, 0}}; TOP = 1; }\n    cand.resize(TOP);\n\n    int bestScore = -1;\n    int bestFamA = orientPairs[0].first, bestFamB = orientPairs[0].second;\n    vector<ll> bestCutsA, bestCutsB;\n\n    uint64_t baseSeed = chrono::high_resolution_clock::now().time_since_epoch().count();\n\n    // Global randomized search\n    int RESTARTS = 6;\n    int variantsPerPair = 10;\n\n    for (int r = 0; r < RESTARTS; r++) {\n        RNG rng(baseSeed + 10000019ULL * (uint64_t)r);\n\n        for (auto [famA, famB] : orientPairs) {\n            for (auto &[ps, V, H] : cand) {\n                (void)ps;\n                for (int it = 0; it < variantsPerPair; it++) {\n                    bool allowOnPoint = (it >= variantsPerPair - 3) && rng.chance(750);\n\n                    auto cutsA = makeCutsByQuantiles(sortedVal[famA], occ[famA], V, rng, allowOnPoint);\n                    auto cutsB = makeCutsByQuantiles(sortedVal[famB], occ[famB], H, rng, allowOnPoint);\n\n                    int sc = eval2(famA, famB, cutsA, cutsB);\n                    if (sc > bestScore) {\n                        bestScore = sc;\n                        bestFamA = famA; bestFamB = famB;\n                        bestCutsA = std::move(cutsA);\n                        bestCutsB = std::move(cutsB);\n                    }\n                }\n            }\n        }\n    }\n\n    // Local search (gap-aware + informed candidates) with fast eval\n    {\n        int famA = bestFamA, famB = bestFamB;\n        vector<ll> cA = bestCutsA, cB = bestCutsB;\n        int cur = bestScore;\n\n        RNG rng(baseSeed ^ 0x9e3779b97f4a7c15ULL);\n\n        int evalBudget = 9000; // more now that eval is fast\n        int used = 0;\n\n        auto evalNow = [&](const vector<ll>& A, const vector<ll>& B)->int{\n            used++;\n            return eval2(famA, famB, A, B);\n        };\n\n        static const int deltas[] = {-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,1,2,3,4,5,6,7,8,9,10};\n\n        auto genCandidates1D = [&](const vector<ll>& sortedProj,\n                                    const unordered_set<ll>& occSet,\n                                    const vector<ll>& cuts,\n                                    int idx,\n                                    bool allowOccMove,\n                                    ll loBound, ll hiBound,\n                                    int maxRes)->vector<ll> {\n            vector<ll> res;\n            res.reserve(32);\n\n            ll curc = cuts[idx];\n\n            int pos = (int)(lower_bound(sortedProj.begin(), sortedProj.end(), curc) - sortedProj.begin());\n            ll low = (pos == 0 ? sortedProj[0] : sortedProj[pos - 1]);\n            ll high = (pos >= (int)sortedProj.size() ? sortedProj.back() : sortedProj[pos]);\n\n            auto add = [&](ll x){\n                if (x < loBound || x > hiBound) return;\n                if (!allowOccMove && occSet.find(x) != occSet.end()) return;\n                res.push_back(x);\n            };\n\n            // gap-aware\n            if (high - low >= 2) {\n                ll mid = (low + high) / 2;\n                add(low + 1);\n                add(mid);\n                add(high - 1);\n                add(mid - 1);\n                add(mid + 1);\n            } else {\n                add(low);\n                add(high);\n            }\n\n            // neighborhood around current cut\n            for (int d : deltas) add(curc + d);\n\n            // boundaries (often useful)\n            add(loBound);\n            add(hiBound);\n\n            sort(res.begin(), res.end());\n            res.erase(unique(res.begin(), res.end()), res.end());\n            if ((int)res.size() > maxRes) res.resize(maxRes);\n            return res;\n        };\n\n        int iters = 2600;\n        for (int it = 0; it < iters && used < evalBudget; it++) {\n            bool moveA = rng.chance(520);\n            bool allowOccMove = rng.chance(250); // sometimes allow touching occ values\n\n            if (moveA) {\n                int V = (int)cA.size();\n                if (V == 0) continue;\n                int idx = rng.nextInt(0, V - 1);\n\n                ll lo = (idx == 0 ? CLIP_L : cA[idx - 1] + 1);\n                ll hi = (idx + 1 == V ? CLIP_R : cA[idx + 1] - 1);\n                if (lo > hi) continue;\n\n                auto candVals = genCandidates1D(sortedVal[famA], occ[famA], cA, idx,\n                                                allowOccMove, lo, hi, 14);\n\n                ll old = cA[idx];\n                int bestLocal = cur;\n                ll bestVal = old;\n\n                for (ll x : candVals) {\n                    if (used >= evalBudget) break;\n                    if (x == old) continue;\n                    cA[idx] = x;\n                    int ns = evalNow(cA, cB);\n                    if (ns > bestLocal) { bestLocal = ns; bestVal = x; }\n                }\n                cA[idx] = bestVal;\n                if (bestLocal > cur) cur = bestLocal;\n            } else {\n                int H = (int)cB.size();\n                if (H == 0) continue;\n                int idx = rng.nextInt(0, H - 1);\n\n                ll lo = (idx == 0 ? CLIP_L : cB[idx - 1] + 1);\n                ll hi = (idx + 1 == H ? CLIP_R : cB[idx + 1] - 1);\n                if (lo > hi) continue;\n\n                auto candVals = genCandidates1D(sortedVal[famB], occ[famB], cB, idx,\n                                                allowOccMove, lo, hi, 14);\n\n                ll old = cB[idx];\n                int bestLocal = cur;\n                ll bestVal = old;\n\n                for (ll x : candVals) {\n                    if (used >= evalBudget) break;\n                    if (x == old) continue;\n                    cB[idx] = x;\n                    int ns = evalNow(cA, cB);\n                    if (ns > bestLocal) { bestLocal = ns; bestVal = x; }\n                }\n                cB[idx] = bestVal;\n                if (bestLocal > cur) cur = bestLocal;\n            }\n        }\n\n        // Final save\n        bestScore = cur;\n        bestFamA = famA; bestFamB = famB;\n        bestCutsA = std::move(cA);\n        bestCutsB = std::move(cB);\n    }\n\n    int k = (int)bestCutsA.size() + (int)bestCutsB.size();\n    if (k > K) { // safety\n        cout << 0 << \"\\n\";\n        return 0;\n    }\n\n    cout << k << \"\\n\";\n    for (ll C : bestCutsA) outputLineForFamily(bestFamA, C, cout);\n    for (ll C : bestCutsB) outputLineForFamily(bestFamB, C, cout);\n    return 0;\n}","ahc014":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing u8 = uint8_t;\nusing u16 = uint16_t;\n\nstatic inline int VID(int N, int x, int y) { return x * N + y; }\n\nstruct Edge {\n    // kind: 0=H, 1=V, 2=D1 (slope +1), 3=DM (slope -1)\n    u8 kind, a, b;\n};\n\nstruct Rect {\n    array<u16, 4> v{};\n    static constexpr int MAXE = 56;\n    static constexpr int MAXM = 48;\n    Edge edges[MAXE];\n    u8 eLen = 0;\n    u16 mids[MAXM];\n    u8 mLen = 0;\n};\n\nstruct Candidate {\n    long long key;\n    int rid;\n    bool operator<(Candidate const& o) const { return key < o.key; } // max-heap\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    int N, M;\n    cin >> N >> M;\n    vector<char> initDot(N * N, 0);\n    for (int i = 0; i < M; i++) {\n        int x, y;\n        cin >> x >> y;\n        initDot[VID(N, x, y)] = 1;\n    }\n\n    // weights\n    int c = (N - 1) / 2;\n    vector<long long> weight(N * N, 0);\n    long long baseSum = 0;\n    for (int x = 0; x < N; x++) for (int y = 0; y < N; y++) {\n        long long dx = x - c, dy = y - c;\n        long long w = dx * dx + dy * dy + 1;\n        weight[VID(N, x, y)] = w;\n        if (initDot[VID(N, x, y)]) baseSum += w;\n    }\n\n    // rectangle family sizes\n    const int LAX = 13, LDI = 13;\n\n    // Precompute rectangles\n    vector<Rect> rects;\n    rects.reserve(1000000);\n\n    auto addAxisRect = [&](int x, int y, int dx, int dy) {\n        Rect r;\n        r.v = { (u16)VID(N, x, y),\n                (u16)VID(N, x + dx, y),\n                (u16)VID(N, x + dx, y + dy),\n                (u16)VID(N, x, y + dy) };\n        r.eLen = 0;\n        r.mLen = 0;\n\n        // bottom & top horizontal unit edges\n        for (int t = 0; t < dx; t++) r.edges[r.eLen++] = Edge{0, (u8)(x + t), (u8)y};\n        for (int t = 0; t < dx; t++) r.edges[r.eLen++] = Edge{0, (u8)(x + t), (u8)(y + dy)};\n\n        // left & right vertical unit edges\n        for (int t = 0; t < dy; t++) r.edges[r.eLen++] = Edge{1, (u8)x, (u8)(y + t)};\n        for (int t = 0; t < dy; t++) r.edges[r.eLen++] = Edge{1, (u8)(x + dx), (u8)(y + t)};\n\n        // midpoints on perimeter excluding corners\n        for (int t = 1; t < dx; t++) {\n            r.mids[r.mLen++] = (u16)VID(N, x + t, y);\n            r.mids[r.mLen++] = (u16)VID(N, x + t, y + dy);\n        }\n        for (int t = 1; t < dy; t++) {\n            r.mids[r.mLen++] = (u16)VID(N, x, y + t);\n            r.mids[r.mLen++] = (u16)VID(N, x + dx, y + t);\n        }\n\n        rects.push_back(r);\n    };\n\n    for (int dx = 1; dx <= LAX; dx++) for (int dy = 1; dy <= LAX; dy++) {\n        for (int x = 0; x + dx < N; x++) {\n            for (int y = 0; y + dy < N; y++) addAxisRect(x, y, dx, dy);\n        }\n    }\n\n    auto addDiagRect = [&](int x, int y, int a, int b) {\n        // A=(x,y)\n        // B=(x+a,y+a)\n        // C=(x+a+b,y+a-b)\n        // D=(x+b,y-b)\n        Rect r;\n        r.v = { (u16)VID(N, x, y),\n                (u16)VID(N, x + a, y + a),\n                (u16)VID(N, x + a + b, y + a - b),\n                (u16)VID(N, x + b, y - b) };\n        r.eLen = 0;\n        r.mLen = 0;\n\n        // A->B: D1 edges kind=2\n        for (int t = 0; t < a; t++) r.edges[r.eLen++] = Edge{2, (u8)(x + t), (u8)(y + t)};\n\n        // B->C: DM edges kind=3 encoded by lower endpoint:\n        // (x+a+t, y+a-t) -> (x+a+t+1, y+a-t-1), lower endpoint is (x+a+t, y+a-t-1)\n        for (int t = 0; t < b; t++) {\n            r.edges[r.eLen++] = Edge{3, (u8)(x + a + t), (u8)(y + a - t - 1)};\n        }\n\n        // C->D: D1 edges (reverse)\n        for (int t = 0; t < a; t++) {\n            r.edges[r.eLen++] = Edge{2, (u8)(x + b + t), (u8)(y - b + t)};\n        }\n\n        // D->A: DM edges\n        for (int t = 0; t < b; t++) {\n            r.edges[r.eLen++] = Edge{3, (u8)(x + t), (u8)(y - t - 1)};\n        }\n\n        // mids\n        for (int t = 1; t < a; t++) r.mids[r.mLen++] = (u16)VID(N, x + t, y + t);\n        for (int t = 1; t < b; t++) r.mids[r.mLen++] = (u16)VID(N, x + a + t, y + a - t);\n        for (int t = 1; t < a; t++) r.mids[r.mLen++] = (u16)VID(N, x + b + t, y - b + t);\n        for (int t = 1; t < b; t++) r.mids[r.mLen++] = (u16)VID(N, x + t, y - t);\n\n        rects.push_back(r);\n    };\n\n    for (int a = 1; a <= LDI; a++) {\n        for (int b = 1; b <= LDI; b++) {\n            for (int x = 0; x + a + b < N; x++) {\n                for (int y = b; y + a < N; y++) addDiagRect(x, y, a, b);\n            }\n        }\n    }\n\n    int R = (int)rects.size();\n\n    // adjacency: vertex -> rectangles where vertex is corner/mid\n    vector<vector<int>> adjCorner(N * N), adjMid(N * N);\n    for (int rid = 0; rid < R; rid++) {\n        for (int k = 0; k < 4; k++) adjCorner[rects[rid].v[k]].push_back(rid);\n        for (int i = 0; i < rects[rid].mLen; i++) adjMid[rects[rid].mids[i]].push_back(rid);\n    }\n\n    // unit edge indexing and edge->rect mapping\n    int cntH = (N - 1) * N;\n    int cntV = N * (N - 1);\n    int cntD = (N - 1) * (N - 1);\n    int baseV = cntH;\n    int baseD1 = baseV + cntV;\n    int baseD2 = baseD1 + cntD;\n    int totalEdges = baseD2 + cntD;\n\n    auto edgeIndex = [&](const Edge& e) -> int {\n        if (e.kind == 0) return (int)e.a * N + (int)e.b;                 // H: a in [0..N-2], b in [0..N-1]\n        if (e.kind == 1) return baseV + (int)e.a * (N - 1) + (int)e.b;   // V\n        if (e.kind == 2) return baseD1 + (int)e.a * (N - 1) + (int)e.b;  // D1\n        return baseD2 + (int)e.a * (N - 1) + (int)e.b;                  // DM\n    };\n\n    vector<vector<int>> edgeToRects(totalEdges);\n    for (int rid = 0; rid < R; rid++) {\n        const Rect& rc = rects[rid];\n        for (int i = 0; i < rc.eLen; i++) {\n            int ei = edgeIndex(rc.edges[i]);\n            edgeToRects[ei].push_back(rid);\n        }\n    }\n\n    // init cnt / midCnt\n    vector<int> initCnt(R, 0), initMidCnt(R, 0);\n    for (int rid = 0; rid < R; rid++) {\n        int s = 0;\n        for (int k = 0; k < 4; k++) s += initDot[rects[rid].v[k]] ? 1 : 0;\n        initCnt[rid] = s;\n\n        int sm = 0;\n        for (int i = 0; i < rects[rid].mLen; i++) sm += initDot[rects[rid].mids[i]] ? 1 : 0;\n        initMidCnt[rid] = sm;\n    }\n\n    const int JITTER_MASK = 15; // 0..15\n\n    auto runTrial = [&](long long lambda, uint64_t seed, bool recordOps)\n        -> pair<long long, vector<array<u16,4>>> {\n\n        vector<char> dot = initDot;\n        vector<int> cnt = initCnt;\n        vector<int> midCnt = initMidCnt;\n\n        vector<u8> usedRect(R, 0);\n        vector<u8> conflictFlag(R, 0);\n\n        // xorshift RNG for jitter\n        uint64_t rng = seed ? seed : 88172645463325252ULL;\n        auto nextJitter = [&]() -> long long {\n            rng ^= rng << 7;\n            rng ^= rng >> 9;\n            return (long long)(rng & JITTER_MASK); // 0..15\n        };\n\n        priority_queue<Candidate> pq;\n        vector<array<u16,4>> ops;\n        if (recordOps) ops.reserve(140000);\n\n        vector<int> potBuf;\n        potBuf.reserve(64);\n\n        vector<int> mark(R, 0), seen(R, 0);\n        int curMark = 1, curSeen = 1;\n\n        auto findMissingCorner = [&](int rid) -> int {\n            const Rect& rc = rects[rid];\n            for (int k = 0; k < 4; k++) if (!dot[rc.v[k]]) return k;\n            return -1;\n        };\n\n        auto applyRect = [&](int rid) {\n            usedRect[rid] = 1;\n            const Rect& rc = rects[rid];\n            for (int i = 0; i < rc.eLen; i++) {\n                int ei = edgeIndex(rc.edges[i]);\n                for (int rr : edgeToRects[ei]) {\n                    if (usedRect[rr]) continue;\n                    conflictFlag[rr] = 1;\n                }\n            }\n        };\n\n        auto computeKeyAndPush = [&](int rid) {\n            if (usedRect[rid]) return;\n            if (cnt[rid] != 3) return;\n            if (midCnt[rid] != 0) return;\n            if (conflictFlag[rid]) return;\n\n            int missIdx = findMissingCorner(rid);\n            if (missIdx < 0) return;\n            int u = rects[rid].v[missIdx];\n\n            long long jitter = nextJitter();\n\n            if (lambda == 0) {\n                pq.push(Candidate{weight[u] + jitter, rid});\n                return;\n            }\n\n            // potential rectangles: adjacent via corner u with cnt==2, midCnt==0, no conflict\n            potBuf.clear();\n            for (int rr : adjCorner[u]) {\n                if (usedRect[rr]) continue;\n                if (cnt[rr] != 2) continue;\n                if (midCnt[rr] != 0) continue;\n                if (conflictFlag[rr]) continue;\n                potBuf.push_back(rr);\n            }\n            long long potential = (long long)potBuf.size();\n            if (potential == 0) {\n                pq.push(Candidate{weight[u] + jitter, rid});\n                return;\n            }\n\n            // loss: distinct potential rectangles that share any unit edge with current rectangle\n            if (++curMark == INT_MAX) {\n                fill(mark.begin(), mark.end(), 0);\n                curMark = 1;\n            }\n            for (int rr : potBuf) mark[rr] = curMark;\n\n            if (++curSeen == INT_MAX) {\n                fill(seen.begin(), seen.end(), 0);\n                curSeen = 1;\n            }\n\n            long long loss = 0;\n            const Rect& rc = rects[rid];\n            for (int i = 0; i < rc.eLen; i++) {\n                int ei = edgeIndex(rc.edges[i]);\n                for (int rr2 : edgeToRects[ei]) {\n                    if (mark[rr2] != curMark) continue;\n                    if (seen[rr2] == curSeen) continue;\n                    seen[rr2] = curSeen;\n                    loss++;\n                }\n            }\n\n            long long effectivePotential = potential - loss;\n            long long key = weight[u] + lambda * effectivePotential + jitter;\n            pq.push(Candidate{key, rid});\n        };\n\n        for (int rid = 0; rid < R; rid++) {\n            if (initCnt[rid] == 3 && initMidCnt[rid] == 0) computeKeyAndPush(rid);\n        }\n\n        long long sumW = baseSum;\n\n        while (!pq.empty()) {\n            auto cur = pq.top();\n            pq.pop();\n            int rid = cur.rid;\n\n            if (usedRect[rid]) continue;\n            if (cnt[rid] != 3 || midCnt[rid] != 0) continue;\n            if (conflictFlag[rid]) continue;\n\n            int missIdx = findMissingCorner(rid);\n            if (missIdx < 0) continue;\n            int u = rects[rid].v[missIdx];\n\n            applyRect(rid);\n            dot[u] = 1;\n            sumW += weight[u];\n\n            if (recordOps) {\n                const Rect& rc = rects[rid];\n                array<u16,4> op{};\n                for (int t = 0; t < 4; t++) op[t] = rc.v[(missIdx + t) % 4]; // p1 is missing corner\n                ops.push_back(op);\n            }\n\n            // update corner cnt\n            for (int rr : adjCorner[u]) {\n                if (usedRect[rr]) continue;\n                cnt[rr]++;\n                if (cnt[rr] == 3) computeKeyAndPush(rr);\n            }\n            // update midpoint count\n            for (int rr : adjMid[u]) {\n                if (usedRect[rr]) continue;\n                midCnt[rr]++;\n            }\n        }\n\n        return {sumW, std::move(ops)};\n    };\n\n    // Two-stage lambda selection\n    vector<long long> lambdas = {0, 3, 6, 9, 12, 15};\n    int stage1Trials = 2;\n    int stage2Trials = 10; // only for top-2 lambdas\n\n    uint64_t seedBase = splitmix64((uint64_t)N * 10000019ULL ^ (uint64_t)M * 9176ULL ^ 0x9e3779b97f4a7c15ULL);\n\n    struct BestCand { long long sum; long long lam; uint64_t seed; };\n    vector<BestCand> bests;\n    bests.reserve(lambdas.size());\n\n    for (long long lam : lambdas) {\n        long long bestSumLam = -1;\n        uint64_t bestSeedLam = seedBase;\n        for (int t = 0; t < stage1Trials; t++) {\n            uint64_t seed = splitmix64(seedBase + (uint64_t)lam * 1009ULL + (uint64_t)t * 9171ULL);\n            auto [s, _ops] = runTrial(lam, seed, false);\n            if (s > bestSumLam) {\n                bestSumLam = s;\n                bestSeedLam = seed;\n            }\n        }\n        bests.push_back({bestSumLam, lam, bestSeedLam});\n    }\n\n    sort(bests.begin(), bests.end(), [](const BestCand& a, const BestCand& b) {\n        return a.sum > b.sum;\n    });\n\n    // pick top-2 lambdas\n    BestCand first = bests[0];\n    BestCand second = bests[1];\n\n    long long bestSum = first.sum;\n    long long bestLam = first.lam;\n    uint64_t bestSeed = first.seed;\n\n    // stage2 refine both\n    for (int which = 0; which < 2; which++) {\n        long long lam = (which == 0 ? first.lam : second.lam);\n        for (int t = 0; t < stage2Trials; t++) {\n            uint64_t seed = splitmix64(seedBase + (uint64_t)lam * 1000003ULL + (uint64_t)which * 12345ULL + (uint64_t)t * 54321ULL);\n            auto [s, _ops] = runTrial(lam, seed, false);\n            if (s > bestSum) {\n                bestSum = s;\n                bestLam = lam;\n                bestSeed = seed;\n            }\n        }\n    }\n\n    auto [finalSum, ops] = runTrial(bestLam, bestSeed, true);\n\n    cout << ops.size() << \"\\n\";\n    for (auto &op : ops) {\n        for (int t = 0; t < 4; t++) {\n            int vid = (int)op[t];\n            int x = vid / N;\n            int y = vid % N;\n            cout << x << \" \" << y << (t == 3 ? '\\n' : ' ');\n        }\n    }\n    return 0;\n}","ahc015":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct State {\n    array<uint8_t, 100> a{};\n};\n\nstatic inline int id(int r, int c) { return r * 10 + c; }\n\n// Undirected adjacency edges for DSU calcNumerator\nstatic vector<pair<int,int>> edges;\n\n// DSU with on-demand initialization (timestamp-based) to speed calcNumerator\nstatic int parentUF[100], szUF[100], stampUF[100];\nstatic int curUFStamp = 0;\n\nstatic inline void uf_touch(int x) {\n    if (stampUF[x] != curUFStamp) {\n        stampUF[x] = curUFStamp;\n        parentUF[x] = x;\n        szUF[x] = 1;\n    }\n}\nstatic inline int uf_find(int x) {\n    uf_touch(x);\n    while (parentUF[x] != x) {\n        parentUF[x] = parentUF[parentUF[x]];\n        x = parentUF[x];\n    }\n    return x;\n}\nstatic inline void uf_union(int x, int y) {\n    x = uf_find(x);\n    y = uf_find(y);\n    if (x == y) return;\n    if (szUF[x] < szUF[y]) swap(x, y);\n    parentUF[y] = x;\n    szUF[x] += szUF[y];\n}\n\nstatic State tilt(const State& s, int dir) {\n    // dir: 0=F(up), 1=B(down), 2=L(left), 3=R(right)\n    State t;\n    t.a.fill(0);\n\n    if (dir == 0) { // F: r -> 0\n        for (int c = 0; c < 10; c++) {\n            int k = 0;\n            for (int r = 0; r < 10; r++) {\n                uint8_t v = s.a[id(r, c)];\n                if (v) t.a[id(k++, c)] = v;\n            }\n        }\n    } else if (dir == 1) { // B: r -> 9\n        for (int c = 0; c < 10; c++) {\n            int k = 9;\n            for (int r = 9; r >= 0; r--) {\n                uint8_t v = s.a[id(r, c)];\n                if (v) t.a[id(k--, c)] = v;\n            }\n        }\n    } else if (dir == 2) { // L: c -> 0\n        for (int r = 0; r < 10; r++) {\n            int k = 0;\n            for (int c = 0; c < 10; c++) {\n                uint8_t v = s.a[id(r, c)];\n                if (v) t.a[id(r, k++)] = v;\n            }\n        }\n    } else { // R: c -> 9\n        for (int r = 0; r < 10; r++) {\n            int k = 9;\n            for (int c = 9; c >= 0; c--) {\n                uint8_t v = s.a[id(r, c)];\n                if (v) t.a[id(r, k--)] = v;\n            }\n        }\n    }\n    return t;\n}\n\n// numerator = sum of (component size)^2 for same-flavor 4-neighbor components\nstatic inline long long calcNumerator(const State& s) {\n    ++curUFStamp;\n    // avoid overflow issues in extremely long runs (not relevant here, but safe)\n    if (curUFStamp == INT_MAX) {\n        curUFStamp = 1;\n        fill(begin(stampUF), end(stampUF), 0);\n    }\n\n    for (auto [u, v] : edges) {\n        uint8_t fu = s.a[u];\n        if (fu == 0) continue;\n        if (fu == s.a[v]) uf_union(u, v);\n    }\n\n    static int seenRoot[100];\n    static int stampSeen[100];\n    static int curSeen = 0;\n    ++curSeen;\n\n    long long sum = 0;\n    for (int i = 0; i < 100; i++) {\n        uint8_t fi = s.a[i];\n        if (fi == 0) continue;\n        int r = uf_find(i);\n        if (stampSeen[r] == curSeen) continue;\n        stampSeen[r] = curSeen;\n        long long csz = szUF[r];\n        sum += csz * csz;\n    }\n    return sum;\n}\n\nstatic inline int getEmpties(const State& s, int cells[100]) {\n    int sz = 0;\n    for (int i = 0; i < 100; i++) if (s.a[i] == 0) cells[sz++] = i;\n    return sz;\n}\n\nstatic int findCellByPT(const State& g, int p) {\n    int cnt = 0;\n    for (int i = 0; i < 100; i++) if (g.a[i] == 0) {\n        cnt++;\n        if (cnt == p) return i;\n    }\n    return -1;\n}\n\nstatic inline void sampleK_inplace(int cells[100], int sz, int K, mt19937_64& rng) {\n    for (int i = 0; i < K; i++) {\n        int j = i + (int)(rng() % (unsigned long long)(sz - i));\n        swap(cells[i], cells[j]);\n    }\n}\n\nstatic vector<int> F; // 1..100\n\n// Exact expectimax (used for t>=95)\nstatic double solveExactValue(const State& s, int k);\n\nstatic int chooseDirExact(const State& s, int k);\n\nstatic double solveExactValue(const State& s, int k) {\n    if (k == 100) return (double)calcNumerator(s);\n\n    uint8_t nextFlavor = (uint8_t)F[k + 1];\n    double best = -1e100;\n\n    for (int dir = 0; dir < 4; dir++) {\n        State s1 = tilt(s, dir);\n        int cells[100];\n        int E = getEmpties(s1, cells);\n\n        double sum = 0.0;\n        for (int i = 0; i < E; i++) {\n            State s2 = s1;\n            s2.a[cells[i]] = nextFlavor;\n            sum += solveExactValue(s2, k + 1);\n        }\n        best = max(best, sum / (double)E);\n    }\n    return best;\n}\n\nstatic int chooseDirExact(const State& s, int k) {\n    (void)k;\n    uint8_t nextFlavor = (uint8_t)F[k + 1];\n    (void)nextFlavor;\n\n    int bestDir = 0;\n    double bestVal = -1e100;\n\n    for (int dir = 0; dir < 4; dir++) {\n        State s1 = tilt(s, dir);\n        int cells[100];\n        int E = getEmpties(s1, cells);\n\n        double sum = 0.0;\n        for (int i = 0; i < E; i++) {\n            State s2 = s1;\n            s2.a[cells[i]] = (uint8_t)F[k + 1];\n            sum += solveExactValue(s2, k + 1);\n        }\n        double val = sum / (double)E;\n        if (val > bestVal) {\n            bestVal = val;\n            bestDir = dir;\n        }\n    }\n    return bestDir;\n}\n\n// Exact evaluation for a fixed first tilt direction at time k:\n// choose dir0 at time k, then place next candy randomly, then continue optimally.\nstatic double evalFixedDirExactFirst(const State& s, int k, int dir0) {\n    uint8_t nextFlavor = (uint8_t)F[k + 1];\n    State s1 = tilt(s, dir0);\n\n    int cells[100];\n    int E = getEmpties(s1, cells);\n\n    double sum = 0.0;\n    for (int i = 0; i < E; i++) {\n        State s2 = s1;\n        s2.a[cells[i]] = nextFlavor;\n        sum += solveExactValue(s2, k + 1);\n    }\n    return sum / (double)E;\n}\n\n// Fast stochastic depth-2 heuristic for earlier times\nstatic double estimateDepth2(const State& s0, int t, mt19937_64& rng) {\n    uint8_t f1 = (uint8_t)F[t + 1];\n    uint8_t f2 = (uint8_t)F[t + 2];\n\n    int cells1[100];\n    int E1 = getEmpties(s0, cells1);\n    if (E1 == 0) return (double)calcNumerator(s0);\n\n    int K1;\n    if (E1 <= 12) K1 = E1;\n    else if (E1 <= 35) K1 = 10;\n    else K1 = 8;\n\n    K1 = min(K1, E1);\n    sampleK_inplace(cells1, E1, K1, rng);\n\n    long double total = 0.0L;\n\n    for (int i1 = 0; i1 < K1; i1++) {\n        int c1 = cells1[i1];\n        State s1 = s0;\n        s1.a[c1] = f1;\n\n        long double bestExpDir1 = -1e100L;\n\n        for (int dir1 = 0; dir1 < 4; dir1++) {\n            State t1 = tilt(s1, dir1);\n\n            int cells2[100];\n            int E2 = getEmpties(t1, cells2);\n            if (E2 == 0) {\n                bestExpDir1 = max(bestExpDir1, (long double)calcNumerator(t1));\n                continue;\n            }\n\n            int K2;\n            if (E2 <= 12) K2 = E2;\n            else if (E2 <= 35) K2 = 5;\n            else K2 = 3;\n\n            K2 = min(K2, E2);\n            sampleK_inplace(cells2, E2, K2, rng);\n\n            long double sum2 = 0.0L;\n            for (int i2 = 0; i2 < K2; i2++) {\n                int c2 = cells2[i2];\n                State s2 = t1;\n                s2.a[c2] = f2;\n\n                long long bestNum2 = -1;\n                for (int dir2 = 0; dir2 < 4; dir2++) {\n                    State t2 = tilt(s2, dir2);\n                    bestNum2 = max(bestNum2, calcNumerator(t2));\n                }\n                sum2 += (long double)bestNum2;\n            }\n\n            bestExpDir1 = max(bestExpDir1, sum2 / (long double)K2);\n        }\n\n        total += bestExpDir1;\n    }\n\n    return (double)(total / (long double)K1);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // Precompute edges for DSU\n    edges.clear();\n    edges.reserve(180);\n    for (int r = 0; r < 10; r++) for (int c = 0; c < 10; c++) {\n        int u = id(r, c);\n        if (r + 1 < 10) edges.push_back({u, id(r + 1, c)});\n        if (c + 1 < 10) edges.push_back({u, id(r, c + 1)});\n    }\n\n    F.assign(101, 0);\n    for (int i = 1; i <= 100; i++) cin >> F[i];\n\n    // Initialize DSU stamps arrays\n    fill(begin(stampUF), end(stampUF), 0);\n\n    State g;\n    g.a.fill(0);\n\n    const char dirChar[4] = {'F', 'B', 'L', 'R'};\n\n    uint64_t seed = 0x9e3779b97f4a7c15ULL;\n    for (int i = 1; i <= 100; i++) seed = seed * 1315423911u + (uint64_t)F[i] + i;\n    mt19937_64 rng(seed);\n\n    for (int t = 1; t <= 100; t++) {\n        int p;\n        cin >> p;\n\n        int cell = findCellByPT(g, p);\n        g.a[cell] = (uint8_t)F[t];\n\n        if (t == 100) break;\n\n        int bestDir = 0;\n\n        if (t >= 95) {\n            bestDir = chooseDirExact(g, t);\n        } else if (t == 94) {\n            // Exact only for top-2 directions (by fast heuristic) to avoid TLE\n            double quick[4];\n            for (int d = 0; d < 4; d++) {\n                State s0 = tilt(g, d);\n                quick[d] = estimateDepth2(s0, t, rng);\n            }\n\n            int d1 = 0, d2 = 1;\n            if (quick[d2] > quick[d1]) swap(d1, d2);\n            if (quick[2] > quick[d1]) { d2 = d1; d1 = 2; }\n            else if (quick[2] > quick[d2]) d2 = 2;\n            if (quick[3] > quick[d1]) { d2 = d1; d1 = 3; }\n            else if (quick[3] > quick[d2]) d2 = 3;\n\n            // Evaluate exact for d1 and d2\n            double val[4];\n            for (int d = 0; d < 4; d++) val[d] = quick[d];\n            val[d1] = evalFixedDirExactFirst(g, t, d1);\n            val[d2] = evalFixedDirExactFirst(g, t, d2);\n\n            bestDir = 0;\n            for (int d = 1; d < 4; d++) if (val[d] > val[bestDir]) bestDir = d;\n        } else {\n            double bestVal = -1e100;\n            for (int dir0 = 0; dir0 < 4; dir0++) {\n                State s0 = tilt(g, dir0);\n                double val = estimateDepth2(s0, t, rng);\n                if (val > bestVal) {\n                    bestVal = val;\n                    bestDir = dir0;\n                }\n            }\n        }\n\n        g = tilt(g, bestDir);\n        cout << dirChar[bestDir] << \"\\n\" << flush;\n    }\n\n    return 0;\n}","ahc016":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic inline int popcnt_u64(uint64_t x) { return __builtin_popcountll(x); }\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\n// L1 distance between count-multisets from sorted arrays (exact)\nstatic inline int multisetL1_sorted(const vector<uint64_t>& a, const vector<uint64_t>& b) {\n    int i = 0, j = 0;\n    int common = 0;\n    while (i < (int)a.size() && j < (int)b.size()) {\n        if (a[i] == b[j]) {\n            uint64_t x = a[i];\n            int i2 = i;\n            while (i2 < (int)a.size() && a[i2] == x) i2++;\n            int j2 = j;\n            while (j2 < (int)b.size() && b[j2] == x) j2++;\n            common += min(i2 - i, j2 - j);\n            i = i2; j = j2;\n        } else if (a[i] < b[j]) {\n            i++;\n        } else {\n            j++;\n        }\n    }\n    return (int)a.size() + (int)b.size() - 2 * common;\n}\n\nstruct Invariants {\n    int edges = 0;\n    long long twoStars = 0;\n    long long triangles = 0;\n};\n\nstruct Sig {\n    vector<uint64_t> vKeys; // size N, sorted\n    vector<uint64_t> eKeys; // size = #edges, sorted (edge keys depending on eps)\n    Invariants inv;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int M;\n    double epsInput;\n    cin >> M >> epsInput;\n    double eps = epsInput;\n\n    // More conservative N schedule to reduce catastrophic noise sensitivity\n    int N;\n    if (eps <= 0.10) N = 28;\n    else if (eps <= 0.18) N = 26;\n    else if (eps <= 0.26) N = 24;\n    else if (eps <= 0.34) N = 22;\n    else N = 20;\n    N = max(4, min(63, N)); // use uint64 adjacency rows\n\n    int T = N * (N - 1) / 2;\n\n    // maskGT[i] bitset of {j | j > i}\n    vector<uint64_t> maskGT(N, 0ULL);\n    for (int i = 0; i < N; i++) {\n        uint64_t m = 0ULL;\n        for (int j = i + 1; j < N; j++) m |= (1ULL << j);\n        maskGT[i] = m;\n    }\n\n    // Edge CN usage: keep it only when noise is not too large.\n    // (Less fragile than extra edge-set moments.)\n    bool useCN = (eps <= 0.22);\n\n    // Vertex keys: (deg, neighDegSum, neighDegSqSum)\n    // Exact packing within safe ranges for N<=63.\n    // deg: 0..62 fits 6 bits\n    // neighSum: sum of <=62 degrees each <=62 => <=3844 fits ~12 bits\n    // neighSqSum: sum of <=62 squares each <=62^2=3844 => <=~238k fits 18 bits\n    auto vKey = [&](int deg, int neighSum, int neighSqSum) -> uint64_t {\n        // pack into [0..6)+[6..18)+[18..36)\n        return (uint64_t)(uint32_t)deg\n             | ((uint64_t)(uint32_t)neighSum << 6)\n             | ((uint64_t)(uint32_t)neighSqSum << 18);\n    };\n\n    // Edge base key: (minDeg, maxDeg)\n    // deg<=62 fits 6 bits each => 12 bits total\n    auto eBaseKey = [&](int d1, int d2) -> uint64_t {\n        if (d1 > d2) swap(d1, d2);\n        return (uint64_t)(uint32_t)d1 | ((uint64_t)(uint32_t)d2 << 6);\n    };\n\n    // Full edge key: base + cn (cn<=62) into next bits\n    auto eFullKey = [&](int d1, int d2, int cn) -> uint64_t {\n        uint64_t base = eBaseKey(d1, d2);\n        return base | ((uint64_t)(uint32_t)cn << 12);\n    };\n\n    auto parseGraphBits = [&](const string& H) -> vector<uint64_t> {\n        vector<uint64_t> adj(N, 0ULL);\n        int idx = 0;\n        for (int i = 0; i < N; i++) {\n            for (int j = i + 1; j < N; j++) {\n                if (H[idx++] == '1') {\n                    adj[i] |= (1ULL << j);\n                    adj[j] |= (1ULL << i);\n                }\n            }\n        }\n        return adj;\n    };\n\n    auto encodeGraphBits = [&](const vector<uint64_t>& adj) -> string {\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                s.push_back(((adj[i] >> j) & 1ULL) ? '1' : '0');\n            }\n        }\n        return s;\n    };\n\n    auto makeSig = [&](const vector<uint64_t>& adj) -> Sig {\n        vector<int> deg(N, 0);\n        for (int v = 0; v < N; v++) deg[v] = popcnt_u64(adj[v]);\n\n        long long edges2 = 0;\n        long long twoStars = 0;\n        for (int v = 0; v < N; v++) {\n            edges2 += deg[v];\n            twoStars += 1LL * deg[v] * (deg[v] - 1) / 2;\n        }\n        int edges = (int)(edges2 / 2);\n\n        vector<int> neighSum(N, 0), neighSqSum(N, 0);\n        for (int v = 0; v < N; v++) {\n            long long s1 = 0, s2 = 0;\n            uint64_t row = adj[v];\n            while (row) {\n                int u = __builtin_ctzll(row);\n                row &= row - 1;\n                s1 += deg[u];\n                s2 += 1LL * deg[u] * deg[u];\n            }\n            neighSum[v] = (int)s1;\n            neighSqSum[v] = (int)s2;\n        }\n\n        vector<uint64_t> vKeys;\n        vKeys.reserve(N);\n        for (int v = 0; v < N; v++) vKeys.push_back(vKey(deg[v], neighSum[v], neighSqSum[v]));\n        sort(vKeys.begin(), vKeys.end());\n\n        vector<uint64_t> eKeys;\n        eKeys.reserve(edges);\n\n        long long sumCnOverEdges = 0; // = 3*triangles\n        for (int i = 0; i < N; i++) {\n            uint64_t row = adj[i] & maskGT[i];\n            while (row) {\n                int j = __builtin_ctzll(row);\n                row &= row - 1;\n\n                int cn = popcnt_u64(adj[i] & adj[j]);\n                sumCnOverEdges += cn;\n\n                if (useCN) eKeys.push_back(eFullKey(deg[i], deg[j], cn));\n                else eKeys.push_back(eBaseKey(deg[i], deg[j]));\n            }\n        }\n        sort(eKeys.begin(), eKeys.end());\n\n        long long triangles = sumCnOverEdges / 3;\n        return Sig{std::move(vKeys), std::move(eKeys), Invariants{edges, twoStars, triangles}};\n    };\n\n    // Full distance used for BOTH codebook selection and decoding\n    // (weights tuned for stability)\n    long long wV = 3, wE = 2;\n    auto dist = [&](const Sig& A, const Sig& B) -> long long {\n        int dV = multisetL1_sorted(A.vKeys, B.vKeys);\n        int dE = multisetL1_sorted(A.eKeys, B.eKeys);\n        long long sc = wV * (long long)dV + wE * (long long)dE;\n        // small invariant stabilization\n        sc += llabs((long long)A.inv.edges - (long long)B.inv.edges);\n        sc += llabs(A.inv.triangles - B.inv.triangles) / 20;\n        return sc;\n    };\n\n    // ----- Generate pool + compute signatures -----\n    uint64_t seedBase = 0x6a09e667f3bcc909ULL\n                      ^ splitmix64((uint64_t)(M * 1000ULL))\n                      ^ splitmix64((uint64_t)llround(eps * 1000.0));\n\n    auto nextRand = [&](uint64_t &st) -> uint64_t {\n        st = splitmix64(st);\n        return st;\n    };\n\n    int poolSize = min(1800, 14 * M + 180);\n    vector<vector<uint64_t>> poolAdj(poolSize, vector<uint64_t>(N, 0ULL));\n    vector<Sig> poolSig(poolSize);\n\n    vector<double> ps = {0.22, 0.30, 0.38, 0.46, 0.54, 0.62, 0.70};\n\n    for (int p = 0; p < poolSize; p++) {\n        uint64_t st = seedBase ^ splitmix64((uint64_t)p * 0x9e3779b97f4a7c15ULL);\n        double prob = ps[(int)(nextRand(st) % ps.size())];\n        uint64_t thr = (uint64_t)llround(prob * 1'000'000.0);\n\n        vector<uint64_t> adj(N, 0ULL);\n        for (int i = 0; i < N; i++) adj[i] = 0ULL;\n\n        for (int i = 0; i < N; i++) {\n            for (int j = i + 1; j < N; j++) {\n                uint64_t r = nextRand(st) % 1'000'000ULL;\n                if (r < thr) {\n                    adj[i] |= (1ULL << j);\n                    adj[j] |= (1ULL << i);\n                }\n            }\n        }\n\n        poolAdj[p] = std::move(adj);\n        poolSig[p] = makeSig(poolAdj[p]);\n    }\n\n    // ----- Greedy farthest-point selection using the exact same dist -----\n    int first = 0;\n    for (int i = 1; i < poolSize; i++) if (poolSig[i].inv.edges > poolSig[first].inv.edges) first = i;\n\n    vector<int> chosen;\n    chosen.reserve(M);\n    chosen.push_back(first);\n\n    vector<long long> minDist(poolSize, (1LL << 62));\n    for (int i = 0; i < poolSize; i++) minDist[i] = dist(poolSig[i], poolSig[first]);\n    minDist[first] = -1;\n\n    while ((int)chosen.size() < M) {\n        int bestIdx = -1;\n        long long bestVal = -1;\n        for (int i = 0; i < poolSize; i++) {\n            if (minDist[i] > bestVal) {\n                bestVal = minDist[i];\n                bestIdx = i;\n            }\n        }\n        chosen.push_back(bestIdx);\n\n        for (int i = 0; i < poolSize; i++) {\n            if (minDist[i] < 0) continue;\n            long long d = dist(poolSig[i], poolSig[bestIdx]);\n            if (d < minDist[i]) minDist[i] = d;\n        }\n        minDist[bestIdx] = -1;\n    }\n\n    vector<vector<uint64_t>> GAdj(M, vector<uint64_t>(N, 0ULL));\n    vector<Sig> Gsig(M);\n    for (int k = 0; k < M; k++) {\n        int idx = chosen[k];\n        GAdj[k] = poolAdj[idx];\n        Gsig[k] = poolSig[idx];\n    }\n\n    // ----- Output graphs -----\n    cout << N << \"\\n\";\n    for (int k = 0; k < M; k++) {\n        cout << encodeGraphBits(GAdj[k]) << \"\\n\";\n    }\n    cout.flush();\n\n    // ----- Decode: evaluate all candidates with the same dist -----\n    for (int qi = 0; qi < 100; qi++) {\n        string H;\n        cin >> H;\n        auto adjH = parseGraphBits(H);\n        Sig qSig = makeSig(adjH);\n\n        int best = 0;\n        long long bestScore = (1LL << 62);\n        for (int k = 0; k < M; k++) {\n            long long sc = dist(qSig, Gsig[k]);\n            if (sc < bestScore) {\n                bestScore = sc;\n                best = k;\n            }\n        }\n        cout << best << \"\\n\";\n        cout.flush();\n    }\n\n    return 0;\n}","ahc017":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct AdjEdge {\n    int to;\n    int eid;\n    int nxt;\n};\n\nstatic const long long INFLL = (1LL << 60);\nstatic const long long UNREACH = 1000000000LL;\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<long long> W(M);\n    vector<vector<AdjEdge>> g(N); // will reserve below\n\n    for (int i = 0; i < M; i++) {\n        int u, v;\n        long long w;\n        cin >> u >> v >> w;\n        --u; --v;\n        W[i] = w;\n        g[u].push_back({v, i, -1});\n        g[v].push_back({u, i, -1});\n    }\n\n    // coords unused\n    for (int i = 0; i < N; i++) {\n        int x, y;\n        cin >> x >> y;\n    }\n\n    mt19937_64 rng(1234567);\n\n    // -----------------------------\n    // Lightweight importance for initialization:\n    // few-source shortest-path tree subtree sizes (as in previous refinement)\n    // -----------------------------\n    int Qimp = min(8, N);\n    vector<int> sourcesImp;\n    sourcesImp.reserve(Qimp);\n    vector<int> anchors = {0, N/2, N-1};\n    for (int a : anchors) if ((int)sourcesImp.size() < Qimp) sourcesImp.push_back(a);\n    while ((int)sourcesImp.size() < Qimp) {\n        int s = (int)(rng() % N);\n        bool ok = true;\n        for (int t : sourcesImp) if (t == s) ok = false;\n        if (ok) sourcesImp.push_back(s);\n    }\n\n    vector<long long> dist(N);\n    vector<int> parent(N), parentEdge(N);\n    vector<vector<int>> children(N);\n    vector<int> order(N), subtree(N);\n\n    // parent chosen from all shortest predecessors (single parent for tree)\n    auto dijkstra_original = [&](int src, vector<long long>& d) {\n        fill(d.begin(), d.end(), INFLL);\n        priority_queue<pair<long long,int>, vector<pair<long long,int>>, greater<pair<long long,int>>> pq;\n        d[src] = 0;\n        pq.push({0, src});\n        while (!pq.empty()) {\n            auto [cd, v] = pq.top(); pq.pop();\n            if (cd != d[v]) continue;\n            for (auto &e : g[v]) {\n                int to = e.to, id = e.eid;\n                long long nd = cd + W[id];\n                if (nd < d[to]) {\n                    d[to] = nd;\n                    pq.push({nd, to});\n                }\n            }\n        }\n    };\n\n    vector<long long> edgeCount(M, 0);\n\n    for (int s : sourcesImp) {\n        dijkstra_original(s, dist);\n\n        for (int i = 0; i < N; i++) {\n            parent[i] = -1;\n            parentEdge[i] = -1;\n            children[i].clear();\n        }\n\n        parent[s] = s;\n        parentEdge[s] = -1;\n\n        for (int v = 0; v < N; v++) {\n            if (v == s) continue;\n            long long dv = dist[v];\n            long long bestDu = INFLL;\n            int bestE = -1, bestP = -1;\n\n            // scan predecessors by checking all neighbors u with dist[u]+w(u,v)=dist[v]\n            for (auto &e : g[v]) {\n                int u = e.to;\n                int eid = e.eid;\n                if (dist[u] == INFLL) continue;\n                if (dist[u] + W[eid] == dv) {\n                    if (dist[u] < bestDu || (dist[u] == bestDu && eid < bestE)) {\n                        bestDu = dist[u];\n                        bestE = eid;\n                        bestP = u;\n                    }\n                }\n            }\n            parent[v] = bestP;\n            parentEdge[v] = bestE;\n        }\n\n        iota(order.begin(), order.end(), 0);\n        sort(order.begin(), order.end(), [&](int a, int b){ return dist[a] > dist[b]; });\n\n        for (int v = 0; v < N; v++) if (v != s) children[parent[v]].push_back(v);\n\n        for (int v = 0; v < N; v++) subtree[v] = 1;\n        for (int v : order) {\n            int sum = 1;\n            for (int c : children[v]) sum += subtree[c];\n            subtree[v] = sum;\n        }\n\n        for (int v = 0; v < N; v++) {\n            if (v == s) continue;\n            int e = parentEdge[v];\n            if (e >= 0) edgeCount[e] += subtree[v];\n        }\n    }\n\n    vector<long double> impRaw(M);\n    long double mxRaw = 0;\n    for (int e = 0; e < M; e++) {\n        impRaw[e] = (long double)edgeCount[e] * (long double)W[e];\n        mxRaw = max(mxRaw, impRaw[e]);\n    }\n    if (mxRaw <= 0) mxRaw = 1;\n\n    vector<double> imp(M);\n    long double scale = mxRaw;\n    for (int e = 0; e < M; e++) {\n        // concave log transform\n        long double x = impRaw[e] / scale * 100.0L + 1.0L;\n        imp[e] = (double)log1pl(x);\n    }\n    double mxImp = 0;\n    for (double x : imp) mxImp = max(mxImp, x);\n    if (mxImp <= 0) mxImp = 1;\n    for (int e = 0; e < M; e++) imp[e] /= mxImp;\n\n    // -----------------------------\n    // Initial schedule: greedy balance by imp\n    // -----------------------------\n    vector<int> edgeOrder(M);\n    iota(edgeOrder.begin(), edgeOrder.end(), 0);\n    sort(edgeOrder.begin(), edgeOrder.end(), [&](int a, int b){\n        if (imp[a] != imp[b]) return imp[a] > imp[b];\n        return W[a] > W[b];\n    });\n\n    vector<int> dayOfEdge(M, -1), posInDay(M, -1);\n    vector<vector<int>> edgesByDay(D);\n    vector<vector<unsigned char>> removed(D, vector<unsigned char>(M, 0));\n    vector<int> cntDay(D, 0);\n    vector<long double> sumImpDay(D, 0.0L);\n\n    struct PQNode { long double s; int c; int d; int ver; };\n    struct PQCmp {\n        bool operator()(const PQNode& a, const PQNode& b) const {\n            if (a.s != b.s) return a.s > b.s;\n            if (a.c != b.c) return a.c > b.c;\n            return a.d > b.d;\n        }\n    };\n\n    priority_queue<PQNode, vector<PQNode>, PQCmp> pq;\n    vector<int> ver(D, 0);\n    for (int d = 0; d < D; d++) pq.push({0.0L, 0, d, ver[d]});\n\n    for (int e : edgeOrder) {\n        while (true) {\n            auto cur = pq.top(); pq.pop();\n            int d = cur.d;\n            if (cur.ver != ver[d]) continue;\n            if ((int)edgesByDay[d].size() >= K) continue;\n\n            dayOfEdge[e] = d;\n            posInDay[e] = (int)edgesByDay[d].size();\n            edgesByDay[d].push_back(e);\n            removed[d][e] = 1;\n            cntDay[d]++;\n            sumImpDay[d] += (long double)imp[e];\n\n            ver[d]++;\n            pq.push({sumImpDay[d], cntDay[d], d, ver[d]});\n            break;\n        }\n    }\n\n    // -----------------------------\n    // Dijkstra proxy local search\n    // -----------------------------\n    int Qfast = min(14, N);\n    vector<int> sourcesFast;\n    sourcesFast.reserve(Qfast);\n    {\n        unordered_set<int> used;\n        while ((int)sourcesFast.size() < Qfast) {\n            int s = (int)(rng() % N);\n            if (used.insert(s).second) sourcesFast.push_back(s);\n        }\n    }\n\n    auto dijkstra_original_src = [&](int src, vector<long long>& d) {\n        fill(d.begin(), d.end(), INFLL);\n        priority_queue<pair<long long,int>, vector<pair<long long,int>>, greater<pair<long long,int>>> pq;\n        d[src] = 0;\n        pq.push({0, src});\n        while (!pq.empty()) {\n            auto [cd, v] = pq.top(); pq.pop();\n            if (cd != d[v]) continue;\n            for (auto &e : g[v]) {\n                int to = e.to, id = e.eid;\n                long long nd = cd + W[id];\n                if (nd < d[to]) {\n                    d[to] = nd;\n                    pq.push({nd, to});\n                }\n            }\n        }\n    };\n\n    vector<vector<long long>> baseDist(Qfast, vector<long long>(N, INFLL));\n    for (int i = 0; i < Qfast; i++) dijkstra_original_src(sourcesFast[i], baseDist[i]);\n\n    auto dijkstra_day = [&](int day, int src, vector<long long>& d) {\n        fill(d.begin(), d.end(), INFLL);\n        priority_queue<pair<long long,int>, vector<pair<long long,int>>, greater<pair<long long,int>>> pq;\n        d[src] = 0;\n        pq.push({0, src});\n        while (!pq.empty()) {\n            auto [cd, v] = pq.top(); pq.pop();\n            if (cd != d[v]) continue;\n            for (auto &e : g[v]) {\n                int to = e.to, id = e.eid;\n                if (removed[day][id]) continue; // repaired on this day => removed\n                long long nd = cd + W[id];\n                if (nd < d[to]) {\n                    d[to] = nd;\n                    pq.push({nd, to});\n                }\n            }\n        }\n    };\n\n    vector<long long> distWork(N);\n    auto computeProxyDay = [&](int day) -> long double {\n        long double sum = 0.0L;\n        for (int si = 0; si < Qfast; si++) {\n            int s = sourcesFast[si];\n            dijkstra_day(day, s, distWork);\n            for (int v = 0; v < N; v++) {\n                if (v == s) continue;\n                long long dk = (distWork[v] == INFLL ? UNREACH : distWork[v]);\n                long long d0 = baseDist[si][v];\n                // dk >= d0 in this monotone edge removal scenario, so nonnegative\n                sum += (long double)(dk - d0);\n            }\n        }\n        return sum;\n    };\n\n    vector<long double> proxyDay(D, 0.0L);\n    long double totalProxy = 0.0L;\n    for (int day = 0; day < D; day++) {\n        proxyDay[day] = computeProxyDay(day);\n        totalProxy += proxyDay[day];\n    }\n\n    auto swapEdges = [&](int eA, int eB) {\n        if (eA == eB) return;\n        int d1 = dayOfEdge[eA], d2 = dayOfEdge[eB];\n        if (d1 == d2) return;\n\n        int p1 = posInDay[eA];\n        int p2 = posInDay[eB];\n\n        // swap edge IDs inside day vectors\n        edgesByDay[d1][p1] = eB;\n        edgesByDay[d2][p2] = eA;\n\n        posInDay[eB] = p1;\n        posInDay[eA] = p2;\n\n        dayOfEdge[eA] = d2;\n        dayOfEdge[eB] = d1;\n\n        // update removed flags for each day\n        removed[d1][eA] = 0;\n        removed[d2][eB] = 0;\n        removed[d1][eB] = 1;\n        removed[d2][eA] = 1;\n    };\n\n    auto elapsedSec = [&](){\n        static auto start = chrono::steady_clock::now();\n        return chrono::duration<double>(chrono::steady_clock::now() - start).count();\n    };\n\n    double TIME_LIMIT = 5.85; // conservative\n    int iter = 0;\n\n    auto pickCandidatesHigh = [&](int d, int take) {\n        // sample some edges from day d, return the top-by-imp 'take' edges\n        auto &vec = edgesByDay[d];\n        int sz = (int)vec.size();\n        int samples = min(sz, 18);\n        vector<int> cand;\n        cand.reserve(samples);\n        for (int t = 0; t < samples; t++) {\n            int id = (int)(rng() % sz);\n            cand.push_back(vec[id]);\n        }\n        sort(cand.begin(), cand.end(), [&](int a, int b){ return imp[a] > imp[b]; });\n        cand.erase(unique(cand.begin(), cand.end()), cand.end());\n        if ((int)cand.size() > take) cand.resize(take);\n        while ((int)cand.size() < take && sz > 0) {\n            int id = (int)(rng() % sz);\n            cand.push_back(vec[id]);\n            sort(cand.begin(), cand.end(), [&](int a, int b){ return imp[a] > imp[b]; });\n            cand.erase(unique(cand.begin(), cand.end()), cand.end());\n            if ((int)cand.size() > take) cand.resize(take);\n        }\n        return cand;\n    };\n\n    auto pickCandidatesLow = [&](int d, int take) {\n        auto &vec = edgesByDay[d];\n        int sz = (int)vec.size();\n        int samples = min(sz, 18);\n        vector<int> cand;\n        cand.reserve(samples);\n        for (int t = 0; t < samples; t++) {\n            int id = (int)(rng() % sz);\n            cand.push_back(vec[id]);\n        }\n        sort(cand.begin(), cand.end(), [&](int a, int b){ return imp[a] < imp[b]; });\n        cand.erase(unique(cand.begin(), cand.end()), cand.end());\n        if ((int)cand.size() > take) cand.resize(take);\n        while ((int)cand.size() < take && sz > 0) {\n            int id = (int)(rng() % sz);\n            cand.push_back(vec[id]);\n            sort(cand.begin(), cand.end(), [&](int a, int b){ return imp[a] < imp[b]; });\n            cand.erase(unique(cand.begin(), cand.end()), cand.end());\n            if ((int)cand.size() > take) cand.resize(take);\n        }\n        return cand;\n    };\n\n    while (true) {\n        if (elapsedSec() > TIME_LIMIT) break;\n        iter++;\n\n        // sort days by proxy\n        vector<int> days(D);\n        iota(days.begin(), days.end(), 0);\n        sort(days.begin(), days.end(), [&](int a, int b){ return proxyDay[a] > proxyDay[b]; });\n\n        int topCount = min(3, D);\n        int botCount = min(3, D);\n        int dHigh = days[(int)(rng() % topCount)];                // among worst\n        int dLow = days[D-1 - (int)(rng() % botCount)];          // among best\n        if (dHigh == dLow) continue;\n\n        // candidate edges on those days\n        auto candHigh = pickCandidatesHigh(dHigh, 3); // largest imp\n        auto candLow  = pickCandidatesLow(dLow, 3);  // smallest imp\n\n        // generate candidate pairs, prioritize by predicted improvement in proxy (imp difference heuristic)\n        struct PairCand { int eA, eB; double score; };\n        vector<PairCand> pairs;\n        for (int eA : candHigh) for (int eB : candLow) {\n            if (eA == eB) continue;\n            if (dayOfEdge[eA] != dHigh || dayOfEdge[eB] != dLow) continue;\n            double sc = imp[eA] - imp[eB];\n            pairs.push_back({eA, eB, sc});\n        }\n        if (pairs.empty()) continue;\n        sort(pairs.begin(), pairs.end(), [&](const PairCand& a, const PairCand& b){\n            return a.score > b.score;\n        });\n\n        // evaluate a few best pairs exactly by proxy\n        long double bestNewTotal = totalProxy;\n        int bestEA = -1, bestEB = -1;\n        long double bestNewHigh = 0, bestNewLow = 0;\n\n        int evalLimit = min(6, (int)pairs.size());\n        for (int pi = 0; pi < evalLimit; pi++) {\n            int eA = pairs[pi].eA;\n            int eB = pairs[pi].eB;\n\n            swapEdges(eA, eB);\n\n            long double newHigh = computeProxyDay(dHigh); // day indices unchanged\n            long double newLow  = computeProxyDay(dLow);\n            long double newTotal = totalProxy - proxyDay[dHigh] - proxyDay[dLow] + newHigh + newLow;\n\n            swapEdges(eA, eB); // revert to original\n\n            if (newTotal < bestNewTotal) {\n                bestNewTotal = newTotal;\n                bestEA = eA; bestEB = eB;\n                bestNewHigh = newHigh;\n                bestNewLow = newLow;\n            }\n        }\n\n        // apply best improving swap\n        if (bestEA != -1) {\n            swapEdges(bestEA, bestEB);\n            proxyDay[dHigh] = bestNewHigh;\n            proxyDay[dLow] = bestNewLow;\n            totalProxy = bestNewTotal;\n        }\n    }\n\n    // Output schedule\n    for (int e = 0; e < M; e++) {\n        cout << (dayOfEdge[e] + 1) << (e + 1 == M ? '\\n' : ' ');\n    }\n    return 0;\n}","ahc019":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic inline int idx3(int D, int x, int y, int z) { // z fastest\n    return x * D * D + y * D + z;\n}\n\nstruct SplitMix64 {\n    uint64_t x;\n    explicit SplitMix64(uint64_t seed = 0) : x(seed) {}\n    uint64_t next_u64() {\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    template <class T>\n    void shuffle_vec(vector<T>& a) {\n        for (int i = (int)a.size() - 1; i > 0; --i) {\n            int j = (int)(next_u64() % (uint64_t)(i + 1));\n            swap(a[i], a[j]);\n        }\n    }\n};\n\nstruct HopcroftKarp {\n    int nL, nR;\n    vector<vector<int>> adj;\n    vector<int> dist, matchL, matchR;\n\n    HopcroftKarp(int nL_ = 0, int nR_ = 0) { init(nL_, nR_); }\n\n    void init(int nL_, int nR_) {\n        nL = nL_; nR = nR_;\n        adj.assign(nL, {});\n        dist.assign(nL, 0);\n        matchL.assign(nL, -1);\n        matchR.assign(nR, -1);\n    }\n\n    void add_edge(int u, int v) { adj[u].push_back(v); }\n\n    bool bfs() {\n        deque<int> q;\n        for (int i = 0; i < nL; i++) {\n            if (matchL[i] == -1) dist[i] = 0, q.push_back(i);\n            else dist[i] = -1;\n        }\n        bool reachFreeR = false;\n        while (!q.empty()) {\n            int v = q.front(); q.pop_front();\n            for (int to : adj[v]) {\n                int u = matchR[to];\n                if (u == -1) reachFreeR = true;\n                else if (dist[u] == -1) dist[u] = dist[v] + 1, q.push_back(u);\n            }\n        }\n        return reachFreeR;\n    }\n\n    bool dfs(int v) {\n        for (int to : adj[v]) {\n            int u = matchR[to];\n            if (u == -1 || (dist[u] == dist[v] + 1 && dfs(u))) {\n                matchL[v] = to;\n                matchR[to] = v;\n                return true;\n            }\n        }\n        dist[v] = -1;\n        return false;\n    }\n\n    int max_matching() {\n        int flow = 0;\n        while (bfs()) {\n            for (int i = 0; i < nL; i++) {\n                if (matchL[i] == -1 && dfs(i)) flow++;\n            }\n        }\n        return flow;\n    }\n};\n\nstatic vector<pair<int,int>> maxDominoPairs(\n    int D,\n    const vector<int>& parity,\n    const vector<array<int,6>>& neigh,\n    const vector<int>& remCubes\n) {\n    int N = D*D*D;\n    int m = (int)remCubes.size();\n    vector<int> posToLocal(N, -1);\n    for (int i = 0; i < m; i++) posToLocal[remCubes[i]] = i;\n\n    vector<int> leftIdx, rightIdx; // local indices into remCubes\n    leftIdx.reserve(m); rightIdx.reserve(m);\n    vector<int> localToRight(m, -1);\n\n    for (int i = 0; i < m; i++) {\n        int g = remCubes[i];\n        if (parity[g] == 0) leftIdx.push_back(i);\n        else {\n            localToRight[i] = (int)rightIdx.size();\n            rightIdx.push_back(i);\n        }\n    }\n\n    HopcroftKarp hk((int)leftIdx.size(), (int)rightIdx.size());\n\n    for (int li = 0; li < (int)leftIdx.size(); li++) {\n        int lLocal = leftIdx[li];\n        int g = remCubes[lLocal];\n        for (int dir = 0; dir < 6; dir++) {\n            int ng = neigh[g][dir];\n            if (ng < 0) continue;\n            int vLocal = posToLocal[ng];\n            if (vLocal < 0) continue;\n            int rv = localToRight[vLocal];\n            if (rv >= 0) hk.add_edge(li, rv);\n        }\n    }\n\n    hk.max_matching();\n\n    vector<pair<int,int>> pairs;\n    pairs.reserve((int)leftIdx.size());\n    for (int li = 0; li < (int)leftIdx.size(); li++) {\n        int rmatch = hk.matchL[li];\n        if (rmatch != -1) {\n            int lLocal = leftIdx[li];\n            int rLocal = rightIdx[rmatch];\n            pairs.push_back({remCubes[lLocal], remCubes[rLocal]});\n        }\n    }\n    return pairs;\n}\n\ntemplate<int K>\nstatic vector<int> greedyPackMaxK(\n    const vector<int>& candIdx,                   // indices into placements\n    const vector<array<int,K>>& placements,\n    vector<unsigned char>& used,                 // modified\n    SplitMix64& rng\n) {\n    vector<int> order = candIdx;\n    rng.shuffle_vec(order);\n    vector<int> chosen;\n    chosen.reserve(order.size());\n    for (int pi : order) {\n        const auto &pl = placements[pi];\n        bool ok = true;\n        for (int i = 0; i < K; i++) {\n            if (used[pl[i]]) { ok = false; break; }\n        }\n        if (!ok) continue;\n        for (int i = 0; i < K; i++) used[pl[i]] = 1;\n        chosen.push_back(pi);\n    }\n    return chosen;\n}\n\nstatic vector<int> randomSubsetK(const vector<int>& v, int k, SplitMix64& rng) {\n    if (k <= 0) return {};\n    if ((int)v.size() <= k) return v;\n    vector<int> tmp = v;\n    rng.shuffle_vec(tmp);\n    tmp.resize(k);\n    return tmp;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int D;\n    cin >> D;\n    int N = D*D*D;\n\n    vector<vector<string>> f(2, vector<string>(D)), r(2, vector<string>(D));\n    for (int i = 0; i < 2; i++) {\n        for (int z = 0; z < D; z++) cin >> f[i][z];\n        for (int z = 0; z < D; z++) cin >> r[i][z];\n    }\n\n    vector<vector<unsigned char>> exist(2, vector<unsigned char>(N, 0));\n    for (int obj = 0; obj < 2; obj++) {\n        for (int x = 0; x < D; x++) for (int y = 0; y < D; y++) for (int z = 0; z < D; z++) {\n            if (f[obj][z][x] == '1' && r[obj][z][y] == '1') exist[obj][idx3(D,x,y,z)] = 1;\n        }\n    }\n\n    // parity and neighbors for domino matching\n    vector<int> parity(N, 0);\n    vector<array<int,6>> neigh(N);\n    for (int x = 0; x < D; x++) for (int y = 0; y < D; y++) for (int z = 0; z < D; z++) {\n        int id = idx3(D,x,y,z);\n        parity[id] = (x+y+z) & 1;\n        array<int,6> nb; nb.fill(-1);\n        if (x+1 < D) nb[0] = idx3(D,x+1,y,z);\n        if (x-1 >=0) nb[1] = idx3(D,x-1,y,z);\n        if (y+1 < D) nb[2] = idx3(D,x,y+1,z);\n        if (y-1 >=0) nb[3] = idx3(D,x,y-1,z);\n        if (z+1 < D) nb[4] = idx3(D,x,y,z+1);\n        if (z-1 >=0) nb[5] = idx3(D,x,y,z-1);\n        neigh[id] = nb;\n    }\n\n    // Precompute placements for prisms\n    vector<array<int,8>> P8;\n    for (int x = 0; x+2 <= D; x++)\n        for (int y = 0; y+2 <= D; y++)\n            for (int z = 0; z+2 <= D; z++) {\n                array<int,8> a{};\n                int t = 0;\n                for (int dx=0;dx<2;dx++) for (int dy=0;dy<2;dy++) for (int dz=0;dz<2;dz++)\n                    a[t++] = idx3(D,x+dx,y+dy,z+dz);\n                P8.push_back(a);\n            }\n\n    vector<array<int,6>> P6;\n    // permutations of (3,2,1)\n    vector<array<int,3>> dims6 = {\n        {3,2,1},{3,1,2},{2,3,1},{2,1,3},{1,3,2},{1,2,3}\n    };\n    for (auto d : dims6) {\n        int dx=d[0], dy=d[1], dz=d[2];\n        for (int x = 0; x+dx <= D; x++)\n            for (int y = 0; y+dy <= D; y++)\n                for (int z = 0; z+dz <= D; z++) {\n                    array<int,6> a{};\n                    int t = 0;\n                    for (int i0=0;i0<dx;i0++) for (int j0=0;j0<dy;j0++) for (int k0=0;k0<dz;k0++)\n                        a[t++] = idx3(D,x+i0,y+j0,z+k0);\n                    P6.push_back(a);\n                }\n    }\n\n    vector<array<int,4>> P4;\n    // orientations of 2x2x1: (2,2,1),(2,1,2),(1,2,2)\n    vector<array<int,3>> dims4 = { {2,2,1},{2,1,2},{1,2,2} };\n    for (auto d : dims4) {\n        int dx=d[0], dy=d[1], dz=d[2];\n        for (int x = 0; x+dx <= D; x++)\n            for (int y = 0; y+dy <= D; y++)\n                for (int z = 0; z+dz <= D; z++) {\n                    array<int,4> a{};\n                    int t = 0;\n                    for (int i0=0;i0<dx;i0++) for (int j0=0;j0<dy;j0++) for (int k0=0;k0<dz;k0++)\n                        a[t++] = idx3(D,x+i0,y+j0,z+k0);\n                    P4.push_back(a);\n                }\n    }\n\n    vector<array<int,3>> P3;\n    // orientations of 1x1x3: (3,1,1),(1,3,1),(1,1,3)\n    vector<array<int,3>> dims3 = { {3,1,1},{1,3,1},{1,1,3} };\n    for (auto d : dims3) {\n        int dx=d[0], dy=d[1], dz=d[2];\n        for (int x = 0; x+dx <= D; x++)\n            for (int y = 0; y+dy <= D; y++)\n                for (int z = 0; z+dz <= D; z++) {\n                    array<int,3> a{};\n                    int t = 0;\n                    for (int i0=0;i0<dx;i0++) for (int j0=0;j0<dy;j0++) for (int k0=0;k0<dz;k0++)\n                        a[t++] = idx3(D,x+i0,y+j0,z+k0);\n                    P3.push_back(a);\n                }\n    }\n\n    // Candidate placement indices fully inside exist mask\n    vector<vector<int>> cand8(2), cand6(2), cand4(2), cand3(2);\n    for (int obj = 0; obj < 2; obj++) {\n        cand8[obj].reserve(P8.size());\n        for (int i = 0; i < (int)P8.size(); i++) {\n            bool ok = true;\n            for (int c : P8[i]) if (!exist[obj][c]) { ok = false; break; }\n            if (ok) cand8[obj].push_back(i);\n        }\n        cand6[obj].reserve(P6.size());\n        for (int i = 0; i < (int)P6.size(); i++) {\n            bool ok = true;\n            for (int c : P6[i]) if (!exist[obj][c]) { ok = false; break; }\n            if (ok) cand6[obj].push_back(i);\n        }\n        cand4[obj].reserve(P4.size());\n        for (int i = 0; i < (int)P4.size(); i++) {\n            bool ok = true;\n            for (int c : P4[i]) if (!exist[obj][c]) { ok = false; break; }\n            if (ok) cand4[obj].push_back(i);\n        }\n        cand3[obj].reserve(P3.size());\n        for (int i = 0; i < (int)P3.size(); i++) {\n            bool ok = true;\n            for (int c : P3[i]) if (!exist[obj][c]) { ok = false; break; }\n            if (ok) cand3[obj].push_back(i);\n        }\n    }\n\n    // Search best trial\n    const int T_outer = 9;\n\n    double bestEval = 1e100;\n    int bestKeep8=0,bestKeep6=0,bestKeep4=0,bestKeep3=0,bestKeepDom=0;\n    vector<int> bestS8[2], bestS6[2], bestS4[2], bestS3[2];\n    vector<pair<int,int>> bestDomPairs[2];\n\n    for (int trial = 0; trial < T_outer; trial++) {\n        SplitMix64 rng0(1234567ULL + (uint64_t)trial*10007ULL + 31ULL*(uint64_t)D);\n        SplitMix64 rng1(998244353ULL + (uint64_t)trial*9176ULL + 17ULL*(uint64_t)D);\n\n        // ---- 8 blocks ----\n        vector<int> full8[2];\n        for (int obj = 0; obj < 2; obj++) {\n            vector<unsigned char> used(N, 0);\n            SplitMix64 &rng = (obj==0 ? rng0 : rng1);\n            full8[obj] = greedyPackMaxK<8>(cand8[obj], P8, used, rng);\n        }\n        int keep8 = min((int)full8[0].size(), (int)full8[1].size());\n        vector<int> s8[2];\n        for (int obj=0; obj<2; obj++) {\n            SplitMix64 &rng = (obj==0 ? rng0 : rng1);\n            s8[obj] = randomSubsetK(full8[obj], keep8, rng);\n        }\n\n        vector<unsigned char> usedBase[2];\n        for (int obj=0; obj<2; obj++) {\n            usedBase[obj].assign(N, 0);\n            for (int pi : s8[obj]) for (int c : P8[pi]) usedBase[obj][c] = 1;\n        }\n\n        // ---- 6 blocks ----\n        vector<int> full6[2], s6[2];\n        for (int obj=0; obj<2; obj++) {\n            vector<unsigned char> usedTmp = usedBase[obj];\n            SplitMix64 &rng = (obj==0 ? rng0 : rng1);\n            full6[obj] = greedyPackMaxK<6>(cand6[obj], P6, usedTmp, rng);\n        }\n        int keep6 = min((int)full6[0].size(), (int)full6[1].size());\n        for (int obj=0; obj<2; obj++) {\n            SplitMix64 &rng = (obj==0 ? rng0 : rng1);\n            s6[obj] = randomSubsetK(full6[obj], keep6, rng);\n        }\n        for (int obj=0; obj<2; obj++) {\n            for (int pi : s6[obj]) for (int c : P6[pi]) usedBase[obj][c] = 1;\n        }\n\n        // ---- 4 blocks ----\n        vector<int> full4[2], s4[2];\n        for (int obj=0; obj<2; obj++) {\n            vector<unsigned char> usedTmp = usedBase[obj];\n            SplitMix64 &rng = (obj==0 ? rng0 : rng1);\n            full4[obj] = greedyPackMaxK<4>(cand4[obj], P4, usedTmp, rng);\n        }\n        int keep4 = min((int)full4[0].size(), (int)full4[1].size());\n        for (int obj=0; obj<2; obj++) {\n            SplitMix64 &rng = (obj==0 ? rng0 : rng1);\n            s4[obj] = randomSubsetK(full4[obj], keep4, rng);\n        }\n        for (int obj=0; obj<2; obj++) {\n            for (int pi : s4[obj]) for (int c : P4[pi]) usedBase[obj][c] = 1;\n        }\n\n        // ---- 3 blocks ----\n        vector<int> full3[2], s3[2];\n        for (int obj=0; obj<2; obj++) {\n            vector<unsigned char> usedTmp = usedBase[obj];\n            SplitMix64 &rng = (obj==0 ? rng0 : rng1);\n            full3[obj] = greedyPackMaxK<3>(cand3[obj], P3, usedTmp, rng);\n        }\n        int keep3 = min((int)full3[0].size(), (int)full3[1].size());\n        for (int obj=0; obj<2; obj++) {\n            SplitMix64 &rng = (obj==0 ? rng0 : rng1);\n            s3[obj] = randomSubsetK(full3[obj], keep3, rng);\n        }\n        for (int obj=0; obj<2; obj++) {\n            for (int pi : s3[obj]) for (int c : P3[pi]) usedBase[obj][c] = 1;\n        }\n\n        // ---- Remaining for dominos ----\n        vector<int> rem[2];\n        for (int obj=0; obj<2; obj++) {\n            rem[obj].clear();\n            for (int id=0; id<N; id++) {\n                if (exist[obj][id] && !usedBase[obj][id]) rem[obj].push_back(id);\n            }\n        }\n        auto pairs0 = maxDominoPairs(D, parity, neigh, rem[0]);\n        auto pairs1 = maxDominoPairs(D, parity, neigh, rem[1]);\n        int keepDom = min((int)pairs0.size(), (int)pairs1.size());\n\n        // Units counts (exact): every unoccupied rem cube becomes a unit,\n        // dominos cover 2*keepDom cubes.\n        int units0 = (int)rem[0].size() - 2*keepDom;\n        int units1 = (int)rem[1].size() - 2*keepDom;\n        int maxUnits = max(units0, units1);\n\n        double eval = (double)maxUnits\n            + (double)keepDom/2.0\n            + (double)keep3/3.0\n            + (double)keep4/4.0\n            + (double)keep6/6.0\n            + (double)keep8/8.0;\n\n        if (eval < bestEval) {\n            bestEval = eval;\n            bestKeep8 = keep8; bestKeep6 = keep6; bestKeep4 = keep4; bestKeep3 = keep3; bestKeepDom = keepDom;\n            for (int obj=0; obj<2; obj++) {\n                bestS8[obj] = s8[obj];\n                bestS6[obj] = s6[obj];\n                bestS4[obj] = s4[obj];\n                bestS3[obj] = s3[obj];\n            }\n            bestDomPairs[0].assign(pairs0.begin(), pairs0.begin()+keepDom);\n            bestDomPairs[1].assign(pairs1.begin(), pairs1.begin()+keepDom);\n        }\n    }\n\n    // ---- Build final answer ----\n    vector<int> b0(N, 0), b1(N, 0);\n    int id = 1;\n\n    auto markBlocks = [&](vector<int>& b, int startId, const vector<int>& sel, const auto& P) {\n        int cur = startId;\n        for (int pi : sel) {\n            for (int c : P[pi]) b[c] = cur;\n            cur++;\n        }\n        return cur;\n    };\n\n    // shared 2x2x2 (vol 8)\n    for (int k = 0; k < bestKeep8; k++) {\n        int pi0 = bestS8[0][k];\n        int pi1 = bestS8[1][k];\n        for (int c : P8[pi0]) b0[c] = id;\n        for (int c : P8[pi1]) b1[c] = id;\n        id++;\n    }\n\n    // shared 3x2x1 (vol 6)\n    for (int k = 0; k < bestKeep6; k++) {\n        int pi0 = bestS6[0][k];\n        int pi1 = bestS6[1][k];\n        for (int c : P6[pi0]) b0[c] = id;\n        for (int c : P6[pi1]) b1[c] = id;\n        id++;\n    }\n\n    // shared 2x2x1 (vol 4)\n    for (int k = 0; k < bestKeep4; k++) {\n        int pi0 = bestS4[0][k];\n        int pi1 = bestS4[1][k];\n        for (int c : P4[pi0]) b0[c] = id;\n        for (int c : P4[pi1]) b1[c] = id;\n        id++;\n    }\n\n    // shared 1x1x3 (vol 3)\n    for (int k = 0; k < bestKeep3; k++) {\n        int pi0 = bestS3[0][k];\n        int pi1 = bestS3[1][k];\n        for (int c : P3[pi0]) b0[c] = id;\n        for (int c : P3[pi1]) b1[c] = id;\n        id++;\n    }\n\n    int domStart = id;\n\n    // shared dominos (vol 2)\n    for (int t = 0; t < bestKeepDom; t++) {\n        int bid = domStart + t;\n        auto [a0, c0] = bestDomPairs[0][t];\n        auto [a1, c1] = bestDomPairs[1][t];\n        b0[a0] = bid; b0[c0] = bid;\n        b1[a1] = bid; b1[c1] = bid;\n    }\n\n    int unitBase = domStart + bestKeepDom;\n\n    // assign units to remaining exist-cubes (different counts ok)\n    vector<int> units0, units1;\n    for (int cid = 0; cid < N; cid++) {\n        if (exist[0][cid] && b0[cid] == 0) units0.push_back(cid);\n        if (exist[1][cid] && b1[cid] == 0) units1.push_back(cid);\n    }\n    int maxUnits = max((int)units0.size(), (int)units1.size());\n    for (int t = 0; t < (int)units0.size(); t++) b0[units0[t]] = unitBase + t;\n    for (int t = 0; t < (int)units1.size(); t++) b1[units1[t]] = unitBase + t;\n\n    int nBlocks = unitBase + maxUnits - 1;\n    if (nBlocks < 1) nBlocks = 1; // should not happen\n\n    cout << nBlocks << \"\\n\";\n    auto printB = [&](const vector<int>& b) {\n        bool first = true;\n        for (int x=0;x<D;x++) for (int y=0;y<D;y++) for (int z=0;z<D;z++) {\n            if (!first) cout << ' ';\n            first = false;\n            cout << b[idx3(D,x,y,z)];\n        }\n        cout << \"\\n\";\n    };\n    printB(b0);\n    printB(b1);\n    return 0;\n}","ahc020":"#include <bits/stdc++.h>\nusing namespace std;\nusing ll = long long;\n\nstatic int ceil_sqrt_ll(long long x) {\n    if (x <= 0) return 0;\n    long long r = (long long)sqrt((long double)x);\n    while (r * r < x) ++r;\n    while ((r - 1) * (r - 1) >= x) --r;\n    return (int)r;\n}\n\nstruct Fenwick {\n    int n = 0, bitMask = 1;\n    vector<int> bit;\n    void init(int n_) {\n        n = n_;\n        bit.assign(n + 1, 0);\n        bitMask = 1;\n        while (bitMask < n) bitMask <<= 1;\n    }\n    void add(int idx, int delta) { // idx in [1..n]\n        for (; idx <= n; idx += idx & -idx) bit[idx] += delta;\n    }\n    int kth(int k) const { // smallest idx s.t prefix >= k (k>=1)\n        int idx = 0;\n        for (int d = bitMask; d > 0; d >>= 1) {\n            int nxt = idx + d;\n            if (nxt <= n && bit[nxt] < k) {\n                idx = nxt;\n                k -= bit[nxt];\n            }\n        }\n        return idx + 1;\n    }\n    int getMax(int total) const { // radii mapped to (r+1)\n        if (total <= 0) return 0;\n        int pos = kth(total);\n        return pos - 1;\n    }\n};\n\nstruct SPT {\n    vector<int> parent;\n    vector<int> parentEdgeId;\n    vector<ll> weightToParent;\n    vector<vector<int>> children;\n    vector<vector<int>> anc;   // nodes on path v->root excluding root, including v\n    vector<int> depthCnt;      // anc[v].size()\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, K;\n    cin >> N >> M >> K;\n    vector<ll> x(N), y(N);\n    for (int i = 0; i < N; i++) cin >> x[i] >> y[i];\n\n    vector<int> U(M), V(M);\n    vector<ll> W(M);\n    vector<vector<tuple<int,ll,int>>> adj(N);\n    for (int j = 0; j < M; j++) {\n        cin >> U[j] >> V[j] >> W[j];\n        --U[j]; --V[j];\n        adj[U[j]].push_back({V[j], W[j], j});\n        adj[V[j]].push_back({U[j], W[j], j});\n    }\n\n    vector<ll> ax(K), ay(K);\n    for (int k = 0; k < K; k++) cin >> ax[k] >> ay[k];\n\n    const int LIM = 5000;\n    const ll LIM2 = 1LL * LIM * LIM;\n\n    vector<vector<uint16_t>> r(N, vector<uint16_t>(K, (uint16_t)(LIM + 1)));\n    for (int i = 0; i < N; i++) {\n        for (int k = 0; k < K; k++) {\n            ll dx = x[i] - ax[k];\n            ll dy = y[i] - ay[k];\n            ll d2 = dx*dx + dy*dy;\n            if (d2 <= LIM2) {\n                int rr = ceil_sqrt_ll(d2);\n                if (rr <= LIM) r[i][k] = (uint16_t)rr;\n            }\n        }\n    }\n\n    auto buildSPT = [&](uint64_t seed) -> SPT {\n        mt19937_64 rng(seed);\n        const ll INF = (1LL<<62);\n\n        vector<ll> dist(N, INF);\n        vector<int> parent(N, -1), parentEdgeId(N, -1);\n        vector<ll> bestEdgeW(N, INF);\n\n        dist[0] = 0;\n        parent[0] = -1;\n        bestEdgeW[0] = 0;\n\n        using PII = pair<ll,int>;\n        priority_queue<PII, vector<PII>, greater<PII>> pq;\n        pq.push({0, 0});\n\n        while (!pq.empty()) {\n            auto [d,u] = pq.top(); pq.pop();\n            if (d != dist[u]) continue;\n            for (auto [v, ww, id] : adj[u]) {\n                ll nd = d + ww;\n                if (nd < dist[v]) {\n                    dist[v] = nd;\n                    parent[v] = u;\n                    parentEdgeId[v] = id;\n                    bestEdgeW[v] = ww;\n                    pq.push({nd, v});\n                } else if (nd == dist[v]) {\n                    if (ww < bestEdgeW[v]) {\n                        parent[v] = u;\n                        parentEdgeId[v] = id;\n                        bestEdgeW[v] = ww;\n                    } else if (ww == bestEdgeW[v]) {\n                        if ((rng() & 1ULL) == 0) {\n                            parent[v] = u;\n                            parentEdgeId[v] = id;\n                        }\n                    }\n                }\n            }\n        }\n\n        vector<ll> weightToParent(N, 0);\n        for (int v = 1; v < N; v++) weightToParent[v] = W[parentEdgeId[v]];\n\n        vector<vector<int>> children(N);\n        for (int v = 1; v < N; v++) children[parent[v]].push_back(v);\n\n        vector<vector<int>> anc(N);\n        vector<int> depthCnt(N, 0);\n        for (int v = 1; v < N; v++) {\n            int cur = v;\n            while (cur != 0) {\n                anc[v].push_back(cur);\n                cur = parent[cur];\n            }\n            depthCnt[v] = (int)anc[v].size();\n        }\n\n        return SPT{std::move(parent), std::move(parentEdgeId), std::move(weightToParent),\n                    std::move(children), std::move(anc), std::move(depthCnt)};\n    };\n\n    auto buildCandidates = [&](const SPT& spt,\n                                int Lnear, int Lshallow,\n                                int ancestorSpan, int Lcap) {\n        vector<vector<int>> cand(K);\n        vector<vector<int>> candNeedSorted(K);\n\n        vector<pair<int,int>> tmp;\n        tmp.reserve(N);\n\n        for (int k = 0; k < K; k++) {\n            tmp.clear();\n            for (int i = 0; i < N; i++) {\n                int need = (int)r[i][k];\n                if (need <= LIM) tmp.push_back({need, i});\n            }\n            sort(tmp.begin(), tmp.end());\n\n            vector<char> used(N, 0);\n            vector<int> res;\n            res.reserve(Lcap);\n\n            auto addStation = [&](int s) {\n                if (!used[s] && (int)r[s][k] <= LIM) {\n                    used[s] = 1;\n                    res.push_back(s);\n                }\n            };\n\n            for (int t = 0; t < (int)tmp.size() && t < Lnear && (int)res.size() < Lcap; t++) {\n                int s = tmp[t].second;\n                int cur = s;\n                for (int step = 0; step <= ancestorSpan; step++) {\n                    addStation(cur);\n                    if (cur == 0) break;\n                    cur = spt.parent[cur];\n                    if (cur < 0) break;\n                    if ((int)res.size() >= Lcap) break;\n                }\n            }\n\n            if ((int)res.size() < Lcap) {\n                vector<pair<int,int>> tmp2;\n                tmp2.reserve(tmp.size());\n                for (auto &pr : tmp) tmp2.push_back({spt.depthCnt[pr.second], pr.second});\n                sort(tmp2.begin(), tmp2.end());\n                for (int t = 0; t < (int)tmp2.size() && t < Lshallow && (int)res.size() < Lcap; t++) {\n                    addStation(tmp2[t].second);\n                }\n            }\n\n            if (res.empty()) addStation(tmp[0].second);\n            if ((int)res.size() > Lcap) res.resize(Lcap);\n\n            cand[k] = res;\n\n            auto ord = res;\n            sort(ord.begin(), ord.end(), [&](int a, int b){\n                return r[a][k] < r[b][k];\n            });\n            candNeedSorted[k] = std::move(ord);\n        }\n        return pair{cand, candNeedSorted};\n    };\n\n    auto greedyInit = [&](const SPT& spt,\n                           const vector<vector<int>>& cand,\n                           uint64_t seed) {\n        mt19937_64 rng(seed);\n        vector<int> assign(K, -1);\n\n        vector<int> sz(N, 0);\n        vector<int> curMax(N, 0);\n        vector<int> subtreeCnt(N, 0);\n\n        vector<int> order(K);\n        iota(order.begin(), order.end(), 0);\n        shuffle(order.begin(), order.end(), rng);\n\n        for (int k : order) {\n            ll best = (1LL<<62);\n            vector<int> bests;\n            for (int to : cand[k]) {\n                int need = (int)r[to][k];\n                int oldMax = curMax[to];\n                int newMax = max(oldMax, need);\n                ll dP = 1LL*newMax*newMax - 1LL*oldMax*oldMax;\n\n                ll dE = 0;\n                if (sz[to] == 0) {\n                    for (int u : spt.anc[to]) if (subtreeCnt[u] == 0) dE += spt.weightToParent[u];\n                }\n                ll d = dP + dE;\n                if (d < best) {\n                    best = d;\n                    bests.clear();\n                    bests.push_back(to);\n                } else if (d == best) {\n                    bests.push_back(to);\n                }\n            }\n            int chosen = bests[(size_t)(rng() % (uint64_t)bests.size())];\n            assign[k] = chosen;\n\n            int need = (int)r[chosen][k];\n            bool wasInactive = (sz[chosen] == 0);\n            sz[chosen]++;\n            curMax[chosen] = max(curMax[chosen], need);\n            if (wasInactive) {\n                for (int u : spt.anc[chosen]) subtreeCnt[u]++;\n            }\n        }\n        return assign;\n    };\n\n    auto solveTrial = [&](const SPT& spt,\n                           const vector<vector<int>>& cand,\n                           const vector<vector<int>>& candNeedSorted,\n                           const vector<int>& assignInit,\n                           uint64_t seed,\n                           int timeLimitMs,\n                           int HILLCAP,\n                           int SUB2) -> pair<ll, vector<int>> {\n        mt19937_64 rng(seed);\n        auto tStart = chrono::steady_clock::now();\n        auto timeUp = [&](){\n            return chrono::duration_cast<chrono::milliseconds>(chrono::steady_clock::now() - tStart).count() > timeLimitMs;\n        };\n\n        vector<int> assign = assignInit;\n\n        vector<Fenwick> fenw(N);\n        for (int i = 0; i < N; i++) fenw[i].init(LIM + 1);\n\n        vector<int> sz(N, 0), P(N, 0);\n        for (int k = 0; k < K; k++) {\n            int st = assign[k];\n            int need = (int)r[st][k];\n            fenw[st].add(need + 1, +1);\n            sz[st]++;\n        }\n\n        ll Pcost = 0;\n        for (int i = 0; i < N; i++) {\n            P[i] = (sz[i] ? fenw[i].getMax(sz[i]) : 0);\n            Pcost += 1LL * P[i] * P[i];\n        }\n\n        vector<int> subtreeCnt(N, 0);\n        function<int(int)> dfs = [&](int v)->int{\n            int cnt = (sz[v] > 0) ? 1 : 0;\n            for (int to : spt.children[v]) cnt += dfs(to);\n            subtreeCnt[v] = cnt;\n            return cnt;\n        };\n        dfs(0);\n\n        ll edgeCost = 0;\n        for (int v = 1; v < N; v++) if (subtreeCnt[v] > 0) edgeCost += spt.weightToParent[v];\n\n        ll totalCost = Pcost + edgeCost;\n        ll bestCost = totalCost;\n        vector<int> bestAssign = assign;\n\n        vector<int> mark(N, 0), deltaVal(N, 0), touched;\n        touched.reserve(N);\n        int stamp = 1;\n\n        auto deltaEdge = [&](int from, int to, bool fromInactive, bool toActive) -> ll {\n            if (!fromInactive && !toActive) return 0LL;\n\n            if (fromInactive && !toActive) {\n                ll dE = 0;\n                for (int u : spt.anc[from]) {\n                    if (subtreeCnt[u] == 1) dE -= spt.weightToParent[u];\n                }\n                return dE;\n            }\n            if (!fromInactive && toActive) {\n                ll dE = 0;\n                for (int u : spt.anc[to]) {\n                    if (subtreeCnt[u] == 0) dE += spt.weightToParent[u];\n                }\n                return dE;\n            }\n\n            // both toggles: union anc[from] and anc[to]\n            stamp++;\n            touched.clear();\n\n            auto addDeltaPath = [&](int start, int d) {\n                for (int u : spt.anc[start]) {\n                    if (mark[u] != stamp) {\n                        mark[u] = stamp;\n                        deltaVal[u] = 0;\n                        touched.push_back(u);\n                    }\n                    deltaVal[u] += d;\n                }\n            };\n\n            addDeltaPath(from, -1);\n            addDeltaPath(to, +1);\n\n            ll dE = 0;\n            for (int u : touched) {\n                int before = subtreeCnt[u];\n                int after = before + deltaVal[u];\n                bool b1 = before > 0, b2 = after > 0;\n                if (b1 != b2) dE += (b2 ? +spt.weightToParent[u] : -spt.weightToParent[u]);\n            }\n            return dE;\n        };\n\n        auto evalDelta = [&](int k, int to) -> ll {\n            int from = assign[k];\n            if (to == from) return 0LL;\n\n            int rFrom = (int)r[from][k];\n            int rTo = (int)r[to][k];\n\n            int oldPFrom = P[from], oldPTo = P[to];\n            bool fromInactive = (sz[from] == 1);\n            bool toActive = (sz[to] == 0);\n\n            ll dE = deltaEdge(from, to, fromInactive, toActive);\n\n            // apply fenwick/size temporarily\n            fenw[from].add(rFrom + 1, -1);\n            sz[from]--;\n            fenw[to].add(rTo + 1, +1);\n            sz[to]++;\n\n            int newPFrom = (sz[from] ? fenw[from].getMax(sz[from]) : 0);\n            int newPTo   = (sz[to] ? fenw[to].getMax(sz[to]) : 0);\n\n            ll dP = 1LL*newPFrom*newPFrom + 1LL*newPTo*newPTo\n                  - (1LL*oldPFrom*oldPFrom + 1LL*oldPTo*oldPTo);\n\n            // rollback\n            fenw[to].add(rTo + 1, -1);\n            sz[to]--;\n            fenw[from].add(rFrom + 1, +1);\n            sz[from]++;\n\n            return dP + dE;\n        };\n\n        auto commitMove = [&](int k, int to) {\n            int from = assign[k];\n            if (to == from) return;\n\n            int rFrom = (int)r[from][k];\n            int rTo = (int)r[to][k];\n\n            int oldPFrom = P[from], oldPTo = P[to];\n            bool fromInactive = (sz[from] == 1);\n            bool toActive = (sz[to] == 0);\n\n            // update fenwick/size\n            fenw[from].add(rFrom + 1, -1);\n            sz[from]--;\n            fenw[to].add(rTo + 1, +1);\n            sz[to]++;\n\n            int newPFrom = (sz[from] ? fenw[from].getMax(sz[from]) : 0);\n            int newPTo   = (sz[to] ? fenw[to].getMax(sz[to]) : 0);\n\n            Pcost += 1LL*newPFrom*newPFrom + 1LL*newPTo*newPTo\n                   - (1LL*oldPFrom*oldPFrom + 1LL*oldPTo*oldPTo);\n\n            // update subtreeCnt/edgeCost by toggles\n            if (fromInactive) {\n                for (int u : spt.anc[from]) {\n                    subtreeCnt[u]--;\n                    if (subtreeCnt[u] == 0) edgeCost -= spt.weightToParent[u];\n                }\n            }\n            if (toActive) {\n                for (int u : spt.anc[to]) {\n                    if (subtreeCnt[u] == 0) edgeCost += spt.weightToParent[u];\n                    subtreeCnt[u]++;\n                }\n            }\n\n            P[from] = newPFrom;\n            P[to] = newPTo;\n            assign[k] = to;\n\n            totalCost = Pcost + edgeCost;\n            if (totalCost < bestCost) {\n                bestCost = totalCost;\n                bestAssign = assign;\n            }\n        };\n\n        // Hill-climb: evaluate only top HILLCAP by need\n        vector<int> order(K);\n        iota(order.begin(), order.end(), 0);\n        int hillPasses = 3;\n\n        for (int pass = 0; pass < hillPasses && !timeUp(); pass++) {\n            shuffle(order.begin(), order.end(), rng);\n            bool any = false;\n            for (int k : order) {\n                if (timeUp()) break;\n                int from = assign[k];\n\n                ll bestDelta = 0;\n                int bestTo = -1;\n\n                int lim = min(HILLCAP, (int)candNeedSorted[k].size());\n                for (int i = 0; i < lim; i++) {\n                    int to = candNeedSorted[k][i];\n                    if (to == from) continue;\n                    ll d = evalDelta(k, to);\n                    if (d < bestDelta) {\n                        bestDelta = d;\n                        bestTo = to;\n                    }\n                }\n                if (bestTo != -1) {\n                    commitMove(k, bestTo);\n                    any = true;\n                }\n            }\n            if (!any) break;\n        }\n\n        // SA: keep exploration; 2-move uses top-subset by need\n        if (!timeUp()) {\n            auto rand01 = [&]()->double{\n                uint64_t r01raw = rng() >> 11;\n                return (double)r01raw / (double)(1ULL<<53);\n            };\n\n            auto pickTo = [&](int k, int from)->int{\n                // Bias strongly toward candNeedSorted prefix\n                const auto &ord = candNeedSorted[k];\n                if (ord.empty()) return from;\n                if ((int)ord.size() == 1) return ord[0];\n                int TB = min((int)ord.size(), 10);\n                for (int t = 0; t < 6; t++) {\n                    int to = ord[(size_t)(rng() % (uint64_t)TB)];\n                    if (to != from) return to;\n                }\n                // fallback uniform\n                for (int t = 0; t < 6; t++) {\n                    int to = ord[(size_t)(rng() % (uint64_t)ord.size())];\n                    if (to != from) return to;\n                }\n                return from;\n            };\n\n            double temp = 3.0e6;\n            int STEPS = max(20000, min(90000, timeLimitMs * 180));\n\n            for (int it = 0; it < STEPS && !timeUp(); it++) {\n                // 2-move attempt\n                if (K >= 2 && (rng() % 5ULL) == 0) {\n                    int k1 = (int)(rng() % (uint64_t)K);\n                    int k2 = (int)(rng() % (uint64_t)K);\n                    if (k1 == k2) continue;\n\n                    int from1 = assign[k1];\n                    int from2 = assign[k2];\n\n                    int to1 = pickTo(k1, from1);\n                    if (to1 == from1) continue;\n\n                    ll d1 = evalDelta(k1, to1);\n                    commitMove(k1, to1);\n\n                    // second step: enumerate top SUB2 by need\n                    const auto &ord2 = candNeedSorted[k2];\n                    if (ord2.empty()) { commitMove(k1, from1); continue; }\n\n                    ll bestD2 = (1LL<<62);\n                    int bestTo2 = -1;\n                    int lim2 = min(SUB2, (int)ord2.size());\n                    for (int i = 0; i < lim2; i++) {\n                        int cand2 = ord2[i];\n                        if (cand2 == from2) continue;\n                        ll d2 = evalDelta(k2, cand2);\n                        if (d2 < bestD2) {\n                            bestD2 = d2;\n                            bestTo2 = cand2;\n                        }\n                    }\n\n                    if (bestTo2 == -1) { // cannot do second step\n                        commitMove(k1, from1);\n                        continue;\n                    }\n\n                    ll dTotal = d1 + bestD2;\n                    bool accept = false;\n                    if (dTotal <= 0) accept = true;\n                    else if (rand01() < exp(-(double)dTotal / temp)) accept = true;\n\n                    if (accept) commitMove(k2, bestTo2);\n                    else commitMove(k1, from1); // rollback k1 only\n                    temp *= 0.9997;\n                    continue;\n                }\n\n                // 1-move SA\n                int k = (int)(rng() % (uint64_t)K);\n                int from = assign[k];\n                int to = pickTo(k, from);\n                if (to == from) continue;\n\n                ll d = evalDelta(k, to);\n                if (d <= 0) commitMove(k, to);\n                else if (rand01() < exp(-(double)d / temp)) commitMove(k, to);\n\n                temp *= 0.9997;\n            }\n        }\n\n        // Rebuild P and B from bestAssign\n        vector<int> sz2(N,0), P2(N,0);\n        for (int k = 0; k < K; k++) {\n            int s = bestAssign[k];\n            sz2[s]++;\n            P2[s] = max(P2[s], (int)r[s][k]);\n        }\n\n        vector<int> subtreeCnt2(N,0);\n        function<int(int)> dfs2 = [&](int v)->int{\n            int cnt = (sz2[v] > 0) ? 1 : 0;\n            for (int to : spt.children[v]) cnt += dfs2(to);\n            subtreeCnt2[v] = cnt;\n            return cnt;\n        };\n        dfs2(0);\n\n        vector<int> out(N + M, 0);\n        for (int i = 0; i < N; i++) out[i] = P2[i];\n        for (int v = 1; v < N; v++) {\n            if (subtreeCnt2[v] > 0) out[N + spt.parentEdgeId[v]] = 1;\n        }\n        return {bestCost, out};\n    };\n\n    // Global loop\n    auto overallStart = chrono::steady_clock::now();\n    auto elapsedMs = [&](){\n        return (int)chrono::duration_cast<chrono::milliseconds>(chrono::steady_clock::now() - overallStart).count();\n    };\n    auto timeUpOverall = [&](){ return elapsedMs() > 1900; };\n\n    int Lnear = 18, Lshallow = 8, ancestorSpan = 4, Lcap = 40;\n    int maxTrialsPerSPT = 5;\n\n    // Key improvement knobs\n    int HILLCAP = 14;  // only evaluate top-14 candidates in hill-climb\n    int SUB2 = 12;     // enumerate top-12 candidates in the 2-move second step\n\n    vector<uint64_t> sptSeeds = {\n        1234567ULL, 987654321ULL, 19260817ULL, 5555557ULL, 246813579ULL, 998244353ULL\n    };\n\n    ll bestCost = (1LL<<62);\n    vector<int> bestOut(N + M, 0);\n\n    int trialsLeft = (int)sptSeeds.size() * maxTrialsPerSPT;\n\n    for (int si = 0; si < (int)sptSeeds.size() && !timeUpOverall(); si++) {\n        SPT spt = buildSPT(sptSeeds[si]);\n        auto [cand, candNeedSorted] = buildCandidates(spt, Lnear, Lshallow, ancestorSpan, Lcap);\n\n        // Build initial assignments (4-5)\n        vector<vector<int>> inits;\n        inits.reserve(maxTrialsPerSPT);\n\n        // Init 0: minimum need among candidates\n        {\n            vector<int> a(K);\n            for (int k = 0; k < K; k++) {\n                int best = cand[k][0], bestNeed = (int)r[best][k];\n                for (int s : cand[k]) {\n                    int need = (int)r[s][k];\n                    if (need < bestNeed) { bestNeed = need; best = s; }\n                }\n                a[k] = best;\n            }\n            inits.push_back(std::move(a));\n        }\n\n        // Init 1: biased random among top-by-need prefix\n        {\n            mt19937_64 rng(7777 + si * 131);\n            vector<int> a(K);\n            for (int k = 0; k < K; k++) {\n                const auto &ord = candNeedSorted[k];\n                int TB = min(12, (int)ord.size());\n                a[k] = ord[(size_t)(rng() % (uint64_t)TB)];\n            }\n            inits.push_back(std::move(a));\n        }\n\n        // Init 2..: greedy\n        while ((int)inits.size() < maxTrialsPerSPT) {\n            uint64_t seed = 1000003ULL + (uint64_t)si * 999983ULL + (uint64_t)inits.size() * 12345ULL;\n            inits.push_back(greedyInit(spt, cand, seed));\n        }\n\n        for (int ti = 0; ti < (int)inits.size() && !timeUpOverall(); ti++) {\n            int remaining = 1900 - elapsedMs();\n            int tl = max(110, min(360, remaining / max(1, trialsLeft)));\n            trialsLeft--;\n\n            uint64_t trialSeed = sptSeeds[si] * 10000019ULL + (uint64_t)ti * 10007ULL + 89123ULL;\n            auto [cost, out] = solveTrial(spt, cand, candNeedSorted, inits[ti],\n                                            trialSeed, tl, HILLCAP, SUB2);\n            if (cost < bestCost) {\n                bestCost = cost;\n                bestOut = std::move(out);\n            }\n        }\n    }\n\n    // Output\n    for (int i = 0; i < N; i++) {\n        if (i) cout << ' ';\n        cout << bestOut[i];\n    }\n    cout << '\\n';\n    for (int j = 0; j < M; j++) {\n        if (j) cout << ' ';\n        cout << bestOut[N + j];\n    }\n    cout << '\\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 LIM = 10000;\nstatic constexpr int KEY_SAMP = 40;\nstatic constexpr int E_SAMP = 60;\n\nstruct SwapOp {\n    short x1, y1, x2, y2;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    auto id = [](int x, int y) -> int { return x * (x + 1) / 2 + y; };\n\n    vector<int> cx(V), cy(V);\n    for (int x = 0; x < N; x++) for (int y = 0; y <= x; y++) {\n        int idx = id(x, y);\n        cx[idx] = x;\n        cy[idx] = y;\n    }\n\n    // Read\n    vector<int> at(V), pos(V);\n    for (int x = 0; x < N; x++) for (int y = 0; y <= x; y++) {\n        int b; cin >> b;\n        int idx = id(x, y);\n        at[idx] = b;\n        pos[b] = idx;\n    }\n\n    // key partition by value rank: blocks 1,2,...,30\n    // pref[t] = sum_{i=1..t+1} i = (t+1)(t+2)/2, and block t is values in [pref[t-1], pref[t]-1]\n    vector<int> pref(N);\n    for (int t = 0; t < N; t++) pref[t] = (t + 1) * (t + 2) / 2;\n\n    vector<int> key(V);\n    for (int v = 0; v < V; v++) {\n        int t = 0;\n        while (t < N && v >= pref[t]) t++;\n        key[v] = t;\n    }\n\n    // Build cover edges: u at tier x -> child at tier x+1 (two children)\n    // store directed edges list (from[e] -> to[e])\n    // and for each cell, store up to 2 incoming/outgoing cover edges.\n    vector<int> from, to;\n    from.reserve(870);\n    to.reserve(870);\n\n    vector<array<int,2>> outEdge(V, array<int,2>{-1,-1});\n    vector<array<int,2>> inEdge(V, array<int,2>{-1,-1});\n\n    auto add_out = [&](int u, int eidx) {\n        if (outEdge[u][0] == -1) outEdge[u][0] = eidx;\n        else outEdge[u][1] = eidx;\n    };\n    auto add_in = [&](int v, int eidx) {\n        if (inEdge[v][0] == -1) inEdge[v][0] = eidx;\n        else inEdge[v][1] = eidx;\n    };\n\n    int M = 0;\n    for (int x = 0; x <= N - 2; x++) {\n        for (int y = 0; y <= x; y++) {\n            int u = id(x, y);\n            int c1 = id(x + 1, y);\n            int c2 = id(x + 1, y + 1);\n\n            int e1 = M++;\n            from.push_back(u); to.push_back(c1);\n            add_out(u, e1); add_in(c1, e1);\n\n            int e2 = M++;\n            from.push_back(u); to.push_back(c2);\n            add_out(u, e2); add_in(c2, e2);\n        }\n    }\n\n    auto affectedEdges = [&](int a, int b, int buf[16]) -> int {\n        int cnt = 0;\n        auto add = [&](int e) {\n            if (e < 0) return;\n            for (int i = 0; i < cnt; i++) if (buf[i] == e) return;\n            buf[cnt++] = e;\n        };\n        for (int k = 0; k < 2; k++) {\n            add(outEdge[a][k]); add(inEdge[a][k]);\n            add(outEdge[b][k]); add(inEdge[b][k]);\n        }\n        return cnt;\n    };\n\n    // Swap implementation\n    vector<SwapOp> ops;\n    ops.reserve(LIM);\n    int K = 0;\n\n    auto doSwap = [&](int a, int b) -> bool {\n        if (K >= LIM) return false;\n        if (a == b) return true;\n        ops.push_back(SwapOp{(short)cx[a], (short)cy[a], (short)cx[b], (short)cy[b]});\n        K++;\n        int va = at[a], vb = at[b];\n        swap(at[a], at[b]);\n        pos[va] = b;\n        pos[vb] = a;\n        return true;\n    };\n\n    // Stage 1: key violations along cover edges\n    vector<char> keyViol(M, 0);\n    deque<int> qKey;\n    int keyViolCnt = 0;\n\n    for (int e = 0; e < M; e++) {\n        int u = from[e], v = to[e];\n        bool w = key[at[u]] > key[at[v]];\n        keyViol[e] = (char)w;\n        if (w) { keyViolCnt++; qKey.push_back(e); }\n    }\n\n    auto computeKeyDelta = [&](int a, int b) -> int {\n        int buf[16];\n        int cnt = affectedEdges(a, b, buf);\n        int va = at[a], vb = at[b];\n        int oldSum = 0, newSum = 0;\n        for (int i = 0; i < cnt; i++) {\n            int e = buf[i];\n            oldSum += (keyViol[e] ? 1 : 0);\n            int u = from[e], v = to[e];\n            int newUVal = (u == a ? vb : (u == b ? va : at[u]));\n            int newVVal = (v == a ? vb : (v == b ? va : at[v]));\n            bool nw = key[newUVal] > key[newVVal];\n            newSum += (nw ? 1 : 0);\n        }\n        return newSum - oldSum;\n    };\n\n    auto updateKeyAround = [&](int a, int b, deque<int> &queue) {\n        int buf[16];\n        int cnt = affectedEdges(a, b, buf);\n        for (int i = 0; i < cnt; i++) {\n            int e = buf[i];\n            int u = from[e], v = to[e];\n            bool nw = key[at[u]] > key[at[v]];\n            if ((bool)keyViol[e] != nw) {\n                keyViolCnt += (nw ? +1 : -1);\n                keyViol[e] = (char)nw;\n                if (nw) queue.push_back(e);\n            }\n        }\n    };\n\n    int stuckKey = 0;\n    while (keyViolCnt > 0 && K < LIM) {\n        if (qKey.empty()) {\n            for (int e = 0; e < M; e++) if (keyViol[e]) qKey.push_back(e);\n            if (qKey.empty()) break;\n        }\n\n        vector<int> cand;\n        cand.reserve(KEY_SAMP);\n        while (!qKey.empty() && (int)cand.size() < KEY_SAMP) {\n            int e = qKey.front(); qKey.pop_front();\n            if (keyViol[e]) cand.push_back(e);\n        }\n\n        int bestE = -1;\n        int bestDelta = INT_MAX;\n\n        for (int e : cand) {\n            int a = from[e], b = to[e];\n            int delta = computeKeyDelta(a, b);\n            if (delta < bestDelta) {\n                bestDelta = delta;\n                bestE = e;\n            }\n        }\n\n        // Reinsert other candidates (keep queue alive)\n        for (int e : cand) if (e != bestE) qKey.push_back(e);\n\n        if (bestE == -1) break;\n        int a = from[bestE], b = to[bestE];\n\n        // Prefer non-increasing key violations; occasionally allow small increase if stuck.\n        bool accept = false;\n        if (bestDelta <= 0) accept = true;\n        else if (stuckKey > 200 && bestDelta <= 1) accept = true;\n\n        if (!accept) {\n            stuckKey++;\n            // As a fallback, accept best non-stale edge directly if it still violates.\n            // (This should be rare.)\n            if (bestDelta <= 2) accept = true;\n        }\n\n        if (!accept) break; // let Stage 2 handle remaining if any\n\n        if (!doSwap(a, b)) break;\n        updateKeyAround(a, b, qKey);\n        stuckKey = (bestDelta <= 0 ? 0 : stuckKey + 1);\n    }\n\n    // compute E and actViol\n    vector<char> actViol(M, 0);\n    long long Ecnt = 0;\n    for (int e = 0; e < M; e++) {\n        int u = from[e], v = to[e];\n        bool w = at[u] > at[v];\n        actViol[e] = (char)w;\n        if (w) Ecnt++;\n    }\n\n    if (Ecnt == 0) {\n        cout << K << \"\\n\";\n        for (auto &op : ops) cout << op.x1 << \" \" << op.y1 << \" \" << op.x2 << \" \" << op.y2 << \"\\n\";\n        return 0;\n    }\n\n    // Stage 2: fix only equal-key edges (but choose best delta)\n    deque<int> qAct;\n    for (int e = 0; e < M; e++) {\n        int u = from[e], v = to[e];\n        if (actViol[e] && key[at[u]] == key[at[v]]) qAct.push_back(e);\n    }\n\n    auto computeEDelta = [&](int a, int b) -> long long {\n        int buf[16];\n        int cnt = affectedEdges(a, b, buf);\n        int va = at[a], vb = at[b];\n        long long oldSum = 0, newSum = 0;\n        for (int i = 0; i < cnt; i++) {\n            int e = buf[i];\n            oldSum += (actViol[e] ? 1 : 0);\n            int u = from[e], v = to[e];\n            int newUVal = (u == a ? vb : (u == b ? va : at[u]));\n            int newVVal = (v == a ? vb : (v == b ? va : at[v]));\n            bool nw = newUVal > newVVal;\n            newSum += (nw ? 1 : 0);\n        }\n        return newSum - oldSum;\n    };\n\n    auto updateActAround = [&](int a, int b, deque<int> &queue) {\n        int buf[16];\n        int cnt = affectedEdges(a, b, buf);\n        for (int i = 0; i < cnt; i++) {\n            int e = buf[i];\n            int u = from[e], v = to[e];\n            bool nw = at[u] > at[v];\n            if ((bool)actViol[e] != nw) {\n                Ecnt += (nw ? +1 : -1);\n                actViol[e] = (char)nw;\n            }\n            // Always consider pushing if violated and keys equal\n            if (nw) {\n                if (key[at[u]] == key[at[v]]) queue.push_back(e);\n            }\n        }\n    };\n\n    int stuckE = 0;\n    while (Ecnt > 0 && K < LIM) {\n        if (qAct.empty()) {\n            for (int e = 0; e < M; e++) {\n                if (actViol[e]) {\n                    int u = from[e], v = to[e];\n                    if (key[at[u]] == key[at[v]]) qAct.push_back(e);\n                }\n            }\n            if (qAct.empty()) break; // no equal-key moves\n        }\n\n        vector<int> cand;\n        cand.reserve(E_SAMP);\n        while (!qAct.empty() && (int)cand.size() < E_SAMP) {\n            int e = qAct.front(); qAct.pop_front();\n            if (!actViol[e]) continue;\n            int u = from[e], v = to[e];\n            if (key[at[u]] != key[at[v]]) continue;\n            cand.push_back(e);\n        }\n        if (cand.empty()) continue;\n\n        int bestE = -1;\n        long long bestDelta = (1LL<<60);\n\n        for (int e : cand) {\n            int a = from[e], b = to[e];\n            long long delta = computeEDelta(a, b);\n            if (delta < bestDelta) {\n                bestDelta = delta;\n                bestE = e;\n            }\n        }\n\n        for (int e : cand) if (e != bestE) qAct.push_back(e);\n\n        if (bestE == -1) continue;\n        int a = from[bestE], b = to[bestE];\n\n        // Accept rules: prefer delta<0, allow delta==0, avoid delta>0 unless stuck.\n        bool accept = false;\n        if (bestDelta < 0) accept = true;\n        else if (bestDelta == 0) accept = (stuckE > 50); // reduce plateau wandering\n        else {\n            // bestDelta > 0\n            accept = (stuckE > 400 && bestDelta <= 2);\n        }\n\n        if (!accept) {\n            stuckE++;\n            // If very stuck, do a deterministic rescue: take any violated equal-key edge.\n            if (stuckE > 800) {\n                int rescueE = -1;\n                for (int e : cand) { if (actViol[e]) { rescueE = e; break; } }\n                if (rescueE == -1) break;\n                a = from[rescueE]; b = to[rescueE];\n                if (!doSwap(a, b)) break;\n                updateActAround(a, b, qAct);\n                stuckE = 0;\n            }\n            continue;\n        }\n\n        if (!doSwap(a, b)) break;\n        updateActAround(a, b, qAct);\n        stuckE = 0;\n    }\n\n    cout << K << \"\\n\";\n    for (auto &op : ops) cout << op.x1 << \" \" << op.y1 << \" \" << op.x2 << \" \" << op.y2 << \"\\n\";\n    return 0;\n}","toyota2023summer-final":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\n\nstatic const int dx4[4] = {-1, 1, 0, 0}; // up, down, left, right in i\nstatic const int dy4[4] = {0, 0, -1, 1}; // u, d, l, r in j\n\nstruct Tree {\n    int V = 0;\n    int ent = -1;\n    vector<int> parent;\n    vector<int> depth;\n    vector<int> bfsOrder;\n    vector<vector<int>> children; // rooted tree edges: parent -> children\n};\n\nstatic Tree build_bfs_tree(\n    int D,\n    const vector<vector<int>> &id,\n    int ent,\n    const vector<pair<int,int>> &coord,\n    const array<int,4> &dirOrder\n){\n    int V = 0;\n    for (int i = 0; i < D; i++) for (int j = 0; j < D; j++)\n        if (id[i][j] >= 0) V = max(V, id[i][j] + 1);\n\n    vector<int> parent(V, -1), depth(V, -1), bfsOrder(V, -1);\n    vector<vector<int>> children(V);\n    vector<char> vis(V, 0);\n\n    queue<int> q;\n    vis[ent] = 1;\n    depth[ent] = 0;\n    parent[ent] = -1;\n    q.push(ent);\n\n    // Choose parent by BFS with specified neighbor order.\n    while (!q.empty()) {\n        int v = q.front(); q.pop();\n        auto [x, y] = coord[v];\n        for (int k = 0; k < 4; k++) {\n            int dir = dirOrder[k]; // 0..3\n            int nx = x + dx4[dir];\n            int ny = y + dy4[dir];\n            if (nx < 0 || nx >= D || ny < 0 || ny >= D) continue;\n            int nid = id[nx][ny];\n            if (nid < 0) continue;\n            if (vis[nid]) continue;\n            vis[nid] = 1;\n            parent[nid] = v;\n            depth[nid] = depth[v] + 1;\n            q.push(nid);\n        }\n    }\n\n    // children\n    for (int v = 0; v < V; v++) {\n        if (v == ent) continue;\n        int p = parent[v];\n        if (p >= 0) children[p].push_back(v);\n    }\n\n    // bfsOrder along the rooted-tree edges (level-order within tree)\n    vector<char> inq(V, 0);\n    queue<int> qq;\n    bfsOrder[ent] = 0;\n    inq[ent] = 1;\n    qq.push(ent);\n    int ord = 1;\n    while (!qq.empty()) {\n        int v = qq.front(); qq.pop();\n        for (int ch : children[v]) {\n            if (inq[ch]) continue;\n            inq[ch] = 1;\n            bfsOrder[ch] = ord++;\n            qq.push(ch);\n        }\n    }\n\n    Tree t;\n    t.V = V;\n    t.ent = ent;\n    t.parent = move(parent);\n    t.depth = move(depth);\n    t.bfsOrder = move(bfsOrder);\n    t.children = move(children);\n    return t;\n}\n\nstatic vector<int> compute_subtree_sizes(const Tree &t) {\n    vector<int> sub(t.V, 1);\n    vector<int> nodes(t.V);\n    iota(nodes.begin(), nodes.end(), 0);\n    sort(nodes.begin(), nodes.end(), [&](int a,int b){\n        return t.depth[a] > t.depth[b];\n    });\n    for (int v : nodes) {\n        if (v == t.ent) continue;\n        int p = t.parent[v];\n        if (p >= 0) sub[p] += sub[v];\n    }\n    return sub;\n}\n\n// simulate greedy removal order under structural priorities (no labels).\n// parent must be removed before child (ancestor-before-descendant poset).\nstatic vector<int> simulate_proxy_pos(\n    const Tree &t,\n    const vector<ll> &key1,\n    const vector<ll> &key2\n){\n    int M = t.V - 1;\n    vector<int> pos(t.V, -1);\n    vector<char> removed(t.V, 0);\n\n    struct Node {\n        ll k1, k2;\n        int ord;\n        int v;\n    };\n    struct Cmp {\n        bool operator()(const Node &a, const Node &b) const {\n            if (a.k1 != b.k1) return a.k1 > b.k1; // min heap\n            if (a.k2 != b.k2) return a.k2 > b.k2;\n            if (a.ord != b.ord) return a.ord > b.ord;\n            return a.v > b.v;\n        }\n    };\n\n    priority_queue<Node, vector<Node>, Cmp> pq;\n    for (int ch : t.children[t.ent]) {\n        pq.push({key1[ch], key2[ch], t.bfsOrder[ch], ch});\n    }\n\n    int cnt = 0;\n    while (cnt < M) {\n        auto cur = pq.top(); pq.pop();\n        int v = cur.v;\n        if (removed[v]) continue;\n        removed[v] = 1;\n        pos[v] = cnt++;\n        for (int ch : t.children[v]) {\n            if (!removed[ch]) pq.push({key1[ch], key2[ch], t.bfsOrder[ch], ch});\n        }\n    }\n    return pos;\n}\n\nstruct Fenwick {\n    int n;\n    vector<int> bit;\n    Fenwick(int n=0): n(n), bit(n+1, 0) {}\n    void add(int i, int v){ // i: 0-index\n        for(i++; i <= n; i += i&-i) bit[i] += v;\n    }\n    int sumInclusive(int r){ // sum [0..r]\n        if(r < 0) return 0;\n        int s = 0;\n        for(int i = r+1; i > 0; i -= i&-i) s += bit[i];\n        return s;\n    }\n};\n\nstatic ll count_inversions(const vector<int> &a, int maxVal) {\n    int n = (int)a.size();\n    Fenwick fw(maxVal + 1);\n    ll inv = 0;\n    for (int i = 0; i < n; i++) {\n        int x = a[i];\n        int le = fw.sumInclusive(x); // count of <= x so far\n        inv += (ll)i - le;           // previous > x\n        fw.add(x, 1);\n    }\n    return inv;\n}\n\nstruct InsertionHeuristic {\n    int V = 0;\n    int M = 0;\n    int P = 0;\n    vector<vector<int>> proxyPos; // P x V\n};\n\nstatic inline ll candidate_cost(\n    int v, int tval,\n    const InsertionHeuristic &ih,\n    const vector<int> &assignedNodes,\n    const vector<int> &label\n){\n    ll total = 0;\n    for (int p = 0; p < ih.P; p++) {\n        int pv = ih.proxyPos[p][v];\n        for (int u : assignedNodes) {\n            int pu = ih.proxyPos[p][u];\n            int lu = label[u];\n            if (pu < pv) {\n                if (lu > tval) total++;\n            } else { // pu > pv (proxy ranks are permutation)\n                if (tval > lu) total++;\n            }\n        }\n    }\n    return total;\n}\n\nstatic int pick_best_node(\n    const Tree &t,\n    const InsertionHeuristic &ih,\n    const vector<int> &readyVec,\n    const vector<char> &readyFlag,\n    const vector<int> &assignedNodes,\n    const vector<int> &label,\n    int tval\n){\n    int bestV = -1;\n    ll bestCost = (1LL<<62);\n    ll bestTie = (1LL<<62);\n\n    for (int v : readyVec) {\n        if (!readyFlag[v]) continue;\n        ll c = candidate_cost(v, tval, ih, assignedNodes, label);\n\n        ll tie = 0;\n        for (int p = 0; p < ih.P; p++) {\n            int pv = ih.proxyPos[p][v];\n            tie += llabs((ll)pv - (ll)tval);\n        }\n\n        if (c < bestCost || (c == bestCost && tie < bestTie)) {\n            bestCost = c;\n            bestTie = tie;\n            bestV = v;\n        }\n    }\n    return bestV;\n}\n\nstatic void compute_tin_tout(const Tree &t, vector<int> &tin, vector<int> &tout){\n    int V = t.V;\n    tin.assign(V, -1);\n    tout.assign(V, -1);\n    int timer = 0;\n    vector<int> it(V, 0);\n    vector<int> st;\n    st.reserve(V);\n    st.push_back(t.ent);\n    tin[t.ent] = timer++;\n    while (!st.empty()) {\n        int v = st.back();\n        if (it[v] < (int)t.children[v].size()) {\n            int to = t.children[v][it[v]++];\n            tin[to] = timer++;\n            st.push_back(to);\n        } else {\n            tout[v] = timer;\n            st.pop_back();\n        }\n    }\n}\n\nstatic inline bool isAncestor(const vector<int> &tin, const vector<int> &tout, int a, int b){\n    return tin[a] <= tin[b] && tin[b] < tout[a];\n}\n\n// swap order adjacent elements if it doesn't violate partial order.\nstatic void swap_improve_order(\n    const Tree &t,\n    const vector<int> &labels,\n    vector<int> &orderNodes,\n    const vector<int> &tin,\n    const vector<int> &tout\n){\n    int M = (int)orderNodes.size();\n    auto canSwapAdj = [&](int A, int B)->bool{\n        // if one is ancestor of the other, swapping breaks feasibility\n        return !(isAncestor(tin,tout,A,B) || isAncestor(tin,tout,B,A));\n    };\n\n    for (int pass = 0; pass < M; pass++) {\n        bool changed = false;\n        for (int i = 0; i + 1 < M; i++) {\n            int A = orderNodes[i];\n            int B = orderNodes[i+1];\n            if (labels[A] > labels[B] && canSwapAdj(A,B)) {\n                swap(orderNodes[i], orderNodes[i+1]);\n                changed = true;\n            }\n        }\n        if (!changed) break;\n    }\n}\n\nstatic vector<int> build_transport_order_greedy(\n    const Tree &t,\n    const vector<int> &labels,\n    int mode\n){\n    int M = t.V - 1;\n    vector<char> removed(t.V, 0);\n\n    struct Node { int k1, k2, ord, v; };\n    struct Cmp {\n        bool operator()(const Node& a, const Node& b) const {\n            if (a.k1 != b.k1) return a.k1 > b.k1; // min by k1\n            if (a.k2 != b.k2) return a.k2 > b.k2;\n            if (a.ord != b.ord) return a.ord > b.ord;\n            return a.v > b.v;\n        }\n    };\n    priority_queue<Node, vector<Node>, Cmp> pq;\n\n    auto push = [&](int v){\n        int lab = labels[v];\n        if (mode == 0) {\n            // min label; break ties by shallower depth then bfsOrder\n            pq.push({lab, t.depth[v], t.bfsOrder[v], v});\n        } else if (mode == 1) {\n            // min label; break ties by deeper depth\n            pq.push({lab, -t.depth[v], t.bfsOrder[v], v});\n        } else {\n            // max label; break ties by shallower depth\n            pq.push({-lab, t.depth[v], t.bfsOrder[v], v});\n        }\n    };\n\n    for (int ch : t.children[t.ent]) push(ch);\n\n    vector<int> order;\n    order.reserve(M);\n    while ((int)order.size() < M) {\n        auto cur = pq.top(); pq.pop();\n        int v = cur.v;\n        if (removed[v]) continue;\n        removed[v] = 1;\n        order.push_back(v);\n        for (int ch : t.children[v]) if (!removed[ch]) push(ch);\n    }\n    return order;\n}\n\nstatic ll simulate_pipeline(\n    const Tree &t,\n    const InsertionHeuristic &ih,\n    const vector<int> &perm,   // arrival order labels t_d = perm[d]\n    const vector<int> &tin,\n    const vector<int> &tout\n){\n    int M = ih.M;\n\n    // online insertion simulation producing label assignment\n    vector<int> labels(t.V, -1);\n    vector<int> remChildCnt(t.V, 0);\n    for (int v = 0; v < t.V; v++) {\n        if (v == t.ent) continue;\n        remChildCnt[v] = (int)t.children[v].size();\n    }\n\n    vector<char> readyFlag(t.V, 0);\n    vector<int> readyVec;\n    readyVec.reserve(M);\n    for (int v = 0; v < t.V; v++) {\n        if (v == t.ent) continue;\n        if (remChildCnt[v] == 0) {\n            readyFlag[v] = 1;\n            readyVec.push_back(v);\n        }\n    }\n\n    vector<int> assignedNodes;\n    assignedNodes.reserve(M);\n\n    for (int d = 0; d < M; d++) {\n        int t_d = perm[d];\n        int v = pick_best_node(t, ih, readyVec, readyFlag, assignedNodes, labels, t_d);\n\n        readyFlag[v] = 0;\n        labels[v] = t_d;\n        assignedNodes.push_back(v);\n\n        int p = t.parent[v];\n        if (p >= 0 && p != t.ent) {\n            remChildCnt[p]--;\n            if (remChildCnt[p] == 0) {\n                readyFlag[p] = 1;\n                readyVec.push_back(p);\n            }\n        }\n    }\n\n    // offline transport: try multiple modes + constrained swap improvement\n    ll bestInv = (1LL<<62);\n    vector<int> bestOrder;\n\n    for (int mode = 0; mode < 3; mode++) {\n        vector<int> orderNodes = build_transport_order_greedy(t, labels, mode);\n        swap_improve_order(t, labels, orderNodes, tin, tout);\n\n        vector<int> seq;\n        seq.reserve(M);\n        for (int v : orderNodes) seq.push_back(labels[v]);\n        ll inv = count_inversions(seq, M-1);\n        if (inv < bestInv) {\n            bestInv = inv;\n            bestOrder = move(orderNodes);\n        }\n    }\n    return bestInv;\n}\n\nint main(){\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int D, N;\n    cin >> D >> N;\n    vector<vector<bool>> obs(D, vector<bool>(D,false));\n    vector<pair<int,int>> obstacles;\n    obstacles.reserve(N);\n    for (int k=0;k<N;k++){\n        int ri, rj;\n        cin >> ri >> rj;\n        obs[ri][rj] = true;\n        obstacles.push_back({ri,rj});\n    }\n\n    int ent_i = 0, ent_j = (D-1)/2;\n\n    vector<vector<int>> id(D, vector<int>(D, -1));\n    vector<pair<int,int>> coord;\n    coord.reserve(D*D);\n\n    int V = 0;\n    for (int i=0;i<D;i++) for (int j=0;j<D;j++){\n        if (obs[i][j]) continue;\n        id[i][j] = V++;\n        coord.push_back({i,j});\n    }\n\n    int ent = id[ent_i][ent_j];\n    int M = V - 1;\n\n    vector<array<int,4>> dirCandidates = {\n        array<int,4>{0,3,1,2},\n        array<int,4>{0,2,1,3},\n        array<int,4>{1,3,0,2},\n        array<int,4>{1,2,0,3},\n        array<int,4>{3,0,2,1},\n        array<int,4>{2,0,3,1},\n    };\n\n    // deterministic seed base\n    auto mix64 = [](uint64_t x)->uint64_t{\n        x ^= x >> 33;\n        x *= 0xff51afd7ed558ccdULL;\n        x ^= x >> 33;\n        x *= 0xc4ceb9fe1a85ec53ULL;\n        x ^= x >> 33;\n        return x;\n    };\n\n    uint64_t base = 0x123456789abcdefULL;\n    for (auto [a,b] : obstacles) base ^= mix64((uint64_t)a*1315423911ULL + (uint64_t)b*2654435761ULL + 0x9e3779b97f4a7c15ULL);\n    base ^= mix64((uint64_t)N * 1000003ULL);\n\n    int S = 2; // samples per tree candidate (tree evaluation now matches final pipeline)\n    ll bestAvg = (1LL<<62);\n    Tree bestTree;\n    InsertionHeuristic bestIH;\n\n    for (int ci = 0; ci < (int)dirCandidates.size(); ci++) {\n        auto dirOrder = dirCandidates[ci];\n        Tree t = build_bfs_tree(D, id, ent, coord, dirOrder);\n\n        // structural proxy preparation\n        auto sub = compute_subtree_sizes(t);\n\n        vector<ll> key1a(t.V), key2a(t.V);\n        vector<ll> key1b(t.V), key2b(t.V);\n        vector<ll> key1c(t.V), key2c(t.V);\n        vector<ll> key1d(t.V), key2d(t.V);\n\n        for (int v=0; v<t.V; v++){\n            if (v == t.ent) continue;\n            key1a[v] = t.depth[v];      key2a[v] = 0;\n            key1b[v] = t.depth[v];      key2b[v] = - (ll)sub[v];\n            key1c[v] = t.depth[v];      key2c[v] = + (ll)sub[v];\n            key1d[v] = - (ll)t.depth[v];key2d[v] = + (ll)sub[v];\n        }\n\n        vector<vector<int>> proxyPos;\n        proxyPos.push_back(simulate_proxy_pos(t, key1a, key2a));\n        proxyPos.push_back(simulate_proxy_pos(t, key1b, key2b));\n        proxyPos.push_back(simulate_proxy_pos(t, key1c, key2c));\n        proxyPos.push_back(simulate_proxy_pos(t, key1d, key2d));\n\n        InsertionHeuristic ih;\n        ih.V = t.V;\n        ih.M = M;\n        ih.P = (int)proxyPos.size();\n        ih.proxyPos = move(proxyPos);\n\n        // ancestor info for swap feasibility\n        vector<int> tin, tout;\n        compute_tin_tout(t, tin, tout);\n\n        ll sumBestInv = 0;\n        for (int s = 0; s < S; s++) {\n            // deterministic permutation\n            uint64_t seed = mix64(base ^ (uint64_t)ci * 1000003ULL ^ (uint64_t)s * 10007ULL);\n            mt19937 rng((uint32_t)seed);\n\n            vector<int> perm(M);\n            iota(perm.begin(), perm.end(), 0);\n            shuffle(perm.begin(), perm.end(), rng);\n\n            sumBestInv += simulate_pipeline(t, ih, perm, tin, tout);\n        }\n        ll avg = sumBestInv / S;\n\n        if (avg < bestAvg) {\n            bestAvg = avg;\n            bestTree = move(t);\n            bestIH = move(ih);\n        }\n    }\n\n    // ===== Real online insertion with bestTree/bestIH =====\n    const Tree &t = bestTree;\n    const InsertionHeuristic &ih = bestIH;\n\n    vector<int> remChildCnt(t.V, 0);\n    for (int v=0; v<t.V; v++){\n        if(v == t.ent) continue;\n        remChildCnt[v] = (int)t.children[v].size();\n    }\n\n    vector<char> readyFlag(t.V, 0);\n    vector<int> readyVec;\n    readyVec.reserve(M);\n    for (int v=0; v<t.V; v++){\n        if(v == t.ent) continue;\n        if(remChildCnt[v] == 0){\n            readyFlag[v] = 1;\n            readyVec.push_back(v);\n        }\n    }\n\n    vector<int> labels(t.V, -1);\n    vector<int> assignedNodes;\n    assignedNodes.reserve(M);\n\n    for (int d=0; d<M; d++){\n        int t_d;\n        cin >> t_d;\n\n        int v = pick_best_node(t, ih, readyVec, readyFlag, assignedNodes, labels, t_d);\n\n        auto [pi,pj] = coord[v];\n        cout << pi << ' ' << pj << \"\\n\" << flush;\n\n        readyFlag[v] = 0;\n        labels[v] = t_d;\n        assignedNodes.push_back(v);\n\n        int p = t.parent[v];\n        if(p >= 0 && p != t.ent){\n            remChildCnt[p]--;\n            if(remChildCnt[p] == 0){\n                readyFlag[p] = 1;\n                readyVec.push_back(p);\n            }\n        }\n    }\n\n    // ===== Real transport: same refined pipeline as evaluation =====\n    vector<int> tin, tout;\n    compute_tin_tout(t, tin, tout);\n\n    ll bestInv = (1LL<<62);\n    vector<int> bestOrderNodes;\n\n    for (int mode=0; mode<3; mode++){\n        vector<int> orderNodes = build_transport_order_greedy(t, labels, mode);\n        swap_improve_order(t, labels, orderNodes, tin, tout);\n\n        vector<int> seq;\n        seq.reserve(M);\n        for(int v: orderNodes) seq.push_back(labels[v]);\n        ll inv = count_inversions(seq, M-1);\n        if(inv < bestInv){\n            bestInv = inv;\n            bestOrderNodes = move(orderNodes);\n        }\n    }\n\n    for (int k=0;k<M;k++){\n        auto [qi,qj] = coord[bestOrderNodes[k]];\n        cout << qi << ' ' << qj << \"\\n\" << flush;\n    }\n    return 0;\n}","ahc024":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const int DIRS[4][2] = {{1,0},{-1,0},{0,1},{0,-1}};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int n, m;\n    cin >> n >> m;\n    vector<vector<int>> a(n, vector<int>(n));\n    for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) cin >> a[i][j];\n\n    const int N = n * n;\n    auto id = [&](int i, int j) { return i * n + j; };\n    auto ij = [&](int v) { return pair<int,int>(v / n, v % n); };\n\n    // neighbor list for within-grid traversal\n    vector<array<int,4>> nb(N);\n    for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) {\n        int v = id(i,j);\n        for (int k = 0; k < 4; k++) {\n            int ni = i + DIRS[k][0], nj = j + DIRS[k][1];\n            nb[v][k] = (0 <= ni && ni < n && 0 <= nj && nj < n) ? id(ni,nj) : -1;\n        }\n    }\n\n    // original adjacency matrix among colors\n    vector<vector<unsigned char>> adjOrig(m+1, vector<unsigned char>(m+1, 0));\n    for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) {\n        int c1 = a[i][j];\n        for (int k = 0; k < 4; k++) {\n            int ni = i + DIRS[k][0], nj = j + DIRS[k][1];\n            int c2 = (ni < 0 || ni >= n || nj < 0 || nj >= n) ? 0 : a[ni][nj];\n            if (c1 == c2) continue;\n            int x = min(c1,c2), y = max(c1,c2);\n            adjOrig[x][y] = 1;\n        }\n    }\n\n    // touchOutside and boundary cells\n    vector<unsigned char> touchOutside(m+1, 0);\n    vector<vector<int>> boundaryCells(m+1);\n    for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) {\n        int c = a[i][j];\n        if (i==0 || i==n-1 || j==0 || j==n-1) {\n            touchOutside[c] = 1;\n            boundaryCells[c].push_back(id(i,j));\n        }\n    }\n\n    // forbidden colors: not touching outside in original\n    vector<unsigned char> forbidden(m+1, 0);\n    for (int c = 1; c <= m; c++) forbidden[c] = !touchOutside[c];\n\n    // isColor and posByColor\n    vector<vector<unsigned char>> isColor(m+1, vector<unsigned char>(N, 0));\n    vector<vector<int>> posByColor(m+1);\n    for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) {\n        int c = a[i][j];\n        int v = id(i,j);\n        isColor[c][v] = 1;\n        posByColor[c].push_back(v);\n    }\n\n    // mustKeepAllowed[c] for allowed colors:\n    // keep every allowed cell adjacent to some forbidden-color cell in original\n    vector<vector<int>> mustKeepAllowed(m+1);\n    for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) {\n        int c = a[i][j];\n        if (c == 0 || forbidden[c]) continue;\n        bool ok = false;\n        for (int k = 0; k < 4; k++) {\n            int ni = i + DIRS[k][0], nj = j + DIRS[k][1];\n            if (ni < 0 || ni >= n || nj < 0 || nj >= n) continue;\n            int cc = a[ni][nj];\n            if (cc != 0 && forbidden[cc]) { ok = true; break; }\n        }\n        if (ok) mustKeepAllowed[c].push_back(id(i,j));\n    }\n\n    // representative edges for allowed-allowed adjacencies: store endpoint pair for each adjacency between colors in original\n    vector<vector<vector<pair<int,int>>>> repEdges(m+1, vector<vector<pair<int,int>>>(m+1));\n    for (int i = 0; i < n; i++) for (int j = 0; j+1 < n; j++) {\n        int u = a[i][j], v = a[i][j+1];\n        if (u == 0 || v == 0) continue;\n        if (u == v) continue;\n        if (forbidden[u] || forbidden[v]) continue;\n        int x = min(u,v), y = max(u,v);\n        int id_x = (u == x) ? id(i,j) : id(i,j+1);\n        int id_y = (u == x) ? id(i,j+1) : id(i,j);\n        repEdges[x][y].push_back({id_x, id_y});\n    }\n    for (int i = 0; i+1 < n; i++) for (int j = 0; j < n; j++) {\n        int u = a[i][j], v = a[i+1][j];\n        if (u == 0 || v == 0) continue;\n        if (u == v) continue;\n        if (forbidden[u] || forbidden[v]) continue;\n        int x = min(u,v), y = max(u,v);\n        int id_x = (u == x) ? id(i,j) : id(i+1,j);\n        int id_y = (u == x) ? id(i+1,j) : id(i,j);\n        repEdges[x][y].push_back({id_x, id_y});\n    }\n\n    // list of allowed-allowed adjacent color pairs present in original\n    vector<pair<int,int>> allowedAdjPairs;\n    for (int x = 1; x <= m; x++) if (!forbidden[x]) {\n        for (int y = x+1; y <= m; y++) if (!forbidden[y]) {\n            if (adjOrig[x][y] && !repEdges[x][y].empty()) allowedAdjPairs.push_back({x,y});\n        }\n    }\n\n    // Precompute distToMustKeep and distToBoundary for allowed colors\n    vector<vector<int>> distToMustKeep(m+1, vector<int>(N, -1));\n    vector<vector<int>> distToBoundary(m+1, vector<int>(N, -1));\n\n    auto bfsMultiSource = [&](int c, const vector<int>& sources, vector<int>& distOut) {\n        fill(distOut.begin(), distOut.end(), -1);\n        queue<int> q;\n        for (int s : sources) {\n            if (!isColor[c][s]) continue;\n            distOut[s] = 0;\n            q.push(s);\n        }\n        while(!q.empty()){\n            int v = q.front(); q.pop();\n            auto [i,j] = ij(v);\n            for (int k = 0; k < 4; k++) {\n                int u = nb[v][k];\n                if (u == -1) continue;\n                if (!isColor[c][u]) continue;\n                if (distOut[u] != -1) continue;\n                distOut[u] = distOut[v] + 1;\n                q.push(u);\n            }\n        }\n    };\n\n    for (int c = 1; c <= m; c++) if (!forbidden[c]) {\n        if (!mustKeepAllowed[c].empty())\n            bfsMultiSource(c, mustKeepAllowed[c], distToMustKeep[c]);\n        if (!boundaryCells[c].empty())\n            bfsMultiSource(c, boundaryCells[c], distToBoundary[c]);\n    }\n\n    // RNG\n    mt19937_64 rng((uint64_t)chrono::high_resolution_clock::now().time_since_epoch().count());\n    auto rndInt = [&](int bound)->int { return (int)(rng() % (uint64_t)bound); };\n\n    // BFS distance within original color c\n    auto bfsDistWithinColor = [&](int c, int s, vector<int>& distOut) {\n        fill(distOut.begin(), distOut.end(), -1);\n        queue<int> q;\n        distOut[s] = 0;\n        q.push(s);\n        while(!q.empty()){\n            int v = q.front(); q.pop();\n            for (int k = 0; k < 4; k++) {\n                int u = nb[v][k];\n                if (u == -1) continue;\n                if (!isColor[c][u]) continue;\n                if (distOut[u] != -1) continue;\n                distOut[u] = distOut[v] + 1;\n                q.push(u);\n            }\n        }\n    };\n\n    // BFS shortest path within original color c from s to t; mark union along ONE shortest path found by BFS parents\n    auto bfsPathMark = [&](int c, int s, int t, vector<unsigned char>& keepMask) {\n        vector<int> parent(N, -1);\n        queue<int> q;\n        parent[s] = s;\n        q.push(s);\n        while(!q.empty()){\n            int v = q.front(); q.pop();\n            if (v == t) break;\n            for (int k = 0; k < 4; k++) {\n                int u = nb[v][k];\n                if (u == -1) continue;\n                if (!isColor[c][u]) continue;\n                if (parent[u] != -1) continue;\n                parent[u] = v;\n                q.push(u);\n            }\n        }\n        if (parent[t] == -1) return;\n        int cur = t;\n        while(true){\n            keepMask[cur] = 1;\n            if (cur == s) break;\n            cur = parent[cur];\n            if (cur == -1) break;\n        }\n    };\n\n    // Connectivity repair: connect components of color c in current b using MST over component reps (keep previous working logic)\n    // (We focus improvements on Steiner stage.)\n    auto connectColorMST = [&](vector<vector<int>>& b, int c) {\n        vector<unsigned char> vis(N, 0);\n        vector<int> compReps;\n        queue<int> q;\n\n        for (int v : posByColor[c]) {\n            if (b[v/n][v%n] != c) continue;\n            if (vis[v]) continue;\n            vis[v] = 1;\n            compReps.push_back(v);\n            q.push(v);\n            while(!q.empty()){\n                int cur = q.front(); q.pop();\n                for (int k = 0; k < 4; k++) {\n                    int u = nb[cur][k];\n                    if (u == -1) continue;\n                    if (vis[u]) continue;\n                    if (b[u/n][u%n] != c) continue;\n                    vis[u] = 1;\n                    q.push(u);\n                }\n            }\n        }\n        int k = (int)compReps.size();\n        if (k <= 1) return;\n\n        // compute distances between reps via BFS each time\n        vector<int> dist(N);\n        vector<vector<int>> distMat(k, vector<int>(k, -1));\n        for (int i = 0; i < k; i++) {\n            bfsDistWithinColor(c, compReps[i], dist);\n            for (int j = 0; j < k; j++) distMat[i][j] = dist[compReps[j]];\n        }\n\n        // Prim MST on component reps\n        vector<int> key(k, INT_MAX), parent(k, -1);\n        vector<unsigned char> used(k, 0);\n        int root = rndInt(k);\n        key[root] = 0;\n\n        for (int it = 0; it < k; it++) {\n            int v = -1;\n            for (int i = 0; i < k; i++) if (!used[i] && (v==-1 || key[i] < key[v])) v = i;\n            used[v] = 1;\n            for (int u = 0; u < k; u++) if (!used[u]) {\n                int w = distMat[v][u];\n                if (w >= 0 && w < key[u]) {\n                    key[u] = w;\n                    parent[u] = v;\n                }\n            }\n        }\n\n        // keep all already-colored-c cells\n        vector<unsigned char> keepMask(N, 0);\n        for (int v : posByColor[c]) if (b[v/n][v%n] == c) keepMask[v] = 1;\n\n        // add shortest paths along MST edges\n        for (int i = 0; i < k; i++) if (i != root) {\n            int p = parent[i];\n            if (p < 0) continue;\n            bfsPathMark(c, compReps[p], compReps[i], keepMask);\n        }\n\n        for (int v = 0; v < N; v++) if (keepMask[v]) b[v/n][v%n] = c;\n    };\n\n    // Improved Steiner construction for allowed color:\n    // incremental Prim-like Steiner where sources are vertices already connected to the current tree.\n    auto buildSteinerIncremental = [&](vector<vector<int>>& b, int c, const vector<int>& terminals, int rootCompIdx) {\n        if (terminals.empty()) return;\n\n        // Determine terminal components under adjacency of terminal vertices only\n        vector<unsigned char> isTerm(N, 0), seenTerm(N, 0);\n        for (int t : terminals) isTerm[t] = 1;\n\n        vector<vector<int>> compTerms;\n        vector<int> compRep; // representative vertex per component\n\n        for (int t : terminals) {\n            if (seenTerm[t]) continue;\n            seenTerm[t] = 1;\n            vector<int> comp;\n            queue<int> q;\n            q.push(t);\n            comp.push_back(t);\n            while(!q.empty()){\n                int v = q.front(); q.pop();\n                for (int k = 0; k < 4; k++) {\n                    int u = nb[v][k];\n                    if (u == -1) continue;\n                    if (!isTerm[u]) continue;\n                    if (seenTerm[u]) continue;\n                    seenTerm[u] = 1;\n                    q.push(u);\n                    comp.push_back(u);\n                }\n            }\n            compRep.push_back(comp[0]);\n            compTerms.push_back(std::move(comp));\n        }\n\n        int K = (int)compTerms.size();\n        if (K <= 1) {\n            // just set all terminals\n            for (int t : terminals) b[t/n][t%n] = c;\n            return;\n        }\n\n        vector<unsigned char> keepMask(N, 0);\n        for (int t : terminals) keepMask[t] = 1; // terminals always kept\n\n        vector<unsigned char> inTree(N, 0);\n        vector<unsigned char> compConnected(K, 0);\n        if (rootCompIdx < 0) rootCompIdx = rndInt(K);\n\n        // init: connected subset = terminals of root component\n        compConnected[rootCompIdx] = 1;\n        for (int t : compTerms[rootCompIdx]) inTree[t] = 1;\n\n        int connectedCount = 1;\n\n        vector<int> dist(N, -1), parent(N, -1);\n        queue<int> q;\n\n        while (connectedCount < K) {\n            // multi-source BFS from current inTree vertices within original color c\n            fill(dist.begin(), dist.end(), -1);\n            fill(parent.begin(), parent.end(), -1);\n            while(!q.empty()) q.pop();\n\n            for (int v = 0; v < N; v++) {\n                if (inTree[v] && isColor[c][v]) {\n                    dist[v] = 0;\n                    parent[v] = -1; // source\n                    q.push(v);\n                }\n            }\n\n            while(!q.empty()){\n                int v = q.front(); q.pop();\n                for (int k = 0; k < 4; k++) {\n                    int u = nb[v][k];\n                    if (u == -1) continue;\n                    if (!isColor[c][u]) continue;\n                    if (dist[u] != -1) continue;\n                    dist[u] = dist[v] + 1;\n                    parent[u] = v;\n                    q.push(u);\n                }\n            }\n\n            // select nearest not-yet-connected terminal component rep\n            int bestComp = -1;\n            int bestD = INT_MAX;\n            for (int comp = 0; comp < K; comp++) if (!compConnected[comp]) {\n                int r = compRep[comp];\n                int d = dist[r];\n                if (d != -1 && d < bestD) {\n                    bestD = d;\n                    bestComp = comp;\n                }\n            }\n            if (bestComp == -1) {\n                // fallback: star from root component representative\n                int rootV = compRep[rootCompIdx];\n                vector<unsigned char> tmpKeep = keepMask;\n                for (int comp = 0; comp < K; comp++) if (!compConnected[comp]) {\n                    bfsPathMark(c, rootV, compRep[comp], tmpKeep);\n                }\n                for (int v = 0; v < N; v++) if (tmpKeep[v]) b[v/n][v%n] = c;\n                return;\n            }\n\n            // connect bestComp rep to the inTree via shortest path using parent pointers\n            int cur = compRep[bestComp];\n            while(!inTree[cur]) {\n                keepMask[cur] = 1;\n                inTree[cur] = 1;\n                int p = parent[cur];\n                if (p == -1) break;\n                cur = p;\n            }\n\n            // mark terminals of this component as inTree (now connected)\n            compConnected[bestComp] = 1;\n            connectedCount++;\n            for (int t : compTerms[bestComp]) inTree[t] = 1;\n        }\n\n        // apply keepMask to b\n        for (int v = 0; v < N; v++) if (keepMask[v]) b[v/n][v%n] = c;\n    };\n\n    auto getScoreDist = [&](int c, int v) -> int {\n        int d = distToMustKeep[c][v];\n        if (d >= 0) return d;\n        return distToBoundary[c][v]; // may be 0.. or -1, but boundary BFS should make it reachable for in-region cells\n    };\n\n    auto checkAll = [&](const vector<vector<int>>& b) -> bool {\n        // ward connectivity for colors 1..m\n        vector<unsigned char> vis(N, 0);\n        queue<int> q;\n        for (int c = 1; c <= m; c++) {\n            int start = -1, tot = 0;\n            for (int v : posByColor[c]) {\n                if (b[v/n][v%n] == c) {\n                    tot++;\n                    if (start == -1) start = v;\n                }\n            }\n            if (tot == 0) return false;\n            fill(vis.begin(), vis.end(), 0);\n            while(!q.empty()) q.pop();\n            vis[start] = 1;\n            q.push(start);\n            int cnt = 1;\n            while(!q.empty()){\n                int cur = q.front(); q.pop();\n                for (int k = 0; k < 4; k++) {\n                    int u = nb[cur][k];\n                    if (u == -1) continue;\n                    if (vis[u]) continue;\n                    if (b[u/n][u%n] != c) continue;\n                    vis[u] = 1;\n                    q.push(u);\n                    cnt++;\n                }\n            }\n            if (cnt != tot) return false;\n        }\n\n        // 0 connectivity via outside\n        int N2 = n + 2;\n        auto idExt = [&](int x, int y){ return x*N2 + y; };\n        vector<unsigned char> vis0(N2*N2, 0);\n        queue<pair<int,int>> q0;\n        vis0[idExt(0,0)] = 1;\n        q0.push({0,0});\n        while(!q0.empty()){\n            auto [x,y] = q0.front(); q0.pop();\n            for (int k = 0; k < 4; k++) {\n                int nx = x + DIRS[k][0], ny = y + DIRS[k][1];\n                if (nx < 0 || nx >= N2 || ny < 0 || ny >= N2) continue;\n                bool pass;\n                if (nx==0 || nx==N2-1 || ny==0 || ny==N2-1) pass = true;\n                else pass = (b[nx-1][ny-1] == 0);\n                if (!pass) continue;\n                int nid = idExt(nx,ny);\n                if (vis0[nid]) continue;\n                vis0[nid] = 1;\n                q0.push({nx,ny});\n            }\n        }\n        for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) {\n            if (b[i][j] == 0) {\n                if (!vis0[idExt(i+1,j+1)]) return false;\n            }\n        }\n\n        // adjacency equivalence\n        vector<vector<unsigned char>> adjOut(m+1, vector<unsigned char>(m+1, 0));\n        for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) {\n            int c1 = b[i][j];\n            for (int k = 0; k < 4; k++) {\n                int ni = i + DIRS[k][0], nj = j + DIRS[k][1];\n                int c2 = (ni < 0 || ni >= n || nj < 0 || nj >= n) ? 0 : b[ni][nj];\n                if (c1 == c2) continue;\n                int x = min(c1,c2), y = max(c1,c2);\n                adjOut[x][y] = 1;\n            }\n        }\n        for (int x = 0; x <= m; x++) for (int y = x+1; y <= m; y++) {\n            if (adjOut[x][y] != adjOrig[x][y]) return false;\n        }\n        return true;\n    };\n\n    auto countZeros = [&](const vector<vector<int>>& b) -> int {\n        int z = 0;\n        for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) if (b[i][j] == 0) z++;\n        return z;\n    };\n\n    vector<vector<int>> best = a;\n    int bestZero = -1;\n\n    auto startTime = chrono::high_resolution_clock::now();\n    int T = 26;\n\n    for (int trial = 0; trial < T; trial++) {\n        double elapsed = chrono::duration<double>(chrono::high_resolution_clock::now() - startTime).count();\n        if (elapsed > 1.95) break;\n\n        vector<vector<int>> b(n, vector<int>(n, 0));\n        for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) {\n            int c = a[i][j];\n            if (forbidden[c]) b[i][j] = c;\n        }\n\n        // terminals per allowed color\n        vector<vector<int>> terminals(m+1);\n        vector<vector<unsigned char>> marked(m+1, vector<unsigned char>(N, 0));\n\n        bool ok = true;\n\n        // mustKeepAllowed terminals + choose a boundary seed (best by getScoreDist)\n        for (int c = 1; c <= m; c++) if (!forbidden[c]) {\n            for (int v : mustKeepAllowed[c]) {\n                if (!marked[c][v]) {\n                    marked[c][v] = 1;\n                    terminals[c].push_back(v);\n                }\n            }\n            if (boundaryCells[c].empty()) { ok = false; break; }\n\n            int chosen = -1;\n            int bestD = INT_MAX;\n            for (int bd : boundaryCells[c]) {\n                int d = getScoreDist(c, bd);\n                if (d < bestD) { bestD = d; chosen = bd; }\n            }\n            if (chosen == -1) chosen = boundaryCells[c][rndInt((int)boundaryCells[c].size())];\n\n            if (!marked[c][chosen]) {\n                marked[c][chosen] = 1;\n                terminals[c].push_back(chosen);\n            }\n\n            if (terminals[c].empty()) { ok = false; break; }\n        }\n        if (!ok) continue;\n\n        // choose representative endpoints for each allowed-adjacent pair, biased by distance-to-mandatory/boundary\n        const int DELTA = 2;\n        for (auto [x,y] : allowedAdjPairs) {\n            auto &vec = repEdges[x][y];\n            if (vec.empty()) continue;\n\n            int bestScore = INT_MAX;\n            vector<pair<int,int>> cand;\n            for (auto &e : vec) {\n                int sx = e.first, sy = e.second;\n                int dx = getScoreDist(x, sx);\n                int dy = getScoreDist(y, sy);\n                if (dx < 0 || dy < 0) continue;\n                int sc = dx + dy;\n                if (sc < bestScore) {\n                    bestScore = sc;\n                    cand.clear();\n                    cand.push_back(e);\n                } else if (sc <= bestScore + DELTA) {\n                    cand.push_back(e);\n                }\n            }\n            if (cand.empty()) cand = vec;\n            auto chosenEdge = cand[rndInt((int)cand.size())];\n\n            int sx = chosenEdge.first;\n            int sy = chosenEdge.second;\n            if (!marked[x][sx]) { marked[x][sx] = 1; terminals[x].push_back(sx); }\n            if (!marked[y][sy]) { marked[y][sy] = 1; terminals[y].push_back(sy); }\n        }\n\n        // Build Steiner for each allowed color (incremental Prim-like)\n        for (int c = 1; c <= m; c++) if (!forbidden[c]) {\n            if (terminals[c].empty()) { ok = false; break; }\n            int rootCompIdx = -1; // random inside\n            buildSteinerIncremental(b, c, terminals[c], rootCompIdx);\n        }\n        if (!ok) continue;\n\n        // 0 connectivity repair loop and reconnect affected components\n        for (int iter = 0; iter < 12; iter++) {\n            int N2 = n + 2;\n            auto idExt = [&](int x, int y){ return x*N2 + y; };\n            vector<unsigned char> vis0(N2*N2, 0);\n            queue<pair<int,int>> q0;\n            vis0[idExt(0,0)] = 1;\n            q0.push({0,0});\n            while(!q0.empty()){\n                auto [x,y] = q0.front(); q0.pop();\n                for (int k = 0; k < 4; k++) {\n                    int nx = x + DIRS[k][0], ny = y + DIRS[k][1];\n                    if (nx < 0 || nx >= N2 || ny < 0 || ny >= N2) continue;\n                    bool pass;\n                    if (nx==0 || nx==N2-1 || ny==0 || ny==N2-1) pass = true;\n                    else pass = (b[nx-1][ny-1] == 0);\n                    if (!pass) continue;\n                    int nid = idExt(nx,ny);\n                    if (vis0[nid]) continue;\n                    vis0[nid] = 1;\n                    q0.push({nx,ny});\n                }\n            }\n\n            vector<unsigned char> changed(m+1, 0);\n            bool anyHole = false;\n            for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) {\n                if (b[i][j] == 0 && !vis0[idExt(i+1,j+1)]) {\n                    anyHole = true;\n                    int origColor = a[i][j];\n                    b[i][j] = origColor;\n                    if (!forbidden[origColor]) changed[origColor] = 1;\n                }\n            }\n            if (!anyHole) break;\n            for (int c = 1; c <= m; c++) if (changed[c]) connectColorMST(b, c);\n        }\n\n        if (!checkAll(b)) continue;\n\n        int z = countZeros(b);\n        if (z > bestZero) {\n            bestZero = z;\n            best = std::move(b);\n        }\n    }\n\n    if (bestZero < 0) best = a;\n\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            if (j) cout << ' ';\n            cout << best[i][j];\n        }\n        cout << '\\n';\n    }\n    return 0;\n}","ahc025":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Judge {\n    int N, D, Q;\n    int used = 0;\n    vector<vector<int8_t>> memo; // 2 unknown, -1/0/+1 known for singleton comparisons\n\n    Judge(int n, int d, int q) : N(n), D(d), Q(q) {\n        memo.assign(N, vector<int8_t>(N, 2));\n    }\n\n    int doQuery(const vector<int>& L, const vector<int>& R) {\n        used++;\n        cout << (int)L.size() << ' ' << (int)R.size();\n        for (int x : L) cout << ' ' << x;\n        for (int x : R) cout << ' ' << x;\n        cout << '\\n' << flush;\n\n        string s;\n        cin >> s;\n        char c = s[0];\n        if (c == '<') return -1;\n        if (c == '>') return 1;\n        return 0;\n    }\n\n    int cmpSingleton(int i, int j) {\n        if (i == j) return 0;\n        int8_t &m = memo[i][j];\n        if (m != 2) return (int)m;\n        int s = doQuery(vector<int>{i}, vector<int>{j});\n        m = (int8_t)s;\n        memo[j][i] = (int8_t)(-s);\n        return s;\n    }\n};\n\nstatic int ceil_log2_int(int x) {\n    int b = 0, v = 1;\n    while (v < x) { v <<= 1; b++; }\n    return b;\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    Judge judge(N, D, Q);\n\n    // Generator parameters\n    const double lambda = 1e-5;\n    const double cap = 1e5 * (double)N / (double)D;   // regeneration threshold\n    const double Z = 1.0 - exp(-lambda * cap);       // truncation normalization\n    const int maxW = max(1, (int)llround(cap));\n\n    auto clampW = [&](long long w) -> double {\n        if (w < 1) return 1.0;\n        if (w > maxW) return (double)maxW;\n        return (double)w;\n    };\n\n    // quantile for truncated Exp on [0,cap]\n    auto quantileX_trunc = [&](double p) -> double {\n        p = min(max(p, 1e-12), 1.0 - 1e-12);\n        double inside = 1.0 - p * Z;   // from (1-exp(-\u03bbx))/Z = p\n        inside = max(1e-300, inside);\n        double x = -log(inside) / lambda;\n        x = min(cap, max(0.0, x));\n        return x;\n    };\n\n    // E[X | X in [a,b]] for X~Exp(lambda) conditioned to be in [a,b] (cap cancels if a,b within [0,cap])\n    auto expectedX_interval = [&](double a, double b) -> double {\n        if (b <= a + 1e-15) return a;\n        a = max(0.0, min(cap, a));\n        b = max(0.0, min(cap, b));\n        if (b <= a + 1e-15) return a;\n\n        double ea = exp(-lambda * a);\n        double eb = exp(-lambda * b);\n        double denom = ea - eb; // >0 if a<b\n        if (fabs(denom) < 1e-300) return 0.5 * (a + b);\n\n        double inv = 1.0 / lambda;\n        // integral x*\u03bbe^{-\u03bbx} dx over [a,b] = (a+1/\u03bb)e^{-\u03bba} - (b+1/\u03bb)e^{-\u03bbb}\n        double num = (a + inv) * ea - (b + inv) * eb;\n        return num / denom;\n    };\n\n    // Budget: spend almost all comparisons for ordering; no query-based refinement later.\n    const int dummyCount = 3;\n    int orderingLimit = max(1, Q - dummyCount);\n\n    // Decide: full sort if fits\n    long long estFullComps = 1LL * N * ceil_log2_int(N); // conservative\n    bool doFull = (estFullComps <= (long long)orderingLimit - 5);\n\n    vector<double> w_est(N, 1.0);\n\n    if (doFull) {\n        // Merge-sort by singleton comparisons using judge.cmpSingleton (ascending).\n        vector<int> a(N), tmp(N);\n        iota(a.begin(), a.end(), 0);\n\n        auto lessThan = [&](int i, int j) -> bool {\n            return judge.cmpSingleton(i, j) == -1;\n        };\n\n        for (int width = 1; width < N && judge.used < orderingLimit; width <<= 1) {\n            for (int i = 0; i < N; i += 2 * width) {\n                int L = i;\n                int M = min(i + width, N);\n                int R = min(i + 2 * width, N);\n                int p = L, q = M, k = L;\n                while (p < M && q < R) {\n                    if (lessThan(a[p], a[q])) tmp[k++] = a[p++];\n                    else tmp[k++] = a[q++];\n                }\n                while (p < M) tmp[k++] = a[p++];\n                while (q < R) tmp[k++] = a[q++];\n            }\n            a.swap(tmp);\n        }\n\n        // Assign estimates by truncated quantiles of order statistic position.\n        for (int pos = 0; pos < N; pos++) {\n            double p = (pos + 0.5) / (double)N;\n            double x = quantileX_trunc(p);\n            w_est[a[pos]] = clampW(llround(x));\n        }\n    } else {\n        // Pivot bucketing\n        auto estimatePivotCost = [&](int Kp) -> long long {\n            if (Kp <= 1) {\n                // binary searches among pivots: ceil_log2(Kp+1) ~ 1\n                return 1LL * (N - Kp) * 1;\n            }\n            long long pivotSortWorst = 1LL * Kp * (Kp - 1) / 2;\n            long long bucket = 1LL * (N - Kp) * ceil_log2_int(Kp + 1);\n            return pivotSortWorst + bucket;\n        };\n\n        int maxKp = min(36, N);\n        int Kp = 1;\n        for (int k = 1; k <= maxKp; k++) {\n            if (estimatePivotCost(k) <= (long long)orderingLimit - 5) Kp = k;\n            else break;\n        }\n\n        mt19937_64 rng(712367821ULL ^ (uint64_t)N * 1000003ULL ^ (uint64_t)D * 9176ULL ^ (uint64_t)Q * 1237ULL);\n        vector<int> ids(N);\n        iota(ids.begin(), ids.end(), 0);\n        shuffle(ids.begin(), ids.end(), rng);\n\n        vector<int> pivots(ids.begin(), ids.begin() + Kp);\n\n        // Sort pivots ascending by singleton comparisons (insertion sort).\n        for (int i = 1; i < Kp && judge.used < orderingLimit; i++) {\n            int j = i;\n            while (j > 0) {\n                int s = judge.cmpSingleton(pivots[j], pivots[j - 1]); // piv[j] ? piv[j-1]\n                if (s == -1) { // piv[j] < piv[j-1]\n                    swap(pivots[j], pivots[j - 1]);\n                    j--;\n                } else break;\n            }\n        }\n\n        vector<int> pivotPos(N, -1);\n        for (int i = 0; i < Kp; i++) pivotPos[pivots[i]] = i;\n\n        // Pivot expected X by truncated quantile at rank within pivots.\n        vector<double> pivotX(Kp);\n        for (int i = 0; i < Kp; i++) {\n            double p = (i + 0.5) / (double)(Kp + 1);\n            pivotX[i] = quantileX_trunc(p);\n        }\n\n        for (int i = 0; i < Kp; i++) {\n            w_est[pivots[i]] = clampW(llround(pivotX[i]));\n        }\n\n        // For each non-pivot: find first pivot >= item (via comparisons), then estimate E[X|X in interval].\n        for (int item = 0; item < N && judge.used < orderingLimit; item++) {\n            if (pivotPos[item] != -1) continue;\n\n            int lo = 0, hi = Kp; // item < piv[hi] region\n            bool eqFound = false;\n            double eqVal = 1.0;\n\n            while (lo < hi) {\n                int mid = (lo + hi) / 2;\n                int s = judge.cmpSingleton(item, pivots[mid]); // item ? piv[mid]\n                if (s == 0) {\n                    eqFound = true;\n                    eqVal = pivotX[mid];\n                    lo = hi = mid;\n                    break;\n                } else if (s == 1) {\n                    lo = mid + 1;\n                } else {\n                    hi = mid;\n                }\n            }\n\n            if (eqFound) {\n                w_est[item] = clampW(llround(eqVal));\n                continue;\n            }\n\n            int k = lo; // pivots[0..k-1] < item <= pivots[k..]\n            double a = (k == 0) ? 0.0 : pivotX[k - 1];\n            double b = (k == Kp) ? cap : pivotX[k];\n            double ex = expectedX_interval(a, b);\n            w_est[item] = clampW(llround(ex));\n        }\n    }\n\n    // Order items for packing by estimated weight descending\n    vector<int> order(N);\n    iota(order.begin(), order.end(), 0);\n    vector<int> tieKey(N);\n    mt19937_64 rng2(998244353ULL ^ (uint64_t)N * 10007ULL ^ (uint64_t)D * 12391ULL);\n    for (int i = 0; i < N; i++) tieKey[i] = (int)rng2();\n\n    sort(order.begin(), order.end(), [&](int a, int b) {\n        if (w_est[a] != w_est[b]) return w_est[a] > w_est[b];\n        return tieKey[a] < tieKey[b];\n    });\n\n    double totalEst = 0;\n    for (double x : w_est) totalEst += x;\n    double target = totalEst / (double)D;\n    double mean = target;\n\n    auto varianceProxy = [&](const vector<double>& sumEst) -> double {\n        // proportional to score's sqrt(V); we just need ordering\n        double v = 0;\n        for (double s : sumEst) {\n            double t = s - mean;\n            v += t * t;\n        }\n        return v;\n    };\n\n    auto buildPartition = [&](int mode) -> tuple<vector<int>, vector<double>> {\n        vector<vector<int>> bins(D);\n        vector<double> sum(D, 0.0);\n\n        for (int x : order) {\n            int best = 0;\n            if (mode == 0) {\n                // LPT: put into bin with minimum sum\n                for (int b = 1; b < D; b++) if (sum[b] < sum[best]) best = b;\n            } else if (mode == 1) {\n                // BestFit-to-target\n                double bestCost = 1e100;\n                for (int b = 0; b < D; b++) {\n                    double ns = sum[b] + w_est[x];\n                    double cost = fabs(ns - target);\n                    if (cost < bestCost - 1e-12 || (fabs(cost - bestCost) <= 1e-12 && sum[b] < sum[best])) {\n                        bestCost = cost;\n                        best = b;\n                    }\n                }\n            } else if (mode == 2) {\n                // MinVarIncrease on squared deviation from mean (local exact)\n                double w = w_est[x];\n                double bestDelta = 1e100;\n                for (int b = 0; b < D; b++) {\n                    double old = (sum[b] - mean) * (sum[b] - mean);\n                    double ns = sum[b] + w;\n                    double nd = (ns - mean) * (ns - mean);\n                    double delta = nd - old;\n                    if (delta < bestDelta - 1e-12 || (fabs(delta - bestDelta) <= 1e-12 && sum[b] < sum[best])) {\n                        bestDelta = delta;\n                        best = b;\n                    }\n                }\n            } else {\n                // Mode 3: restrict to K smallest-sum bins and use MinVarIncrease\n                int Kcand = (mode == 3 ? 5 : 8);\n                vector<int> cand(D);\n                iota(cand.begin(), cand.end(), 0);\n                sort(cand.begin(), cand.end(), [&](int i, int j) {\n                    if (sum[i] != sum[j]) return sum[i] < sum[j];\n                    return i < j;\n                });\n                cand.resize(min(D, Kcand));\n\n                double w = w_est[x];\n                int bestBin = cand[0];\n                double bestDelta = 1e100;\n                for (int b : cand) {\n                    double old = (sum[b] - mean) * (sum[b] - mean);\n                    double ns = sum[b] + w;\n                    double nd = (ns - mean) * (ns - mean);\n                    double delta = nd - old;\n                    if (delta < bestDelta - 1e-12 || (fabs(delta - bestDelta) <= 1e-12 && sum[b] < sum[bestBin])) {\n                        bestDelta = delta;\n                        bestBin = b;\n                    }\n                }\n                best = bestBin;\n            }\n\n            bins[best].push_back(x);\n            sum[best] += w_est[x];\n        }\n\n        vector<int> assign(N, 0);\n        for (int b = 0; b < D; b++) for (int x : bins[b]) assign[x] = b;\n        return {assign, sum};\n    };\n\n    // Try several packing modes\n    double bestProxy = 1e100;\n    vector<int> bestAssign(N, 0);\n    vector<double> bestSum(D, 0.0);\n\n    for (int rep = 0; rep < 2; rep++) {\n        if (rep == 1) {\n            // perturb tie-breaking by re-sorting order\n            for (int i = 0; i < N; i++) tieKey[i] = (int)rng2();\n            sort(order.begin(), order.end(), [&](int a, int b) {\n                if (w_est[a] != w_est[b]) return w_est[a] > w_est[b];\n                return tieKey[a] < tieKey[b];\n            });\n        }\n        for (int mode : {0, 1, 2, 3, 4}) {\n            auto [assign, sum] = buildPartition(mode);\n            double p = varianceProxy(sum);\n            if (p < bestProxy) {\n                bestProxy = p;\n                bestAssign = move(assign);\n                bestSum = move(sum);\n            }\n        }\n    }\n\n    // ---- Monotonic local improvement WITHOUT queries (estimated proxy only) ----\n    vector<vector<int>> bins(D);\n    vector<int> posInBin(N, -1);\n    for (int i = 0; i < N; i++) bins[bestAssign[i]].push_back(i);\n    for (int b = 0; b < D; b++) for (int i = 0; i < (int)bins[b].size(); i++) posInBin[bins[b][i]] = i;\n\n    vector<double> sumEst = bestSum; // already\n    auto recomputeProxy2 = [&]() -> double { return varianceProxy(sumEst); };\n    (void)recomputeProxy2;\n\n    auto moveItem = [&](int x, int from, int to) {\n        // swap-pop removal from bins[from]\n        int idx = posInBin[x];\n        int y = bins[from].back();\n        bins[from][idx] = y;\n        posInBin[y] = idx;\n        bins[from].pop_back();\n\n        // add to bins[to]\n        bins[to].push_back(x);\n        posInBin[x] = (int)bins[to].size() - 1;\n\n        bestAssign[x] = to;\n        sumEst[from] -= w_est[x];\n        sumEst[to] += w_est[x];\n    };\n\n    const double eps = 1e-9;\n    double curProxy = varianceProxy(sumEst);\n\n    int maxMoves = 600; // bounded\n    for (int it = 0; it < maxMoves; it++) {\n        int heavy = -1, light = -1;\n        for (int b = 0; b < D; b++) {\n            if ((int)bins[b].size() >= 2) {\n                if (heavy == -1 || sumEst[b] > sumEst[heavy]) heavy = b;\n            }\n            if (!bins[b].empty()) {\n                if (light == -1 || sumEst[b] < sumEst[light]) light = b;\n            }\n        }\n        if (heavy == -1 || light == -1 || heavy == light) break;\n\n        // If already close to mean, stop\n        if (sumEst[heavy] <= mean + eps && sumEst[light] >= mean - eps) break;\n\n        double oldH = sumEst[heavy], oldL = sumEst[light];\n        double oldPh = (oldH - mean) * (oldH - mean);\n        double oldPl = (oldL - mean) * (oldL - mean);\n        double bestDelta = 0;\n        int bestX = -1;\n\n        // Try all items in heavy bin (small enough: N<=100)\n        for (int x : bins[heavy]) {\n            double w = w_est[x];\n            double newH = oldH - w;\n            double newL = oldL + w;\n            double newPh = (newH - mean) * (newH - mean);\n            double newPl = (newL - mean) * (newL - mean);\n            double delta = (newPh + newPl) - (oldPh + oldPl);\n            if (delta < bestDelta - 1e-12) {\n                bestDelta = delta;\n                bestX = x;\n            }\n        }\n\n        if (bestX == -1) break; // no improving move\n        moveItem(bestX, heavy, light);\n\n        curProxy = varianceProxy(sumEst);\n        // monotone in theory; but keep guard\n        if (curProxy > bestProxy + 1e-6) bestProxy = curProxy; // no-op, just stability\n    }\n\n    // ---- Dummy queries to reach exactly Q ----\n    while (judge.used < Q) {\n        int a = 0, b = 1;\n        if (a == b) b = 2 % N;\n        if (b == a) b = (a + 1) % N;\n        judge.doQuery(vector<int>{a}, vector<int>{b});\n    }\n\n    // Output assignment\n    for (int i = 0; i < N; i++) {\n        if (i) cout << ' ';\n        cout << bestAssign[i];\n    }\n    cout << '\\n' << flush;\n    return 0;\n}","ahc026":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int MAXM = 10;\nstatic constexpr int MAXN = 200;\nstatic constexpr long long INFLL = (1LL << 60);\n\nstruct State {\n    int a[MAXM][MAXN];       // bottom -> top\n    int len[MAXM];\n    int posStack[MAXN + 1];\n    int posIndex[MAXN + 1];\n    int n = MAXN, m = MAXM;\n\n    State(int n_=0, int m_=0) : n(n_), m(m_) {\n        for (int i = 0; i < MAXM; i++) len[i] = 0;\n        for (int v = 1; v <= MAXN; v++) {\n            posStack[v] = -1;\n            posIndex[v] = -1;\n        }\n    }\n};\n\nstatic inline int energyCarryOne(const State& st, int t) {\n    if (t > st.n) return 0;\n    int s = st.posStack[t];\n    int idx = st.posIndex[t];\n    // energy comes only from operation 1 when t is not on top\n    if (idx == st.len[s] - 1) return 0;\n    int above = st.len[s] - idx - 1;  // number of boxes above t\n    return above + 1;                 // k = above+1 boxes moved by op1, energy=k+1 = above+2?\n    // Wait: energy for op1 is (k+1) where k boxes moved.\n    // Here when t is not on top, op1 moves the box above t and all above it:\n    // moved boxes count k = number of boxes above t = above.\n    // Actually moved boxes include the box immediately above t and everything above it,\n    // so k = above. Energy = k + 1 = above + 1.\n    // Therefore return above + 1 is correct.\n}\n\nstatic inline long long applyCarry(State& st, int v, int forcedDest, vector<pair<int,int>>* ops) {\n    int s = st.posStack[v];\n    int idx = st.posIndex[v];\n\n    if (idx == st.len[s] - 1) {\n        if (ops) ops->push_back({v, 0});\n        st.len[s]--;\n        st.posStack[v] = -1;\n        st.posIndex[v] = -1;\n        return 0;\n    }\n\n    int u = st.a[s][idx + 1]; // box chosen by operation 1\n    int start = idx + 1;     // moved suffix starts here\n    int k = st.len[s] - start; // number of boxes moved by operation 1\n\n    int dest = forcedDest; // 0..m-1\n    if (ops) ops->push_back({u, dest + 1});\n\n    int base = st.len[dest];\n    for (int t = 0; t < k; t++) {\n        int x = st.a[s][start + t];\n        st.a[dest][base + t] = x;\n        st.posStack[x] = dest;\n        st.posIndex[x] = base + t;\n    }\n    st.len[dest] = base + k;\n\n    // truncate source so v becomes top, then remove v by op2\n    st.len[s] = idx + 1;\n    if (ops) ops->push_back({v, 0});\n    st.len[s]--;\n    st.posStack[v] = -1;\n    st.posIndex[v] = -1;\n\n    // op1 energy: k moved => k + 1\n    return (long long)k + 1;\n}\n\n// Heuristic tie-break key (computed from current state before moving v)\nstatic inline tuple<int,int,int,int,int> heuristicKey(const State& st, int v, int dest) {\n    int s = st.posStack[v];\n    int idx = st.posIndex[v];\n    int start = idx + 1;\n\n    // suffix stats\n    int minS = INT_MAX, maxS = 0;\n    for (int j = start; j < st.len[s]; j++) {\n        int y = st.a[s][j];\n        minS = min(minS, y);\n        maxS = max(maxS, y);\n    }\n\n    int height = st.len[dest];\n    if (height == 0) {\n        // prefer safe-ish; keep deterministic\n        return {0, 0, 1, 0, 0};\n    }\n\n    int minD = INT_MAX;\n    for (int i = 0; i < height; i++) minD = min(minD, st.a[dest][i]);\n\n    int safeFlag = (minD > maxS ? 0 : 1);\n\n    // inv = #(x in dest, y in S) with x < y\n    int inv = 0;\n    int cntSmall = 0; // #x in dest with x < minS\n    for (int i = 0; i < height; i++) {\n        int x = st.a[dest][i];\n        if (x < minS) cntSmall++;\n        for (int j = start; j < st.len[s]; j++) {\n            int y = st.a[s][j];\n            if (x < y) inv++;\n        }\n    }\n\n    // key: (safeFlag, inv, height, cntSmall, -minD)\n    return {safeFlag, inv, height, cntSmall, -minD};\n}\n\n// Minimal additional energy to carry out boxes t and t+1 (within horizon length 2).\n// This explores destination choices only when processing the first box (t).\nstatic long long energyTwo(State st, int t) {\n    if (t > st.n) return 0;\n    if (t == st.n) return energyCarryOne(st, t);\n\n    int s = st.posStack[t];\n    int idx = st.posIndex[t];\n\n    // If t is on top: energy for t is 0, remove it, then compute energyCarryOne for t+1.\n    if (idx == st.len[s] - 1) {\n        applyCarry(st, t, 0, nullptr); // op2 only\n        return energyCarryOne(st, t + 1);\n    }\n\n    long long best = INFLL;\n    for (int d = 0; d < st.m; d++) if (d != s) {\n        State tmp = st;\n        long long e = applyCarry(tmp, t, d, nullptr); // energy for carrying t\n        e += energyCarryOne(tmp, t + 1);             // energy for carrying t+1 (last step)\n        best = min(best, e);\n    }\n    return best;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int n, m;\n    cin >> n >> m;\n    int h = n / m;\n\n    State cur(n, m);\n    for (int i = 0; i < m; i++) {\n        cur.len[i] = h;\n        for (int j = 0; j < h; j++) {\n            int x;\n            cin >> x;\n            cur.a[i][j] = x;\n            cur.posStack[x] = i;\n            cur.posIndex[x] = j;\n        }\n    }\n\n    vector<pair<int,int>> ops;\n    ops.reserve(2 * n + 5);\n\n    for (int v = 1; v <= n; v++) {\n        int s = cur.posStack[v];\n        int idx = cur.posIndex[v];\n\n        if (idx == cur.len[s] - 1) {\n            applyCarry(cur, v, 0, &ops);\n            continue;\n        }\n\n        int bestDest = -1;\n        long long bestPred = INFLL;\n        tuple<int,int,int,int,int> bestHKey{};\n\n        for (int d = 0; d < m; d++) if (d != s) {\n            State tmp = cur;\n            long long e = applyCarry(tmp, v, d, nullptr); // energy for box v (constant across d, but keep)\n            e += energyTwo(tmp, v + 1);                   // optimal additional energy for v+1..v+2\n            auto hk = heuristicKey(cur, v, d);            // tie-break from original state\n\n            if (e < bestPred || (e == bestPred && (bestDest == -1 || hk < bestHKey))) {\n                bestPred = e;\n                bestDest = d;\n                bestHKey = hk;\n            }\n        }\n\n        // Apply best choice to real state and output\n        applyCarry(cur, v, bestDest, &ops);\n    }\n\n    if ((int)ops.size() > 5000) return 0;\n    for (auto [vv, ii] : ops) {\n        cout << vv << \" \" << ii << \"\\n\";\n    }\n    return 0;\n}","ahc027":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct RNG {\n    uint64_t x;\n    explicit RNG(uint64_t seed) : x(seed) {}\n    uint64_t next_u64() {\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 next_int(int l, int r) { // inclusive\n        return l + (int)(next_u64() % (uint64_t)(r - l + 1));\n    }\n    double next_double(double l, double r) { // [l, r)\n        long double t = (long double)next_u64() / (long double)numeric_limits<uint64_t>::max();\n        return (double)((long double)l + t * (long double)(r - l));\n    }\n};\n\nstatic inline char dirChar(int N, int a, int b) {\n    int ai = a / N, aj = a % N;\n    int bi = b / N, bj = b % N;\n    if (bi == ai + 1 && bj == aj) return 'D';\n    if (bi == ai - 1 && bj == aj) return 'U';\n    if (bi == ai && bj == aj + 1) return 'R';\n    if (bi == ai && bj == aj - 1) return 'L';\n    return '?';\n}\n\nstruct EvalState {\n    long long numer; // sum_{t=L}^{2L-1} S_t\n    int L;\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(max(0, N - 1));\n    for (int i = 0; i < N - 1; i++) cin >> h[i];\n    vector<string> v(N);\n    for (int i = 0; i < N; i++) cin >> v[i];\n\n    int V = N * N;\n    vector<int> d(V);\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) cin >> d[i * N + j];\n    }\n\n    auto idx = [&](int i, int j) { return i * N + j; };\n    const int root = 0;\n\n    // Build adjacency graph (respecting walls)\n    vector<vector<int>> g(V);\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            int a = idx(i, j);\n            if (i + 1 < N && h[i][j] == '0') {\n                int b = idx(i + 1, j);\n                g[a].push_back(b);\n                g[b].push_back(a);\n            }\n            if (j + 1 < N && v[i][j] == '0') {\n                int b = idx(i, j + 1);\n                g[a].push_back(b);\n                g[b].push_back(a);\n            }\n        }\n    }\n\n    // BFS distances from root\n    vector<int> dist(V, -1);\n    queue<int> q;\n    dist[root] = 0;\n    q.push(root);\n    while (!q.empty()) {\n        int x = q.front(); q.pop();\n        for (int y : g[x]) if (dist[y] == -1) {\n            dist[y] = dist[x] + 1;\n            q.push(y);\n        }\n    }\n\n    // Candidate parents: neighbors with dist-1\n    vector<vector<int>> candParents(V);\n    for (int x = 0; x < V; x++) {\n        if (x == root) continue;\n        int dx = dist[x];\n        for (int y : g[x]) if (dist[y] == dx - 1) candParents[x].push_back(y);\n        if (candParents[x].empty()) candParents[x].push_back(root); // safety\n    }\n\n    vector<int> verts(V);\n    iota(verts.begin(), verts.end(), 0);\n    // deep-to-shallow order for subtree DP\n    sort(verts.begin(), verts.end(), [&](int a, int b) { return dist[a] > dist[b]; });\n\n    long long sum_d = 0;\n    for (int x : d) sum_d += x;\n\n    int L0 = 2 * (V - 1);\n\n    // Fast exact evaluation of average dirtiness:\n    // given pos array of length L (pos[k] = vertex moved into after k+1-th move in the cycle)\n    // compute numer = sum_{t=L}^{2L-1} S_t where S_t = total dirtiness at time t.\n    vector<int> last(V, 0), seen(V, 0);\n    int seen_id = 1;\n\n    auto evalByPos = [&](auto getPos, int L) -> EvalState {\n        // getPos(k) for 0 <= k < L\n        seen_id++;\n        if (seen_id == INT_MAX) {\n            fill(seen.begin(), seen.end(), 0);\n            seen_id = 1;\n        }\n\n        long long numer = 0;\n        long long sum_d_last = 0;\n\n        int T = 2 * L - 1;\n        for (int t = 1; t <= T; t++) {\n            int idxPos = (t - 1) % L;\n            int vv = getPos(idxPos);\n\n            int old = 0;\n            if (seen[vv] == seen_id) old = last[vv];\n            else seen[vv] = seen_id;\n\n            last[vv] = t;\n            sum_d_last += 1LL * d[vv] * (t - old);\n\n            long long S = 1LL * t * sum_d - sum_d_last;\n            if (t >= L) numer += S;\n        }\n        return {numer, L};\n    };\n\n    auto betterAvg = [&](const EvalState& A, const EvalState& B) -> bool {\n        // A.numer/A.L < B.numer/B.L\n        __int128 left = (__int128)A.numer * B.L;\n        __int128 right = (__int128)B.numer * A.L;\n        return left < right;\n    };\n\n    auto buildBase = [&](const vector<int>& parent, vector<vector<int>>& childrenOrder,\n                         vector<int>& basePos, string& baseMoves) {\n        for (int i = 0; i < V; i++) childrenOrder[i].clear();\n\n        for (int x = 0; x < V; x++) if (x != root) {\n            childrenOrder[parent[x]].push_back(x);\n        }\n\n        // already ordered by caller\n        basePos.clear();\n        baseMoves.clear();\n        basePos.reserve(L0);\n        baseMoves.reserve(L0);\n\n        // iterative DFS Euler tour on the tree\n        vector<pair<int,int>> st;\n        st.reserve(V);\n        st.push_back({root, 0});\n\n        while (!st.empty()) {\n            int u = st.back().first;\n            int &it = st.back().second;\n            if (it == (int)childrenOrder[u].size()) {\n                st.pop_back();\n                if (st.empty()) break;\n                int p = parent[u];\n                baseMoves.push_back(dirChar(N, u, p));\n                basePos.push_back(p);\n            } else {\n                int c = childrenOrder[u][it++];\n                baseMoves.push_back(dirChar(N, u, c));\n                basePos.push_back(c);\n                st.push_back({c, 0});\n            }\n        }\n        // basePos.size() should be L0\n        // (tree has V nodes => Euler tour length 2*(V-1))\n    };\n\n    // Random search for best base tree & child order\n    RNG rng((uint64_t)chrono::steady_clock::now().time_since_epoch().count());\n\n    vector<int> parent(V, -1);\n    vector<vector<int>> childrenOrder(V);\n\n    EvalState bestBase{(1LL<<62), L0};\n    vector<int> bestBasePos;\n    string bestBaseMoves;\n    vector<int> bestParent;\n    vector<vector<int>> bestChildrenOrder;\n\n    auto start = chrono::steady_clock::now();\n    double TIME_BASE = 1.25;\n\n    auto chooseParent = [&](int x, double alpha, double greedyProb) {\n        // candParents[x] are all dist-1 neighbors\n        auto &cp = candParents[x];\n        if (cp.empty()) return root;\n        if (rng.next_double(0.0, 1.0) < greedyProb) {\n            int best = cp[0];\n            for (int u : cp) if (d[u] > d[best]) best = u;\n            return best;\n        } else {\n            // weight ~ d[u]^alpha\n            double total = 0;\n            vector<double> w(cp.size());\n            for (int i = 0; i < (int)cp.size(); i++) {\n                w[i] = pow((double)d[cp[i]], alpha);\n                total += w[i];\n            }\n            double r = rng.next_double(0.0, total);\n            for (int i = 0; i < (int)cp.size(); i++) {\n                r -= w[i];\n                if (r <= 0) return cp[i];\n            }\n            return cp.back();\n        }\n    };\n\n    while (true) {\n        double elapsed = chrono::duration<double>(chrono::steady_clock::now() - start).count();\n        if (elapsed > TIME_BASE) break;\n\n        double alpha = rng.next_double(0.6, 2.2);\n        double greedyProb = rng.next_double(0.75, 0.98);\n        int orderType = rng.next_int(0, 2); // 0 subMax, 1 subSum, 2 d(child)\n        bool ascending = rng.next_int(0, 1);\n        double noiseRate = rng.next_double(0.0, 0.28);\n\n        // build parent\n        parent[root] = -1;\n        vector<int> byDistAsc = verts;\n        sort(byDistAsc.begin(), byDistAsc.end(), [&](int a, int b){ return dist[a] < dist[b]; });\n        for (int x : byDistAsc) {\n            if (x == root) continue;\n            parent[x] = chooseParent(x, alpha, greedyProb);\n        }\n\n        // build children lists (unsorted)\n        vector<vector<int>> children(V);\n        for (int i = 0; i < V; i++) children[i].clear();\n        for (int x = 0; x < V; x++) if (x != root) children[parent[x]].push_back(x);\n\n        // subtree DP\n        vector<long long> subMax(V), subSum(V);\n        for (int x : verts) { // deep -> shallow\n            subMax[x] = d[x];\n            subSum[x] = d[x];\n            for (int c : children[x]) {\n                subMax[x] = max(subMax[x], subMax[c]);\n                subSum[x] += subSum[c];\n            }\n        }\n\n        // order children\n        childrenOrder.assign(V, {});\n        for (int u = 0; u < V; u++) {\n            auto &ch = children[u];\n            childrenOrder[u] = ch;\n\n            if (ch.size() <= 1) continue;\n            vector<pair<double,int>> tmp;\n            tmp.reserve(ch.size());\n            for (int c : ch) {\n                double key;\n                if (orderType == 0) key = (double)subMax[c];\n                else if (orderType == 1) key = (double)subSum[c];\n                else key = (double)d[c];\n\n                double sign = rng.next_double(-1.0, 1.0);\n                double adj = key + noiseRate * key * sign;\n                tmp.push_back({adj, c});\n            }\n            sort(tmp.begin(), tmp.end(), [&](auto &A, auto &B) {\n                if (A.first != B.first) return ascending ? (A.first < B.first) : (A.first > B.first);\n                return A.second < B.second;\n            });\n            for (int i = 0; i < (int)ch.size(); i++) childrenOrder[u][i] = tmp[i].second;\n        }\n\n        // build base route\n        vector<int> basePos;\n        string baseMoves;\n        basePos.reserve(L0);\n        baseMoves.reserve(L0);\n\n        buildBase(parent, childrenOrder, basePos, baseMoves);\n        if ((int)basePos.size() != L0) continue; // safety\n\n        auto getPos = [&](int k) -> int { return basePos[k]; };\n        auto val = evalByPos(getPos, L0);\n\n        if (betterAvg(val, bestBase)) {\n            bestBase = val;\n            bestBasePos = std::move(basePos);\n            bestBaseMoves = std::move(baseMoves);\n            bestParent = parent;\n            bestChildrenOrder = childrenOrder;\n        }\n    }\n\n    // Extension search on top edges with consistent evaluation/output\n    int maxLen = 100000;\n    int baseL = L0;\n\n    // compute depth in best base tree\n    vector<int> depthTree(V, 0);\n    vector<int> byDistAsc = verts;\n    sort(byDistAsc.begin(), byDistAsc.end(), [&](int a, int b){ return dist[a] < dist[b]; });\n    depthTree[root] = 0;\n    for (int x : byDistAsc) {\n        if (x == root) continue;\n        depthTree[x] = depthTree[bestParent[x]] + 1;\n    }\n\n    // list undirected edges\n    vector<pair<int,int>> edges;\n    edges.reserve(V * 2);\n    for (int u = 0; u < V; u++) for (int w : g[u]) if (u < w) edges.push_back({u,w});\n\n    // edge ranking by potential shuttle value / overhead\n    struct EdgeCand { double score; int u,v; };\n    vector<EdgeCand> edgeC;\n    edgeC.reserve(edges.size());\n    for (auto [a,b] : edges) {\n        double best = max(\n            (double)(d[a] + d[b]) / (double)(depthTree[a] + depthTree[b] + 1),\n            (double)(d[a] + d[b]) / (double)(depthTree[a] + depthTree[b] + 1)\n        );\n        edgeC.push_back({best, a, b});\n    }\n    sort(edgeC.begin(), edgeC.end(), [&](auto &A, auto &B){ return A.score > B.score; });\n    int TOP_E = min<int>(30, edgeC.size());\n\n    EvalState bestAll = bestBase;\n    string bestAllRoute = bestBaseMoves;\n\n    auto buildChainRootTo = [&](int x) {\n        vector<int> chain;\n        int cur = x;\n        while (cur != root) {\n            chain.push_back(cur);\n            cur = bestParent[cur];\n        }\n        reverse(chain.begin(), chain.end());\n        return chain; // excludes root\n    };\n\n    // Build segment pos for a given s,t,m where:\n    // - start at root, go along tree to s\n    // - shuttle along edge (s,t) for m moves\n    // - then return from current end (depends on parity of m) to root along the tree\n    auto buildSegmentPos = [&](int s, int t, int m, vector<int>& segPos) {\n        segPos.clear();\n        segPos.reserve(depthTree[s] + m + max(depthTree[s], depthTree[t]));\n\n        // root -> s\n        int cur = root;\n        auto chainS = buildChainRootTo(s);\n        for (int nxt : chainS) {\n            segPos.push_back(nxt); // moved into nxt\n            cur = nxt;\n        }\n        // now at s\n        int curV = s;\n        for (int i = 0; i < m; i++) {\n            int nxt = (curV == s ? t : s);\n            segPos.push_back(nxt);\n            curV = nxt;\n        }\n        // return curV -> root via tree parents\n        while (curV != root) {\n            int nxt = bestParent[curV];\n            segPos.push_back(nxt);\n            curV = nxt;\n        }\n    };\n\n    // Evaluate full route consisting of basePos + segPos without allocating combined array.\n    auto evalFull = [&](const vector<int>& segPos) -> EvalState {\n        int segL = (int)segPos.size();\n        int L = baseL + segL;\n\n        auto getPos = [&](int k) -> int {\n            if (k < baseL) return bestBasePos[k];\n            return segPos[k - baseL];\n        };\n        return evalByPos(getPos, L);\n    };\n\n    auto buildSegmentMoves = [&](int s, int t, int m) -> string {\n        string seg;\n        int cur = root;\n\n        auto chainS = buildChainRootTo(s);\n        for (int nxt : chainS) {\n            seg.push_back(dirChar(N, cur, nxt));\n            cur = nxt;\n        }\n        int curV = s;\n        for (int i = 0; i < m; i++) {\n            int nxt = (curV == s ? t : s);\n            seg.push_back(dirChar(N, curV, nxt));\n            curV = nxt;\n        }\n        while (curV != root) {\n            int nxt = bestParent[curV];\n            seg.push_back(dirChar(N, curV, nxt));\n            curV = nxt;\n        }\n        return seg;\n    };\n\n    vector<int> segPos;\n    auto extStart = chrono::steady_clock::now();\n    double TIME_EXT = 0.70;\n\n    // Also consider k=0 already included as bestAll = bestBase\n    for (int ei = 0; ei < TOP_E; ei++) {\n        double elapsed = chrono::duration<double>(chrono::steady_clock::now() - extStart).count();\n        if (elapsed > TIME_EXT) break;\n\n        int u = edgeC[ei].u, vtx = edgeC[ei].v;\n        for (int ori = 0; ori < 2; ori++) {\n            int s = (ori == 0 ? u : vtx);\n            int t = (ori == 0 ? vtx : u);\n\n            // derive max m for even/odd end:\n            // - if m odd => end=t => total segLen = depth[s] + m + depth[t]\n            // - if m even => end=s => total segLen = depth[s] + m + depth[s] = 2*depth[s] + m\n            int oddMax = maxLen - baseL - depthTree[s] - depthTree[t]; // m must be odd and >=1\n            int evenMax = maxLen - baseL - 2 * depthTree[s];            // m must be even and >=2\n\n            vector<int> candidates;\n            auto addIf = [&](int m) {\n                if (m <= 0) return;\n                int end = (m % 2 ? t : s);\n                int segLen = depthTree[s] + m + depthTree[end];\n                if (baseL + segLen <= maxLen) candidates.push_back(m);\n            };\n\n            // near maxima\n            if (oddMax >= 1) {\n                int m = oddMax;\n                if (m % 2 == 0) m--;\n                if (m >= 1) {\n                    addIf(m);\n                    if (m - 2 >= 1) addIf(m - 2);\n                    if (m / 2 >= 1) addIf((m / 2) | 1); // make odd\n                }\n            }\n            if (evenMax >= 2) {\n                int m = evenMax;\n                if (m % 2 == 1) m--;\n                if (m >= 2) {\n                    addIf(m);\n                    if (m - 2 >= 2) addIf(m - 2);\n                    if (m / 2 >= 2) addIf((m / 2) & ~1); // make even\n                }\n            }\n\n            // small shuttles sometimes help\n            addIf(1);\n            addIf(2);\n            addIf(3);\n            addIf(4);\n\n            sort(candidates.begin(), candidates.end());\n            candidates.erase(unique(candidates.begin(), candidates.end()), candidates.end());\n\n            for (int m : candidates) {\n                // build segment pos\n                buildSegmentPos(s, t, m, segPos);\n                if ((int)segPos.size() + baseL > maxLen) continue;\n\n                auto val = evalFull(segPos);\n                if (betterAvg(val, bestAll)) {\n                    bestAll = val;\n                    bestAllRoute = bestBaseMoves + buildSegmentMoves(s, t, m);\n                }\n            }\n        }\n    }\n\n    // Output best route\n    cout << bestAllRoute << \"\\n\";\n    return 0;\n}","ahc028":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M;\n    cin >> N >> M;\n\n    int si, sj;\n    cin >> si >> sj;\n\n    vector<string> grid(N);\n    for (int i = 0; i < N; i++) cin >> grid[i];\n\n    vector<string> t(M);\n    for (int k = 0; k < M; k++) cin >> t[k];\n\n    auto idxOf = [N](int r, int c) { return r * N + c; };\n    auto coordOf = [N](int id) { return pair<int,int>{id / N, id % N}; };\n\n    int C = N * N;\n    int startCell = idxOf(si, sj);\n\n    vector<vector<int>> posByLetter(26);\n    for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) {\n        int a = grid[i][j] - 'A';\n        posByLetter[a].push_back(idxOf(i, j));\n    }\n\n    // dist between any two cells\n    vector<vector<int>> distCell(C, vector<int>(C, 0));\n    for (int a = 0; a < C; a++) {\n        auto [ar, ac] = coordOf(a);\n        for (int b = a; b < C; b++) {\n            auto [br, bc] = coordOf(b);\n            int d = abs(ar - br) + abs(ac - bc);\n            distCell[a][b] = distCell[b][a] = d;\n        }\n    }\n\n    // min dist from a cell to ANY cell containing given letter\n    vector<vector<int>> distCellToLetter(C, vector<int>(26, INT_MAX/4));\n    for (int p = 0; p < C; p++) {\n        for (int l = 0; l < 26; l++) {\n            int best = INT_MAX/4;\n            for (int q : posByLetter[l]) best = min(best, distCell[p][q]);\n            distCellToLetter[p][l] = best;\n        }\n    }\n\n    // min distance between any cell containing letter x and any cell containing y\n    vector<vector<int>> distLetter(26, vector<int>(26, INT_MAX/4));\n    for (int x = 0; x < 26; x++) for (int y = 0; y < 26; y++) {\n        int best = INT_MAX/4;\n        for (int p : posByLetter[x]) {\n            for (int q : posByLetter[y]) best = min(best, distCell[p][q]);\n        }\n        distLetter[x][y] = best;\n    }\n\n    vector<int> st(M), en(M);\n    for (int i = 0; i < M; i++) {\n        st[i] = t[i][0] - 'A';\n        en[i] = t[i][4] - 'A';\n    }\n\n    // overlapLen[i][j]: maximum r (0..4) such that suffix(t[i], r) == prefix(t[j], r)\n    vector<vector<uint8_t>> overlapLen(M, vector<uint8_t>(M, 0));\n    for (int i = 0; i < M; i++) for (int j = 0; j < M; j++) if (i != j) {\n        uint8_t best = 0;\n        for (int r = 4; r >= 0; r--) {\n            bool ok = true;\n            for (int k = 0; k < r; k++) {\n                if (t[i][5 - r + k] != t[j][k]) { ok = false; break; }\n            }\n            if (ok) { best = (uint8_t)r; break; }\n        }\n        overlapLen[i][j] = best;\n    }\n\n    vector<uint8_t> maxOverlapFrom(M, 0);\n    for (int i = 0; i < M; i++) {\n        uint8_t mx = 0;\n        for (int j = 0; j < M; j++) if (i != j) mx = max(mx, overlapLen[i][j]);\n        maxOverlapFrom[i] = mx;\n    }\n\n    // Build merged letter sequence from an order using overlaps.\n    auto buildSeq = [&](const vector<int>& order) -> vector<char> {\n        vector<char> seq;\n        seq.reserve(5 * M);\n        auto addStringFrom = [&](int idx, int fromPos) {\n            for (int p = fromPos; p < 5; p++) seq.push_back(t[idx][p]);\n        };\n        addStringFrom(order[0], 0);\n        for (int i = 1; i < M; i++) {\n            int prev = order[i-1], cur = order[i];\n            int r = overlapLen[prev][cur];\n            addStringFrom(cur, r);\n        }\n        return seq;\n    };\n\n    // Beam search simulation: minimize cost for the fixed letter sequence.\n    auto simulateBeam = [&](const vector<int>& order) -> pair<ll, vector<pair<int,int>>> {\n        vector<char> seq = buildSeq(order);\n        int L = (int)seq.size();\n\n        // beam width (small enough for speed, large enough to improve)\n        const int BEAM = 28;\n\n        vector<vector<int>> cellsAt(L);\n        vector<vector<int>> parentAt(L);\n        vector<vector<ll>> costAt(L);\n\n        // position 0\n        int l0 = seq[0] - 'A';\n        const vector<int>& cand0 = posByLetter[l0];\n\n        vector<tuple<ll,int,int>> vec; // cost, cell, parentIdx(-1)\n        vec.reserve(cand0.size());\n        for (int c : cand0) {\n            ll cost = (ll)distCell[startCell][c] + 1;\n            vec.emplace_back(cost, c, -1);\n        }\n        nth_element(vec.begin(), vec.begin() + min((int)vec.size(), BEAM) - 1, vec.end(),\n                    [](auto &a, auto &b){ return get<0>(a) < get<0>(b); });\n        int take0 = min((int)vec.size(), BEAM);\n        vec.resize(take0);\n        sort(vec.begin(), vec.end(), [](auto &a, auto &b){ return get<0>(a) < get<0>(b); });\n\n        cellsAt[0].resize(take0);\n        parentAt[0].assign(take0, -1);\n        costAt[0].resize(take0);\n        for (int i = 0; i < take0; i++) {\n            cellsAt[0][i] = get<1>(vec[i]);\n            costAt[0][i] = get<0>(vec[i]);\n        }\n\n        // forward DP\n        for (int pos = 1; pos < L; pos++) {\n            int l = seq[pos] - 'A';\n            const vector<int>& cand = posByLetter[l];\n\n            const auto &prevCells = cellsAt[pos-1];\n            const auto &prevCosts = costAt[pos-1];\n            int prevSz = (int)prevCells.size();\n\n            // compute best transition into each candidate cell\n            vector<tuple<ll,int,int>> bestForCand; // cost, cell, parentIdx\n            bestForCand.reserve(cand.size());\n\n            for (int c : cand) {\n                ll best = (1LL<<62);\n                int bestParent = -1;\n                // min over beam states\n                for (int pi = 0; pi < prevSz; pi++) {\n                    ll v = prevCosts[pi] + (ll)distCell[prevCells[pi]][c] + 1;\n                    if (v < best) {\n                        best = v;\n                        bestParent = pi;\n                    }\n                }\n                bestForCand.emplace_back(best, c, bestParent);\n            }\n\n            int take = min((int)bestForCand.size(), BEAM);\n            // select top-k by cost\n            nth_element(bestForCand.begin(), bestForCand.begin() + take - 1, bestForCand.end(),\n                        [](auto &a, auto &b){ return get<0>(a) < get<0>(b); });\n            bestForCand.resize(take);\n            sort(bestForCand.begin(), bestForCand.end(), [](auto &a, auto &b){ return get<0>(a) < get<0>(b); });\n\n            cellsAt[pos].resize(take);\n            parentAt[pos].resize(take);\n            costAt[pos].resize(take);\n            for (int i = 0; i < take; i++) {\n                cellsAt[pos][i] = get<1>(bestForCand[i]);\n                parentAt[pos][i] = get<2>(bestForCand[i]);\n                costAt[pos][i] = get<0>(bestForCand[i]);\n            }\n        }\n\n        // choose best end\n        int idx = (int)(min_element(costAt[L-1].begin(), costAt[L-1].end()) - costAt[L-1].begin());\n        ll bestCost = costAt[L-1][idx];\n\n        // reconstruct chosen cells\n        vector<int> chosenCells(L);\n        int curIdx = idx;\n        for (int pos = L-1; pos >= 0; pos--) {\n            chosenCells[pos] = cellsAt[pos][curIdx];\n            curIdx = parentAt[pos][curIdx];\n            if (pos == 0) break;\n        }\n\n        vector<pair<int,int>> ops;\n        ops.reserve(L);\n        for (int pos = 0; pos < L; pos++) ops.push_back(coordOf(chosenCells[pos]));\n        return {bestCost, ops};\n    };\n\n    // Candidate starting strings: use a slightly deeper proxy (first+second letter)\n    vector<pair<int,int>> startCand; // (proxy, idx)\n    startCand.reserve(M);\n    for (int i = 0; i < M; i++) {\n        int lStart = st[i];\n        int lSecond = t[i][1] - 'A';\n\n        ll proxy = (1LL<<62);\n        for (int c : posByLetter[lStart]) {\n            // move to c for first char, then minimal move to any cell of second char\n            ll v = distCell[startCell][c] + (ll)distCellToLetter[c][lSecond] + 1;\n            proxy = min(proxy, v);\n        }\n        startCand.push_back({(int)min<ll>(proxy, INT_MAX), i});\n    }\n    sort(startCand.begin(), startCand.end());\n\n    // More restarts but still bounded by time\n    int RESTARTS = 10;\n\n    // Random tie-breaking helper\n    std::mt19937 rng(712367);\n\n    ll bestCost = (1LL<<62);\n    vector<pair<int,int>> bestOps;\n\n    for (int rep = 0; rep < RESTARTS; rep++) {\n        int startIdx = startCand[rep].second;\n\n        vector<int> order;\n        order.reserve(M);\n\n        vector<char> used(M, 0);\n        order.push_back(startIdx);\n        used[startIdx] = 1;\n\n        int cur = startIdx;\n\n        for (int step = 1; step < M; step++) {\n            int bestR = -1;\n            int bestMx = -1;\n            int bestD = INT_MAX;\n\n            // First gather best by lexicographic-like criteria:\n            // 1) overlapLen[cur][j] (higher better)\n            // 2) dist between letters en[cur] -> st[j] (lower better)\n            // 3) maxOverlapFrom[j] (higher better)\n            vector<int> cand;\n            for (int j = 0; j < M; j++) if (!used[j]) {\n                int r = overlapLen[cur][j];\n                int d = distLetter[en[cur]][st[j]];\n                int mx = (int)maxOverlapFrom[j];\n                if (r > bestR ||\n                    (r == bestR && d < bestD) ||\n                    (r == bestR && d == bestD && mx > bestMx)) {\n                    bestR = r; bestD = d; bestMx = mx;\n                    cand.clear();\n                    cand.push_back(j);\n                } else if (r == bestR && d == bestD && mx == bestMx) {\n                    cand.push_back(j);\n                }\n            }\n\n            // Randomly pick among equally good candidates to diversify\n            int pick = cand.empty() ? -1 : cand[rng() % cand.size()];\n            used[pick] = 1;\n            order.push_back(pick);\n            cur = pick;\n        }\n\n        auto [cost, ops] = simulateBeam(order);\n        if ((int)ops.size() > 5000) continue; // safety\n        if (cost < bestCost) {\n            bestCost = cost;\n            bestOps = std::move(ops);\n        }\n    }\n\n    for (auto [i, j] : bestOps) cout << i << ' ' << j << '\\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    long double eps;\n    if (!(cin >> N >> M >> eps)) return 0;\n\n    long long totalOil = 0;\n    for (int k = 0; k < M; k++) {\n        int d;\n        cin >> d;\n        totalOil += d;\n        for (int t = 0; t < d; t++) {\n            int i, j;\n            cin >> i >> j; // shape coords, ignore\n        }\n    }\n\n    auto drill_query = [&](int i, int j) -> long long {\n        cout << \"q 1 \" << i << \" \" << j << \"\\n\";\n        cout.flush();\n        long long v;\n        cin >> v;\n        return v;\n    };\n\n    auto div_query_2x2 = [&](int i0, int j0) -> long long {\n        cout << \"q 4 \"\n             << i0 << \" \" << j0 << \" \"\n             << i0 + 1 << \" \" << j0 << \" \"\n             << i0 << \" \" << j0 + 1 << \" \"\n             << i0 + 1 << \" \" << j0 + 1 << \"\\n\";\n        cout.flush();\n        long long r;\n        cin >> r;\n        return r;\n    };\n\n    const long long NN = 1LL * N * N;\n    long double lambdaCell = (long double)totalOil / (long double)NN;\n\n    // If dense enough, just drill all (avoids divination overhead).\n    if (lambdaCell >= 0.72L) {\n        vector<vector<long long>> val(N, vector<long long>(N, 0));\n        long long sumDrilled = 0;\n        for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) {\n            long long v = drill_query(i, j);\n            val[i][j] = v;\n            sumDrilled += v;\n        }\n        vector<pair<int,int>> ans;\n        for (int i = 0; i < N; i++) for (int j = 0; j < N; j++)\n            if (val[i][j] > 0) ans.push_back({i, j});\n        cout << \"a \" << ans.size();\n        for (auto [i,j] : ans) cout << \" \" << i << \" \" << j;\n        cout << \"\\n\";\n        cout.flush();\n        int ok; cin >> ok;\n        return 0;\n    }\n\n    // Choose offsets for 2x2 tilings (adaptive to reduce divination cost).\n    vector<pair<int,int>> offsets;\n\n    if (N % 2 == 0) {\n        // Even N: one tiling already covers all cells.\n        offsets.push_back({0, 0});\n        // Add second tiling only if fairly sparse (to improve ordering).\n        if (lambdaCell < 0.50L) offsets.push_back({1, 1});\n    } else {\n        // Odd N: use 3 offsets to cover borders more robustly.\n        offsets.push_back({0, 0});\n        offsets.push_back({1, 0});\n        offsets.push_back({0, 1});\n        // Optional 4th only when very sparse.\n        if (lambdaCell < 0.35L) offsets.push_back({1, 1});\n    }\n\n    const int k = 4;\n    const long double den = 1.0L - 2.0L * eps; // > 0 for eps <= 0.2\n\n    auto decode_block_sum_linear = [&](long long r) -> long double {\n        // v_block \u2248 (r - k*eps)/den, then clamp\n        long double v_est = ((long double)r - (long double)k * eps) / den;\n        if (v_est < 0) v_est = 0;\n        long double vmax = (long double)k * (long double)M;\n        if (v_est > vmax) v_est = vmax;\n        return v_est;\n    };\n\n    vector<long double> score(NN, 0.0L);\n    vector<int> coverCnt(NN, 0);\n\n    for (auto [si, sj] : offsets) {\n        for (int i0 = si; i0 + 1 < N; i0 += 2) {\n            for (int j0 = sj; j0 + 1 < N; j0 += 2) {\n                long long r = div_query_2x2(i0, j0);\n                long double v_est = decode_block_sum_linear(r);\n                long double perCell = v_est / 4.0L;\n\n                int id00 = i0 * N + j0;\n                int id10 = (i0 + 1) * N + j0;\n                int id01 = i0 * N + (j0 + 1);\n                int id11 = (i0 + 1) * N + (j0 + 1);\n\n                score[id00] += perCell; coverCnt[id00]++;\n                score[id10] += perCell; coverCnt[id10]++;\n                score[id01] += perCell; coverCnt[id01]++;\n                score[id11] += perCell; coverCnt[id11]++;\n            }\n        }\n    }\n\n    // Normalize scores by number of blocks covering each cell.\n    for (int id = 0; id < (int)NN; id++) {\n        if (coverCnt[id] > 0) score[id] /= (long double)coverCnt[id];\n        else score[id] = lambdaCell; // safety fallback\n    }\n\n    // Drill in descending estimated value order.\n    vector<int> order(NN);\n    iota(order.begin(), order.end(), 0);\n    sort(order.begin(), order.end(), [&](int a, int b) {\n        if (score[a] != score[b]) return score[a] > score[b];\n        return a < b;\n    });\n\n    vector<vector<long long>> val(N, vector<long long>(N, -1));\n    long long sumDrilled = 0;\n\n    for (int id : order) {\n        int i = id / N;\n        int j = id % N;\n        if (val[i][j] != -1) continue;\n\n        long long v = drill_query(i, j);\n        val[i][j] = v;\n        sumDrilled += v;\n\n        // Correctness guarantee:\n        // sum of remaining unrevealed cells must be 0 when sumDrilled == totalOil.\n        if (sumDrilled == totalOil) break;\n    }\n\n    vector<pair<int,int>> ans;\n    for (int i = 0; i < N; i++) for (int j = 0; j < N; j++)\n        if (val[i][j] > 0) ans.push_back({i, j});\n\n    cout << \"a \" << ans.size();\n    for (auto [i,j] : ans) cout << \" \" << i << \" \" << j;\n    cout << \"\\n\";\n    cout.flush();\n\n    int ok; cin >> ok;\n    return 0;\n}","ahc031":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const long long INFLL = (1LL << 60);\n\n// Hungarian algorithm (min cost) for square n<=50\n// cost[i][j] : row i -> col j\n// returns minimal total cost\nstatic long long hungarianMinCost(const vector<vector<long long>>& cost) {\n    int n = (int)cost.size();\n    // 1-indexed potentials, p stores matched row for each column\n    vector<long long> u(n + 1, 0), v(n + 1, 0);\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        vector<long long> minv(n + 1, INFLL);\n        vector<char> used(n + 1, false);\n\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 = 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        // augment\n        do {\n            int j1 = way[j0];\n            p[j0] = p[j1];\n            j0 = j1;\n        } while (j0 != 0);\n    }\n\n    // p[j] = row matched to column j. Build min cost.\n    vector<int> matchRow(n, -1);\n    for (int j = 1; j <= n; j++) {\n        int i = p[j];\n        if (i >= 1 && i <= n) matchRow[i - 1] = j - 1;\n    }\n    long long res = 0;\n    for (int i = 0; i < n; i++) res += cost[i][matchRow[i]];\n    return res;\n}\n\n// Hungarian assignment for final output.\n// returns matchRow[k] = strip index for reservation k.\nstatic vector<int> hungarianAssign(const vector<vector<long long>>& cost) {\n    int n = (int)cost.size();\n    vector<long long> u(n + 1, 0), v(n + 1, 0);\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        vector<long long> minv(n + 1, INFLL);\n        vector<char> used(n + 1, false);\n\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 = 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 != 0);\n    }\n\n    vector<int> matchRow(n, -1);\n    for (int j = 1; j <= n; j++) {\n        int i = p[j];\n        matchRow[i - 1] = j - 1;\n    }\n    return matchRow;\n}\n\n// boundaries: prefix sums after each strip except last, strictly increasing\nstatic vector<int> internalBoundaries(const vector<int>& w) {\n    int N = (int)w.size();\n    vector<int> b;\n    b.reserve(N - 1);\n    int pref = 0;\n    for (int i = 0; i < N - 1; i++) {\n        pref += w[i];\n        b.push_back(pref);\n    }\n    return b;\n}\n\nstatic int countCommonSorted(const vector<int>& a, const vector<int>& b) {\n    int i = 0, j = 0, t = 0;\n    while (i < (int)a.size() && j < (int)b.size()) {\n        if (a[i] == b[j]) { t++; i++; j++; }\n        else if (a[i] < b[j]) i++;\n        else j++;\n    }\n    return t;\n}\n\nstatic long long Ld_from_prev_curr(int W, const vector<int>& wPrev, const vector<int>& wCur) {\n    // L_d = W * | symmetric difference of boundary sets |\n    // boundary set size is N-1 each; symmetric diff size = 2((N-1)-|intersection|)\n    vector<int> bPrev = internalBoundaries(wPrev);\n    vector<int> bCur = internalBoundaries(wCur);\n    int t = countCommonSorted(bPrev, bCur);\n    int N = (int)wPrev.size();\n    int diffLines = (N - 1) - t;\n    return 2LL * W * diffLines;\n}\n\n// Greedy suffix widths builder for fixed identity mapping objective.\n// This produces a width vector summing to W, with prefix [0..c-1] fixed to wPrev.\nstatic vector<int> buildCandidateSuffixGreedy(\n    int W, const vector<vector<int>>& a, int d,\n    const vector<int>& wPrev, int c\n) {\n    int N = (int)wPrev.size();\n    vector<int> w(N, 1);\n\n    // fixed prefix\n    int used = 0;\n    for (int i = 0; i < c; i++) {\n        w[i] = wPrev[i];\n        used += w[i];\n    }\n    // suffix initially all 1, so total currently = used + (N-c)\n    int cur = used + (N - c);\n    int S = W - cur; // number of +1 increments to distribute\n    if (S == 0) return w;\n\n    // w0[k] = max w such that a > w*W  <=> w <= (a-1)/W\n    vector<int> w0(N, 0), rem(N, 0);\n    for (int k = 0; k < N; k++) {\n        int ak = a[d][k];\n        w0[k] = (ak - 1) / W; // can be 0..W-? (ak sum <= W^2)\n        if (w0[k] >= 1) rem[k] = ak - w0[k] * W; // in [1..W]\n    }\n\n    const long long NEG_FULL = -100LL * W;\n    const long long INF = (1LL << 60);\n\n    auto deltaOf = [&](int k) -> long long {\n        if (w[k] >= W) return INF; // shouldn't happen\n        if (w0[k] == 0) return 0LL;\n        if (w[k] < w0[k]) return NEG_FULL;\n        if (w[k] == w0[k]) return -100LL * rem[k];\n        return 0LL; // beyond -> already zero cost\n    };\n\n    priority_queue<pair<long long,int>, vector<pair<long long,int>>, greater<pair<long long,int>>> pq;\n    for (int k = c; k < N; k++) pq.push({deltaOf(k), k});\n\n    for (int step = 0; step < S; step++) {\n        auto [del, k] = pq.top(); pq.pop();\n        (void)del;\n        w[k]++; // feasible due to sum constraint\n        pq.push({deltaOf(k), k});\n    }\n    return w;\n}\n\nstatic vector<int> equalWidths(int W, int N) {\n    int base = W / N;\n    int rem = W % N;\n    vector<int> w(N, base);\n    for (int i = 0; i < rem; i++) w[i]++; // all >=1 since N<=50 and W=1000\n    return w;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int W, D, N;\n    cin >> W >> D >> N;\n    vector<vector<int>> a(D, vector<int>(N));\n    for (int d = 0; d < D; d++)\n        for (int k = 0; k < N; k++)\n            cin >> a[d][k];\n\n    vector<vector<int>> widths(D, vector<int>(N, 1));\n\n    // ---- Day 0: try a few candidate geometries, choose by exact assignment cost ----\n    vector<vector<int>> day0Cands;\n\n    // (1) equal\n    day0Cands.push_back(equalWidths(W, N));\n\n    // (2) greedy identity mapping (via greedy suffix builder with c=0, prefix empty)\n    {\n        vector<int> dummyPrev(N, 1);\n        int d = 0;\n        vector<int> w0 = buildCandidateSuffixGreedy(W, a, d, dummyPrev, 0);\n        day0Cands.push_back(w0);\n    }\n\n    // (3) greedy with reversed reservation indexing to alter strip width order/multiset\n    {\n        int d = 0;\n        vector<int> dummyPrev(N, 1);\n        // create reversed aRev for selection only by running greedy internally\n        // easiest: temporarily copy and compute w0 thresholds by using aRev values:\n        // We'll build greedy ourselves by using aRev on the same builder logic.\n        vector<vector<int>> aRev = a;\n        reverse(aRev[d].begin(), aRev[d].end());\n        vector<int> wrev = buildCandidateSuffixGreedy(W, aRev, d, dummyPrev, 0);\n        day0Cands.push_back(wrev);\n    }\n\n    long long bestDay0 = (1LL<<62);\n    vector<int> bestW0 = day0Cands[0];\n    {\n        int d = 0;\n        for (auto &w : day0Cands) {\n            vector<long long> b(N);\n            for (int s = 0; s < N; s++) b[s] = 1LL * w[s] * W;\n\n            vector<vector<long long>> cost(N, vector<long long>(N));\n            for (int k = 0; k < N; k++) {\n                for (int s = 0; s < N; s++) {\n                    long long diff = (long long)a[d][k] - b[s];\n                    cost[k][s] = (diff > 0) ? 100LL * diff : 0LL;\n                }\n            }\n            long long area = hungarianMinCost(cost);\n            if (area < bestDay0) {\n                bestDay0 = area;\n                bestW0 = w;\n            }\n        }\n    }\n    widths[0] = bestW0;\n\n    // ---- Days d>=1: choose best candidate among c=0..N with exact area cost + exact Ld ----\n    for (int d = 1; d < D; d++) {\n        const vector<int>& wPrev = widths[d-1];\n        long long bestTotal = (1LL<<62);\n        vector<int> bestW = wPrev;\n\n        for (int c = 0; c <= N; c++) {\n            vector<int> wCand;\n            if (c == N) wCand = wPrev;\n            else wCand = buildCandidateSuffixGreedy(W, a, d, wPrev, c);\n\n            // area shortfall min via assignment\n            vector<long long> b(N);\n            for (int s = 0; s < N; s++) b[s] = 1LL * wCand[s] * W;\n\n            vector<vector<long long>> cost(N, vector<long long>(N));\n            for (int k = 0; k < N; k++) {\n                for (int s = 0; s < N; s++) {\n                    long long diff = (long long)a[d][k] - b[s];\n                    cost[k][s] = (diff > 0) ? 100LL * diff : 0LL;\n                }\n            }\n            long long area = hungarianMinCost(cost);\n\n            // partition-change cost\n            long long Ld = Ld_from_prev_curr(W, wPrev, wCand);\n\n            long long total = area + Ld;\n            if (total < bestTotal) {\n                bestTotal = total;\n                bestW = std::move(wCand);\n            }\n        }\n        widths[d] = std::move(bestW);\n    }\n\n    // ---- Output: for each day, assign reservations to strips via Hungarian for exact minimal area term ----\n    for (int d = 0; d < D; d++) {\n        const vector<int>& w = widths[d];\n        vector<long long> pref(N + 1, 0);\n        for (int i = 0; i < N; i++) pref[i+1] = pref[i] + w[i];\n\n        vector<long long> b(N);\n        for (int s = 0; s < N; s++) b[s] = 1LL * w[s] * W;\n\n        vector<vector<long long>> cost(N, vector<long long>(N));\n        for (int k = 0; k < N; k++) {\n            for (int s = 0; s < N; s++) {\n                long long diff = (long long)a[d][k] - b[s];\n                cost[k][s] = (diff > 0) ? 100LL * diff : 0LL;\n            }\n        }\n\n        vector<int> match = hungarianAssign(cost); // reservation k -> strip match[k]\n\n        for (int k = 0; k < N; k++) {\n            int s = match[k];\n            long long x0 = pref[s];\n            long long x1 = pref[s+1];\n            // rectangle: (x0,0) to (x1,W)\n            cout << x0 << ' ' << 0 << ' ' << x1 << ' ' << W << '\\n';\n        }\n    }\n    return 0;\n}","ahc032":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int MOD = 998244353;\n\nstruct OpInfo {\n    array<uint8_t, 9> idx; // 9 affected cell ids\n    array<int, 9> add;    // add on those cells (mod MOD)\n    uint64_t lo = 0, hi = 0; // membership mask: cells 0..63 in lo, 64..80 in hi\n};\n\nstatic inline bool maskHas(const OpInfo& op, int cell) {\n    if (cell < 64) return (op.lo >> cell) & 1ULL;\n    return (op.hi >> (cell - 64)) & 1ULL;\n}\nstatic inline void maskSet(OpInfo& op, int cell) {\n    if (cell < 64) op.lo |= (1ULL << cell);\n    else op.hi |= (1ULL << (cell - 64));\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, K;\n    cin >> N >> M >> K;\n\n    vector<vector<int>> a(N, vector<int>(N));\n    for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) cin >> a[i][j];\n\n    vector<vector<vector<int>>> s(M, vector<vector<int>>(3, vector<int>(3)));\n    for (int m = 0; m < M; m++)\n        for (int i = 0; i < 3; i++)\n            for (int j = 0; j < 3; j++)\n                cin >> s[m][i][j];\n\n    const int NN = N * N;\n    if (N != 9 || NN != 81) { // per statement N=9\n        cout << 0 << \"\\n\";\n        return 0;\n    }\n\n    // Enumerate all possible placements (m,p,q), no rotation.\n    vector<OpInfo> ops;\n    vector<array<uint8_t,3>> meta; // {m,p,q}\n    ops.reserve(M * (N - 2) * (N - 2));\n    meta.reserve(M * (N - 2) * (N - 2));\n\n    for (int m = 0; m < M; m++) {\n        for (int p = 0; p <= N - 3; p++) {\n            for (int q = 0; q <= N - 3; q++) {\n                OpInfo op;\n                int t = 0;\n                for (int di = 0; di < 3; di++) {\n                    for (int dj = 0; dj < 3; dj++) {\n                        int ii = p + di, jj = q + dj;\n                        int cell = ii * N + jj;\n                        op.idx[t] = (uint8_t)cell;\n                        op.add[t] = s[m][di][dj] % MOD;\n                        maskSet(op, cell);\n                        t++;\n                    }\n                }\n                ops.push_back(op);\n                meta.push_back({(uint8_t)m, (uint8_t)p, (uint8_t)q});\n            }\n        }\n    }\n    const int numOps = (int)ops.size(); // 980\n\n    // opAddCell[opId][cell] = add for that cell if op touches it, else 0\n    vector<array<int,81>> opAddCell(numOps);\n    for (int opId = 0; opId < numOps; opId++) {\n        opAddCell[opId].fill(0);\n        for (int t = 0; t < 9; t++) {\n            int cell = ops[opId].idx[t];\n            opAddCell[opId][cell] = ops[opId].add[t];\n        }\n    }\n\n    // Build overlap sets: overlapOps[oldOp] = ops that touch any of oldOp's 9 cells.\n    vector<vector<int>> touchOps(81);\n    for (int opId = 0; opId < numOps; opId++) {\n        for (int t = 0; t < 9; t++) {\n            int cell = ops[opId].idx[t];\n            touchOps[cell].push_back(opId);\n        }\n    }\n    vector<vector<int>> overlapOps(numOps);\n    {\n        vector<int> mark(numOps, -1);\n        int stamp = 0;\n        for (int oldOp = 0; oldOp < numOps; oldOp++) {\n            stamp++;\n            vector<int> cand;\n            cand.reserve(600);\n            for (int t = 0; t < 9; t++) {\n                int cell = ops[oldOp].idx[t];\n                for (int op2 : touchOps[cell]) {\n                    if (mark[op2] != stamp) {\n                        mark[op2] = stamp;\n                        cand.push_back(op2);\n                    }\n                }\n            }\n            overlapOps[oldOp] = std::move(cand);\n        }\n    }\n\n    // initial residues\n    array<int,81> initX{};\n    for (int i = 0; i < N; i++)\n        for (int j = 0; j < N; j++)\n            initX[i * N + j] = a[i][j] % MOD;\n\n    auto sumScore = [&](const array<int,81>& x) -> long long {\n        long long sc = 0;\n        for (int i = 0; i < 81; i++) sc += x[i];\n        return sc;\n    };\n\n    auto deltaInsert = [&](int opId, const array<int,81>& x) -> long long {\n        const auto& op = ops[opId];\n        long long d = 0;\n        for (int t = 0; t < 9; t++) {\n            int cell = op.idx[t];\n            int oldv = x[cell];\n            int nv = oldv + op.add[t];\n            if (nv >= MOD) nv -= MOD;\n            d += (long long)nv - oldv;\n        }\n        return d;\n    };\n\n    auto deltaRemove = [&](int opId, const array<int,81>& x) -> long long {\n        const auto& op = ops[opId];\n        long long d = 0;\n        for (int t = 0; t < 9; t++) {\n            int cell = op.idx[t];\n            int oldv = x[cell];\n            int nv = oldv - op.add[t];\n            if (nv < 0) nv += MOD;\n            d += (long long)nv - oldv;\n        }\n        return d;\n    };\n\n    auto deltaReplace = [&](int oldOpId, int newOpId, const array<int,81>& x) -> long long {\n        const auto& oldOp = ops[oldOpId];\n        const auto& newOp = ops[newOpId];\n\n        long long d = 0;\n\n        // oldOp cells: x[cell] + newAdd - oldAdd\n        for (int t = 0; t < 9; t++) {\n            int cell = oldOp.idx[t];\n            int oldv = x[cell];\n            int oldAdd = oldOp.add[t];\n            int newAdd = opAddCell[newOpId][cell]; // 0 if new doesn't touch\n            int tmp = oldv + newAdd - oldAdd;\n            if (tmp < 0) tmp += MOD;\n            else if (tmp >= MOD) tmp -= MOD;\n            d += (long long)tmp - oldv;\n        }\n\n        // newOp cells not in oldOp: x[cell] + newAdd\n        for (int t = 0; t < 9; t++) {\n            int cell = newOp.idx[t];\n            if (maskHas(oldOp, cell)) continue;\n            int oldv = x[cell];\n            int nv = oldv + newOp.add[t];\n            if (nv >= MOD) nv -= MOD;\n            d += (long long)nv - oldv;\n        }\n\n        return d;\n    };\n\n    auto applyAdd = [&](int opId, array<int,81>& x) {\n        const auto& op = ops[opId];\n        for (int t = 0; t < 9; t++) {\n            int cell = op.idx[t];\n            int nv = x[cell] + op.add[t];\n            if (nv >= MOD) nv -= MOD;\n            x[cell] = nv;\n        }\n    };\n    auto applyRemove = [&](int opId, array<int,81>& x) {\n        const auto& op = ops[opId];\n        for (int t = 0; t < 9; t++) {\n            int cell = op.idx[t];\n            int nv = x[cell] - op.add[t];\n            if (nv < 0) nv += MOD;\n            x[cell] = nv;\n        }\n    };\n\n    auto nowMs = []() -> int {\n        using namespace std::chrono;\n        static auto st = steady_clock::now();\n        return (int)duration_cast<milliseconds>(steady_clock::now() - st).count();\n    };\n\n    // Greedy init for fixed K, choosing among top TOPS each step.\n    auto greedyInitFixedK = [&](uint64_t seed) -> vector<int> {\n        mt19937_64 rng(seed);\n        array<int,81> x = initX;\n\n        vector<int> opsVec;\n        opsVec.reserve(K);\n\n        const int TOPS = 28;\n\n        for (int step = 0; step < K; step++) {\n            vector<pair<long long,int>> v;\n            v.reserve(numOps);\n            for (int opId = 0; opId < numOps; opId++) {\n                v.push_back({deltaInsert(opId, x), opId});\n            }\n            int B = min(TOPS, numOps);\n            nth_element(v.begin(), v.begin() + B, v.end(),\n                        [](const auto& A, const auto& B){ return A.first > B.first; });\n            v.resize(B);\n            sort(v.begin(), v.end(), [](const auto& A, const auto& B){ return A.first > B.first; });\n\n            // stochastic pick among top B, weight = max(d,0)+1\n            long long sumw = 0;\n            vector<long long> w(B);\n            for (int i = 0; i < B; i++) {\n                long long wi = v[i].first;\n                if (wi < 0) wi = 0;\n                wi += 1;\n                w[i] = wi;\n                sumw += wi;\n            }\n\n            unsigned long long r = (unsigned long long)rng() % (unsigned long long)sumw;\n            long long acc = 0;\n            int pick = 0;\n            for (int i = 0; i < B; i++) {\n                acc += w[i];\n                if ((long long)r < acc) { pick = i; break; }\n            }\n\n            int chosen = v[pick].second;\n            opsVec.push_back(chosen);\n            applyAdd(chosen, x);\n        }\n        return opsVec;\n    };\n\n    // Fixed-K replacement-only anneal (fast/stable).\n    auto annealFixedK = [&](vector<int> opsVec, uint64_t seed, int timeBudgetMs) -> pair<long long, vector<int>> {\n        mt19937_64 rng(seed);\n\n        array<int,81> x = initX;\n        for (int opId : opsVec) applyAdd(opId, x);\n\n        long long curScore = sumScore(x);\n        long long bestScore = curScore;\n        vector<int> bestOps = opsVec;\n\n        // maintain an \"insert top\" list for candidate mixing\n        vector<int> topInsert;\n        topInsert.reserve(250);\n        int lastRefresh = nowMs();\n\n        auto refreshTopInsert = [&]() {\n            vector<pair<long long,int>> v;\n            v.reserve(numOps);\n            for (int opId = 0; opId < numOps; opId++) {\n                v.push_back({deltaInsert(opId, x), opId});\n            }\n            int B = 220;\n            nth_element(v.begin(), v.begin() + B, v.end(),\n                        [](const auto& A, const auto& B){ return A.first > B.first; });\n            v.resize(B);\n            sort(v.begin(), v.end(), [](const auto& A, const auto& B){ return A.first > B.first; });\n            topInsert.clear();\n            topInsert.reserve(B);\n            for (auto &p : v) topInsert.push_back(p.second);\n        };\n\n        refreshTopInsert();\n\n        int start = nowMs();\n        while (true) {\n            int elapsed = nowMs() - start;\n            if (elapsed >= timeBudgetMs) break;\n\n            double prog = (double)elapsed / (double)timeBudgetMs;\n            // temperature: cool down\n            double T = 2.8e9 + (1.0e6 - 2.8e9) * prog;\n\n            if (nowMs() - lastRefresh >= 120) {\n                refreshTopInsert();\n                lastRefresh = nowMs();\n            }\n\n            int pos = (int)(rng() % (unsigned)K);\n            int oldOp = opsVec[pos];\n\n            // Sample candidates and keep top few deltas\n            const int SAMPLE = 28;\n            const int TOPP = 5;\n\n            array<long long, TOPP> topD{};\n            array<int, TOPP> topId{};\n            int tcnt = 0;\n\n            auto pickCand = [&]() -> int {\n                int r = (int)(rng() % 100);\n                if (r < 70) {\n                    auto &ov = overlapOps[oldOp];\n                    if (!ov.empty()) return ov[(int)(rng() % (unsigned)ov.size())];\n                }\n                if (r < 90 && !topInsert.empty()) {\n                    return topInsert[(int)(rng() % (unsigned)topInsert.size())];\n                }\n                return (int)(rng() % (unsigned)numOps);\n            };\n\n            for (int it = 0; it < SAMPLE; it++) {\n                int cand = pickCand();\n                if (cand == oldOp) continue;\n                long long d = deltaReplace(oldOp, cand, x);\n\n                if (tcnt < TOPP) {\n                    topD[tcnt] = d;\n                    topId[tcnt] = cand;\n                    tcnt++;\n                    for (int i = tcnt - 1; i > 0; i--) {\n                        if (topD[i] > topD[i - 1]) {\n                            swap(topD[i], topD[i - 1]);\n                            swap(topId[i], topId[i - 1]);\n                        }\n                    }\n                } else if (d > topD[TOPP - 1]) {\n                    topD[TOPP - 1] = d;\n                    topId[TOPP - 1] = cand;\n                    for (int i = TOPP - 1; i > 0; i--) {\n                        if (topD[i] > topD[i - 1]) {\n                            swap(topD[i], topD[i - 1]);\n                            swap(topId[i], topId[i - 1]);\n                        }\n                    }\n                }\n            }\n            if (tcnt == 0) continue;\n\n            // stochastic choose among topD\n            long long sumw = 0;\n            array<long long, TOPP> w{};\n            for (int i = 0; i < tcnt; i++) {\n                long long wi = topD[i] + 1; // can be small/negative; +1 shifts\n                if (wi < 1) wi = 1;\n                w[i] = wi;\n                sumw += wi;\n            }\n            unsigned long long rr = (unsigned long long)rng() % (unsigned long long)sumw;\n            long long acc = 0;\n            int pick = 0;\n            for (int i = 0; i < tcnt; i++) {\n                acc += w[i];\n                if ((long long)rr < acc) { pick = i; break; }\n            }\n\n            int newOp = topId[pick];\n            long long d = topD[pick];\n\n            if (newOp == oldOp) continue;\n\n            bool ok = false;\n            if (d >= 0) ok = true;\n            else {\n                double z = (double)d / T; // negative\n                if (z < -50) ok = false;\n                else {\n                    double p = exp(z);\n                    double u = (double)rng() / (double)rng.max();\n                    ok = (u < p);\n                }\n            }\n            if (!ok) continue;\n\n            applyRemove(oldOp, x);\n            applyAdd(newOp, x);\n            opsVec[pos] = newOp;\n            curScore += d;\n\n            if (curScore > bestScore) {\n                bestScore = curScore;\n                bestOps = opsVec;\n            }\n        }\n\n        return {bestScore, bestOps};\n    };\n\n    // Post-pruning: delete operations with positive marginal gain (deltaRemove>0).\n    auto pruneOps = [&](vector<int> opsVec) -> pair<long long, vector<int>> {\n        array<int,81> x = initX;\n        for (int opId : opsVec) applyAdd(opId, x);\n        long long cur = sumScore(x);\n\n        if (opsVec.empty()) return {cur, opsVec};\n\n        // random-ish order for deletions\n        mt19937_64 rng((uint64_t)opsVec.size() * 1234567ULL + 89123ULL);\n\n        int passes = 2; // cheap\n        for (int pass = 0; pass < passes; pass++) {\n            if (opsVec.empty()) break;\n            vector<int> order(opsVec.size());\n            iota(order.begin(), order.end(), 0);\n            shuffle(order.begin(), order.end(), rng);\n\n            for (int idx : order) {\n                if (idx >= (int)opsVec.size()) continue;\n                int opId = opsVec[idx];\n                long long d = deltaRemove(opId, x);\n                if (d > 0) {\n                    applyRemove(opId, x);\n                    cur += d;\n                    opsVec.erase(opsVec.begin() + idx);\n                }\n            }\n        }\n        return {cur, opsVec};\n    };\n\n    int globalStart = nowMs();\n    const int TIME = 1880;\n\n    long long bestScore = -1;\n    vector<int> bestOps;\n\n    int restarts = 4;\n    for (int r = 0; r < restarts; r++) {\n        int elapsed = nowMs() - globalStart;\n        if (elapsed > TIME - 120) break;\n\n        int timeLeft = TIME - elapsed;\n        int budget = max(180, timeLeft / (restarts - r));\n\n        uint64_t seed = 123456789ULL + 10007ULL * (r + 1) * 1009ULL;\n        vector<int> initOps = greedyInitFixedK(seed ^ 0x9e377b97f4a7c15ULL);\n\n        auto [sc, opsBest] = annealFixedK(std::move(initOps), seed + 424242ULL, budget);\n\n        // prune to allow L < K if beneficial\n        auto [scPruned, prunedOps] = pruneOps(std::move(opsBest));\n\n        if (scPruned > bestScore) {\n            bestScore = scPruned;\n            bestOps = std::move(prunedOps);\n        }\n    }\n\n    // Output with L <= K\n    int L = (int)bestOps.size();\n    if (L > K) L = K;\n\n    cout << L << \"\\n\";\n    for (int i = 0; i < L; i++) {\n        auto mm = meta[bestOps[i]];\n        cout << (int)mm[0] << \" \" << (int)mm[1] << \" \" << (int)mm[2] << \"\\n\";\n    }\n    return 0;\n}","ahc033":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic inline int manhattan(int x1,int y1,int x2,int y2){\n    return abs(x1-x2)+abs(y1-y2);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    cin >> N;\n    vector<vector<int>> A(N, vector<int>(N));\n    for(int i=0;i<N;i++) for(int j=0;j<N;j++) cin >> A[i][j];\n\n    const int TOTAL = N*N;\n    const int MAX_T = 10000;\n\n    // grid[x][y] = container id or -1\n    vector<vector<int>> grid(N, vector<int>(N, -1));\n\n    // position tracking for each container id\n    vector<int> px(TOTAL, -3), py(TOTAL, -3);\n\n    // receiving placement counters per row\n    vector<int> recvNext(N, 0);\n\n    // disp[g][k] means container (g*N+k) has been dispatched from gate g\n    vector<vector<bool>> disp(N, vector<bool>(N, false));\n    vector<int> nextK(N, 0); // smallest k not yet dispatched in each gate\n\n    // crane0 state\n    int cx = 0, cy = 0;\n    bool holding = false;\n    int heldId = -1;\n\n    // current plan while not holding\n    bool planned = false;\n    int pickX = -1, pickY = -1;\n    int relX = -1, relY = -1;\n    bool pickAfterIsDispatch = false; // if true => release to correct dispatch gate immediately\n\n    auto moveNotHolding = [&](int x,int y,int tx,int ty)->char{\n        if (x < tx) return 'D';\n        if (x > tx) return 'U';\n        if (y < ty) return 'R';\n        if (y > ty) return 'L';\n        return '.';\n    };\n    auto moveHolding = [&](int x,int y,int tx,int ty)->char{\n        // right-first helps freeing (row,0) quickly after picking\n        if (y < ty) return 'R';\n        if (y > ty) return 'L';\n        if (x < tx) return 'D';\n        if (x > tx) return 'U';\n        return '.';\n    };\n\n    // buffer cells: rows 0..N-1, columns 1..N-2\n    vector<pair<int,int>> bufferCells;\n    for(int x=0;x<N;x++) for(int y=1;y<=N-2;y++) bufferCells.push_back({x,y});\n    int bestBufCol = N - 2;\n\n    vector<char> ops0;\n    ops0.reserve(MAX_T);\n\n    int dispatchedTotal = 0;\n\n    auto isExpectedMinAvailable = [&](int &outPickX, int &outPickY, int &outGate)->bool{\n        long long bestCost = (1LL<<60);\n        outPickX = outPickY = outGate = -1;\n\n        for(int g=0; g<N; g++){\n            int k = nextK[g];\n            if(k >= N) continue;\n            int id = g*N + k;\n            int x = px[id], y = py[id];\n            if(x < 0) continue;\n            if(grid[x][y] != id) continue;\n\n            // should never be at dispatch gate because step3 clears it, but keep safe:\n            if(!(y==0 || (1<=y && y<=N-2))) continue;\n\n            long long cost = (long long)manhattan(cx,cy,x,y) + (long long)manhattan(x,y,g,N-1);\n            if(cost < bestCost){\n                bestCost = cost;\n                outPickX = x; outPickY = y; outGate = g;\n            }\n        }\n        return outPickX != -1;\n    };\n\n    auto findNearestOccupied = [&]()->pair<int,int>{\n        long long best = (1LL<<60);\n        pair<int,int> ans = {-1,-1};\n\n        // search receiving and buffers\n        for(int i=0;i<N;i++){\n            if(grid[i][0] != -1){\n                long long d = manhattan(cx,cy,i,0);\n                if(d < best){ best = d; ans = {i,0}; }\n            }\n        }\n        for(auto [bx,by]: bufferCells){\n            if(grid[bx][by] != -1){\n                long long d = manhattan(cx,cy,bx,by);\n                if(d < best){ best = d; ans = {bx,by}; }\n            }\n        }\n        return ans;\n    };\n\n    for (int t = 0; t < MAX_T; t++) {\n        // ---- step1: place arriving containers at receiving gates (i,0) ----\n        for (int i = 0; i < N; i++) {\n            if (recvNext[i] >= N) continue;\n            if (grid[i][0] != -1) continue;\n\n            // blocked only if crane0 is holding at that exact square\n            if (holding && cx == i && cy == 0) continue;\n\n            int id = A[i][recvNext[i]];\n            grid[i][0] = id;\n            px[id] = i; py[id] = 0;\n            recvNext[i]++;\n        }\n\n        // ---- step2: decide action for crane0 ----\n        char act0 = '.';\n\n        if (holding) {\n            // release at planned target\n            if (cx == relX && cy == relY) {\n                act0 = 'Q';\n            } else {\n                act0 = moveHolding(cx,cy,relX,relY);\n            }\n        } else {\n            // if holding just ended earlier, clear plan status already.\n            // recompute plan only when not holding.\n            if (!planned) {\n                // 1) try dispatching expected-min container if available\n                int pX, pY, gate;\n                bool ok = isExpectedMinAvailable(pX,pY,gate);\n                if(ok){\n                    planned = true;\n                    pickX = pX; pickY = pY;\n                    pickAfterIsDispatch = true;\n                    relX = gate; relY = N-1;\n                } else {\n                    // 2) buffer not full? => store some receiving container into an empty buffer\n                    int bufSize = (int)bufferCells.size();\n                    int bufCount = 0;\n                    for(auto [bx,by]: bufferCells) if(grid[bx][by] != -1) bufCount++;\n                    bool bufferFull = (bufCount == bufSize);\n\n                    if(!bufferFull){\n                        // Choose which receiving container to store and where.\n                        // We'll prefer storing into column bestBufCol, and prefer row = gate of that container.\n                        long long bestScore = (1LL<<60);\n                        int selPickX=-1, selPickY=-1;\n                        int selRelX=-1, selRelY=-1;\n\n                        for(int r=0;r<N;r++){\n                            if(grid[r][0] == -1) continue; // receiving occupied required\n                            int id = grid[r][0];\n                            int g = id / N;\n                            int k = id % N;\n\n                            // must ensure we won't \"lose\" correctness: storing is staging only.\n                            // (M1 handled later by dispatching expected-min when possible.)\n\n                            // find best empty buffer cell for this g, with preference col bestBufCol\n                            vector<pair<int,int>> candidates;\n                            // first try (g, bestBufCol)\n                            if(bestBufCol >= 1 && bestBufCol <= N-2 && grid[g][bestBufCol]==-1){\n                                candidates.push_back({g,bestBufCol});\n                            }\n                            // otherwise try other columns in same row g\n                            for(int y=1;y<=N-2;y++){\n                                if(grid[g][y]==-1 && (g!=g || y!=bestBufCol)) candidates.push_back({g,y});\n                            }\n                            // if still none, try any empty buffer\n                            if(candidates.empty()){\n                                for(auto [bx,by]: bufferCells){\n                                    if(grid[bx][by]==-1) candidates.push_back({bx,by});\n                                }\n                            }\n\n                            // Choose candidate release cell that minimizes distance from current crane to store later.\n                            // We'll incorporate current position for time: cost = dist(cx->(r,0)) + dist((r,0)->(rel))\n                            long long bestCandScore = (1LL<<60);\n                            int candRelX=-1, candRelY=-1;\n                            for(auto [bx,by]: candidates){\n                                // prefer rightmost column slightly (ties will be decided here)\n                                long long storeCost = (long long)manhattan(cx,cy,r,0) + (long long)manhattan(r,0,bx,by);\n                                long long gateGap = (long long)k - nextK[g]; // smaller means closer to being expected-min\n                                // Weighted comparison: prioritize low storeCost, then low gateGap, then prefer rightmost buffer\n                                long long score = storeCost * 10 + gateGap;\n                                if(score < bestCandScore){\n                                    bestCandScore = score;\n                                    candRelX = bx; candRelY = by;\n                                }\n                            }\n\n                            if(candRelX == -1) continue;\n\n                            long long finalScore = bestCandScore;\n                            if(finalScore < bestScore){\n                                bestScore = finalScore;\n                                selPickX = r; selPickY = 0;\n                                selRelX = candRelX; selRelY = candRelY;\n                            }\n                        }\n\n                        if(selPickX != -1){\n                            planned = true;\n                            pickX = selPickX; pickY = selPickY;\n                            pickAfterIsDispatch = false; // store\n                            relX = selRelX; relY = selRelY;\n                        }\n                    } else {\n                        // buffer full: dispatch something from buffer (may cause M1, but prevents deadlock)\n                        // Choose the best (lowest gap to expected-min), and with good cost.\n                        long long bestDispScore = (1LL<<60);\n                        int selPickX=-1, selPickY=-1, selGate=-1;\n\n                        for(auto [bx,by]: bufferCells){\n                            if(grid[bx][by] == -1) continue;\n                            int id = grid[bx][by];\n                            int g = id / N;\n                            int k = id % N;\n\n                            long long gap = (long long)k - nextK[g]; // >= 0 ideally if nextK not passed\n                            long long dispCost = (long long)manhattan(cx,cy,bx,by) + (long long)manhattan(bx,by,g,N-1);\n                            // prioritize expected correctness (small gap), then cost\n                            long long score = gap * 100 + dispCost;\n                            if(score < bestDispScore){\n                                bestDispScore = score;\n                                selPickX = bx; selPickY = by; selGate = g;\n                            }\n                        }\n\n                        if(selPickX != -1){\n                            planned = true;\n                            pickX = selPickX; pickY = selPickY;\n                            pickAfterIsDispatch = true;\n                            relX = selGate; relY = N-1;\n                        }\n                    }\n                }\n\n                // 3) Fallback: if still no plan, move toward nearest occupied cell (avoid idle turns)\n                if(!planned){\n                    auto nearest = findNearestOccupied();\n                    if(nearest.first != -1){\n                        act0 = moveNotHolding(cx,cy,nearest.first,nearest.second);\n                    } else {\n                        act0 = '.'; // nothing on board\n                    }\n                } else {\n                    // we have plan: move toward pick or pick if at location\n                    if (cx == pickX && cy == pickY) act0 = 'P';\n                    else act0 = moveNotHolding(cx,cy,pickX,pickY);\n                }\n            } else {\n                // already have plan\n                if (cx == pickX && cy == pickY) act0 = 'P';\n                else act0 = moveNotHolding(cx,cy,pickX,pickY);\n            }\n        }\n\n        ops0.push_back(act0);\n\n        // ---- apply crane0 action (step2 effects) ----\n        if (holding) {\n            if (act0 == 'Q') {\n                // release into target\n                if (grid[cx][cy] != -1) return 0; // illegal\n                grid[cx][cy] = heldId;\n                px[heldId] = cx; py[heldId] = cy;\n                holding = false;\n                heldId = -1;\n                planned = false; // force replanning next iteration\n                pickAfterIsDispatch = false;\n            } else if (act0=='U' || act0=='D' || act0=='L' || act0=='R') {\n                int nx=cx, ny=cy;\n                if(act0=='U') nx--;\n                if(act0=='D') nx++;\n                if(act0=='L') ny--;\n                if(act0=='R') ny++;\n                if(!(0<=nx && nx<N && 0<=ny && ny<N)) return 0;\n                cx=nx; cy=ny;\n            } else if (act0=='.') {\n                // ok\n            } else {\n                return 0;\n            }\n        } else {\n            if (act0 == 'P') {\n                if (grid[cx][cy] == -1) return 0;\n                heldId = grid[cx][cy];\n                grid[cx][cy] = -1;\n                px[heldId] = -1; py[heldId] = -1;\n                holding = true;\n\n                // keep relX/relY from the plan\n            } else if (act0=='U' || act0=='D' || act0=='L' || act0=='R') {\n                int nx=cx, ny=cy;\n                if(act0=='U') nx--;\n                if(act0=='D') nx++;\n                if(act0=='L') ny--;\n                if(act0=='R') ny++;\n                if(!(0<=nx && nx<N && 0<=ny && ny<N)) return 0;\n                cx=nx; cy=ny;\n            } else if (act0=='.') {\n                // ok\n            } else {\n                return 0;\n            }\n        }\n\n        // ---- step3: dispatch at dispatch gates ----\n        for(int i=0;i<N;i++){\n            if(grid[i][N-1] != -1){\n                int id = grid[i][N-1];\n                grid[i][N-1] = -1;\n                px[id] = -2; py[id] = -2;\n                dispatchedTotal++;\n\n                int g = id / N;\n                int k = id % N;\n                if(!disp[g][k]){\n                    disp[g][k] = true;\n                    while(nextK[g] < N && disp[g][nextK[g]]) nextK[g]++;\n                }\n            }\n        }\n\n        if(dispatchedTotal == TOTAL) break;\n    }\n\n    int L = (int)ops0.size();\n    if(L == 0){ // extremely unlikely\n        cout << \".\\n\";\n        cout << \".\\n\";\n        cout << \".\\n\";\n        cout << \".\\n\";\n        cout << \".\\n\";\n        return 0;\n    }\n\n    vector<string> out(N);\n    out[0].assign(ops0.begin(), ops0.end());\n    for(int i=1;i<N;i++){\n        out[i].clear();\n        out[i].push_back('B');\n        if(L > 1) out[i] += string(L-1, '.');\n    }\n\n    for(int i=0;i<N;i++) cout << out[i] << \"\\n\";\n    return 0;\n}","ahc034":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic inline int cellId(int r, int c, int N) { return r * N + c; }\nstatic inline pair<int,int> cellRC(int id, int N) { return {id / N, id % N}; }\n\nstatic inline void movePath(int &r, int &c, int nr, int nc, vector<string> &ops) {\n    while (r < nr) { ops.push_back(\"D\"); r++; }\n    while (r > nr) { ops.push_back(\"U\"); r--; }\n    while (c < nc) { ops.push_back(\"R\"); c++; }\n    while (c > nc) { ops.push_back(\"L\"); c--; }\n}\n\nstruct Job {\n    int startId = -1;\n    int endId = -1;\n    int totalLoad = 0;\n\n    vector<int> targetIds;   // ordered for internal route\n    vector<int> amounts;     // aligned with targetIds\n\n    long long internalCost = 0; // includes load/unload + loaded travel, no empty move\n    int internalSteps = 0;      // sum of manhattan distances during loaded travel\n    int targetCount = 0;        // number of target visits (len of targetIds)\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++) for (int j = 0; j < N; j++) cin >> h[i][j];\n\n    vector<int> sources, sinks;\n    vector<int> posAmt(N*N, 0), negAmt(N*N, 0);\n\n    for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) {\n        int id = cellId(i, j, N);\n        if (h[i][j] > 0) { sources.push_back(id); posAmt[id] = h[i][j]; }\n        else if (h[i][j] < 0) { sinks.push_back(id); negAmt[id] = -h[i][j]; }\n    }\n    if (sources.empty()) return 0;\n\n    const int V = N * N;\n    vector<vector<int>> dist(V, vector<int>(V, 0));\n    for (int a = 0; a < V; a++) {\n        auto [ra, ca] = cellRC(a, N);\n        for (int b = 0; b < V; b++) {\n            auto [rb, cb] = cellRC(b, N);\n            dist[a][b] = abs(ra - rb) + abs(ca - cb);\n        }\n    }\n\n    // avgDist for internal greedy scoring\n    vector<double> avgDist(V, 0.0);\n    for (int a = 0; a < V; a++) {\n        long long sum = 0;\n        for (int b = 0; b < V; b++) if (b != a) sum += dist[a][b];\n        avgDist[a] = (double)sum / (double)(V - 1);\n    }\n\n    // -------- Allocation: global distance-sorted greedy (robust baseline) --------\n    int S = (int)sources.size();\n    int D = (int)sinks.size();\n    vector<int> remS(S), remD(D);\n    for (int i = 0; i < S; i++) remS[i] = posAmt[sources[i]];\n    for (int j = 0; j < D; j++) remD[j] = negAmt[sinks[j]];\n\n    vector<vector<int>> alloc(S, vector<int>(D, 0));\n    struct Edge { int c; int i; int j; };\n    vector<Edge> edges;\n    edges.reserve((size_t)S * (size_t)D);\n    for (int i = 0; i < S; i++) for (int j = 0; j < D; j++)\n        edges.push_back({dist[sources[i]][sinks[j]], i, j});\n\n    sort(edges.begin(), edges.end(), [](const Edge& a, const Edge& b){\n        if (a.c != b.c) return a.c < b.c;\n        if (a.i != b.i) return a.i < b.i;\n        return a.j < b.j;\n    });\n\n    for (auto &e : edges) {\n        if (remS[e.i] == 0 || remD[e.j] == 0) continue;\n        int x = min(remS[e.i], remD[e.j]);\n        alloc[e.i][e.j] += x;\n        remS[e.i] -= x;\n        remD[e.j] -= x;\n    }\n\n    // -------- Jobs: one per source, load all at once --------\n    vector<Job> jobs;\n    jobs.reserve(S);\n    for (int i = 0; i < S; i++) {\n        int load = posAmt[sources[i]];\n        if (load == 0) continue;\n        Job jb;\n        jb.startId = sources[i];\n        jb.totalLoad = load;\n\n        for (int j = 0; j < D; j++) if (alloc[i][j] > 0) {\n            jb.targetIds.push_back(sinks[j]);\n            jb.amounts.push_back(alloc[i][j]);\n        }\n        jb.targetCount = (int)jb.targetIds.size();\n        jobs.push_back(std::move(jb));\n    }\n    int M = (int)jobs.size();\n    mt19937 rng(123456789);\n\n    // -------- Internal ordering per job --------\n    auto computeInternalCostAndSteps = [&](const Job &jb,\n                                           const vector<int> &ordIdx,\n                                           const vector<int> &tids,\n                                           const vector<int> &amts,\n                                           int &stepsOut) -> long long {\n        int cur = jb.startId;\n        int load = jb.totalLoad;\n        long long moveCost = 0;\n        int steps = 0;\n        for (int pos = 0; pos < (int)ordIdx.size(); pos++) {\n            int idx = ordIdx[pos];\n            int tid = tids[idx];\n            int amt = amts[idx];\n            int d = dist[cur][tid];\n            steps += d;\n            moveCost += 1LL * d * (100LL + (long long)load);\n            load -= amt;\n            cur = tid;\n        }\n        stepsOut = steps;\n        return moveCost + 2LL * jb.totalLoad;\n    };\n\n    for (auto &jb : jobs) {\n        int k = jb.targetCount;\n        if (k == 0) {\n            jb.endId = jb.startId;\n            jb.internalCost = 0;\n            jb.internalSteps = 0;\n            continue;\n        }\n        if (k == 1) {\n            jb.endId = jb.targetIds[0];\n            jb.internalSteps = dist[jb.startId][jb.endId];\n            jb.internalCost = 1LL * jb.internalSteps * (100LL + (long long)jb.totalLoad) + 2LL * jb.totalLoad;\n            continue;\n        }\n\n        vector<int> tids = jb.targetIds;\n        vector<int> amts = jb.amounts;\n\n        auto evalIdxOrder = [&](const vector<int> &ordIdx, int &stepsOut)->long long{\n            return computeInternalCostAndSteps(jb, ordIdx, tids, amts, stepsOut);\n        };\n\n        long long bestCost = (1LL<<62);\n        int bestSteps = 0;\n        vector<int> bestOrdIdx;\n\n        int trials = (k <= 35 ? 28 : (k <= 90 ? 16 : 12));\n        int topK = (k <= 35 ? 6 : 4);\n        double alpha = 1.12;\n\n        for (int tt = 0; tt < trials; tt++) {\n            vector<char> used(k, 0);\n            vector<int> ordIdx;\n            ordIdx.reserve(k);\n\n            int cur = jb.startId;\n            int load = jb.totalLoad;\n\n            while ((int)ordIdx.size() < k) {\n                int rem = k - (int)ordIdx.size();\n                vector<pair<double,int>> cand;\n                cand.reserve(rem);\n\n                for (int i = 0; i < k; i++) if (!used[i]) {\n                    int tid = tids[i];\n                    int amt = amts[i];\n\n                    double imm = 1.0 * dist[cur][tid] * (100.0 + (double)load);\n                    double futureDistEst = (double)(rem - 1) * avgDist[tid];\n                    double save = alpha * (double)amt * futureDistEst;\n                    cand.push_back({imm - save, i});\n                }\n\n                int take = min(topK, (int)cand.size());\n                nth_element(cand.begin(), cand.begin() + take, cand.end(),\n                            [](auto &a, auto &b){ return a.first < b.first; });\n                cand.resize(take);\n                sort(cand.begin(), cand.end(), [](auto &a, auto &b){ return a.first < b.first; });\n\n                int pick = (take == 1 ? 0 : (int)(rng() % take));\n                int idx = cand[pick].second;\n\n                used[idx] = 1;\n                ordIdx.push_back(idx);\n                cur = tids[idx];\n                load -= amts[idx];\n            }\n\n            int steps = 0;\n            long long cost = evalIdxOrder(ordIdx, steps);\n            if (cost < bestCost) {\n                bestCost = cost;\n                bestSteps = steps;\n                bestOrdIdx = std::move(ordIdx);\n            }\n        }\n\n        // Local search: insertion + 2-opt (exact eval)\n        vector<int> curIdx = bestOrdIdx;\n        long long curBest = bestCost;\n        int curSteps = bestSteps;\n\n        auto evalOrderIdx = [&](const vector<int> &idxOrder)->pair<long long,int>{\n            int st = 0;\n            long long cst = evalIdxOrder(idxOrder, st);\n            return {cst, st};\n        };\n\n        int itIns = (k <= 45 ? 360 : (k <= 120 ? 260 : 200));\n        for (int it = 0; it < itIns; it++) {\n            int a = rng() % k;\n            int b = rng() % k;\n            if (a == b) continue;\n\n            vector<int> nxt = curIdx;\n            int val = nxt[a];\n            nxt.erase(nxt.begin() + a);\n            int bb = b;\n            if (bb > a) bb--;\n            nxt.insert(nxt.begin() + bb, val);\n\n            auto [c2, st2] = evalOrderIdx(nxt);\n            if (c2 < curBest) {\n                curBest = c2;\n                curSteps = st2;\n                curIdx = std::move(nxt);\n            }\n        }\n\n        if (k <= 90) {\n            int it2 = 240;\n            for (int it = 0; it < it2; it++) {\n                int l = rng() % k, r = rng() % k;\n                if (l == r) continue;\n                if (l > r) swap(l, r);\n                if (r - l < 2) continue;\n\n                vector<int> nxt = curIdx;\n                reverse(nxt.begin() + l, nxt.begin() + r + 1);\n\n                auto [c2, st2] = evalOrderIdx(nxt);\n                if (c2 < curBest) {\n                    curBest = c2;\n                    curSteps = st2;\n                    curIdx = std::move(nxt);\n                }\n            }\n        }\n\n        jb.internalCost = curBest;\n        jb.internalSteps = curSteps;\n\n        jb.targetIds.clear();\n        jb.amounts.clear();\n        jb.targetIds.reserve(k);\n        jb.amounts.reserve(k);\n        for (int idx : curIdx) {\n            jb.targetIds.push_back(tids[idx]);\n            jb.amounts.push_back(amts[idx]);\n        }\n        jb.endId = jb.targetIds.back();\n    }\n\n    // -------- Outer ordering objective (exact) --------\n    int originId = cellId(0, 0, N);\n\n    vector<long long> originCost(M, 0);\n    vector<int> originSteps(M, 0);\n    for (int i = 0; i < M; i++) {\n        originSteps[i] = dist[originId][jobs[i].startId];\n        originCost[i] = 100LL * originSteps[i];\n    }\n\n    vector<vector<long long>> edgeCost(M, vector<long long>(M, 0));\n    vector<vector<int>> edgeSteps(M, vector<int>(M, 0));\n    for (int i = 0; i < M; i++) for (int j = 0; j < M; j++) if (i != j) {\n        edgeSteps[i][j] = dist[jobs[i].endId][jobs[j].startId];\n        edgeCost[i][j] = 100LL * edgeSteps[i][j];\n    }\n\n    long long internalCostSum = 0;\n    int internalStepsSum = 0;\n    int opsConstSum = 0; // +totalLoad (1 op) + -amt per target (=targetCount ops)\n    for (int i = 0; i < M; i++) {\n        internalCostSum += jobs[i].internalCost;\n        internalStepsSum += jobs[i].internalSteps;\n        opsConstSum += 1 + jobs[i].targetCount;\n    }\n\n    auto totalOuterCost = [&](const vector<int> &order)->long long{\n        long long cost = internalCostSum;\n        cost += originCost[order[0]];\n        for (int t = 0; t + 1 < (int)order.size(); t++) cost += edgeCost[order[t]][order[t+1]];\n        return cost;\n    };\n\n    auto totalOps = [&](const vector<int> &order)->int{\n        int ops = 0;\n        ops += originSteps[order[0]];\n        ops += internalStepsSum;\n        ops += opsConstSum;\n        for (int t = 0; t + 1 < (int)order.size(); t++) ops += edgeSteps[order[t]][order[t+1]];\n        return ops;\n    };\n\n    // swap delta for outer cost (exact O(1))\n    auto swapDeltaCost = [&](const vector<int> &order, int p, int q)->long long{\n        if (p > q) swap(p, q);\n        int x = order[p], y = order[q];\n\n        auto jobAt = [&](int pos)->int{\n            if (pos == p) return y;\n            if (pos == q) return x;\n            return order[pos];\n        };\n\n        long long delta = 0;\n        // origin edge changes only if p == 0\n        if (p == 0) delta += originCost[y] - originCost[x];\n\n        // affected edges indices i: p-1, p, q-1, q (edges between i and i+1)\n        int iSet[4] = {p-1, p, q-1, q};\n        bool seen[450] = {};\n        for (int t = 0; t < 4; t++) {\n            int i = iSet[t];\n            if (i < 0 || i >= M-1) continue;\n            if (seen[i]) continue;\n            seen[i] = true;\n\n            int uOld = order[i];\n            int vOld = order[i+1];\n            int uNew = jobAt(i);\n            int vNew = jobAt(i+1);\n            delta += edgeCost[uNew][vNew] - edgeCost[uOld][vOld];\n        }\n        return delta;\n    };\n\n    // Nearest-neighbor greedy initializer (better behaved than lookahead)\n    auto greedyNN = [&](int seedVariant)->vector<int>{\n        mt19937 rg(seedVariant * 1000003 + 17);\n        vector<char> used(M, 0);\n        vector<int> order;\n        order.reserve(M);\n\n        // pick first among topK by originCost\n        vector<pair<long long,int>> cand;\n        cand.reserve(M);\n        for (int i = 0; i < M; i++) cand.push_back({originCost[i], i});\n        int top = min(6, M);\n        nth_element(cand.begin(), cand.begin()+top, cand.end(),\n                    [](auto &a, auto &b){ return a.first < b.first; });\n        cand.resize(top);\n        sort(cand.begin(), cand.end(), [](auto &a, auto &b){ return a.first < b.first; });\n        int pick0 = (top == 1 ? 0 : (int)(rg() % top));\n        int cur = cand[pick0].second;\n\n        used[cur] = 1;\n        order.push_back(cur);\n\n        while ((int)order.size() < M) {\n            int last = order.back();\n            vector<pair<long long,int>> nxtCand;\n            nxtCand.reserve(M - (int)order.size());\n            for (int j = 0; j < M; j++) if (!used[j]) {\n                nxtCand.push_back({edgeCost[last][j], j});\n            }\n            int take = min(6, (int)nxtCand.size());\n            nth_element(nxtCand.begin(), nxtCand.begin()+take, nxtCand.end(),\n                        [](auto &a, auto &b){ return a.first < b.first; });\n            nxtCand.resize(take);\n            sort(nxtCand.begin(), nxtCand.end(), [](auto &a, auto &b){ return a.first < b.first; });\n            int pick = (take == 1 ? 0 : (int)(rg() % take));\n            int nxt = nxtCand[pick].second;\n\n            used[nxt] = 1;\n            order.push_back(nxt);\n        }\n        return order;\n    };\n\n    const int OP_LIMIT = 100000;\n\n    // SA over permutations with exact delta cost\n    vector<int> bestFeasibleOrder;\n    long long bestFeasibleCost = (1LL<<62);\n\n    vector<int> bestOverallOrder;\n    long long bestOverallCost = (1LL<<62);\n\n    int RESTARTS = 7;\n    int OUT_ITERS = 240000;\n\n    for (int rs = 0; rs < RESTARTS; rs++) {\n        vector<int> curOrder = greedyNN(rs+1);\n        long long curCost = totalOuterCost(curOrder);\n        if (curCost < bestOverallCost) {\n            bestOverallCost = curCost;\n            bestOverallOrder = curOrder;\n        }\n\n        int curOps = totalOps(curOrder);\n        if (curOps <= OP_LIMIT && curCost < bestFeasibleCost) {\n            bestFeasibleCost = curCost;\n            bestFeasibleOrder = curOrder;\n        }\n\n        double T = 3.2e7;\n        for (int it = 0; it < OUT_ITERS; it++) {\n            int p = rng() % M;\n            int q = rng() % M;\n            if (p == q) continue;\n            if (p > q) swap(p, q);\n\n            long long dCost = swapDeltaCost(curOrder, p, q);\n            long long newCost = curCost + dCost;\n\n            bool accept = false;\n            if (dCost <= 0) accept = true;\n            else {\n                double prob = exp((double)(curCost - newCost) / T);\n                if ((double)(rng() % 1000000) / 1000000.0 < prob) accept = true;\n            }\n\n            if (accept) {\n                swap(curOrder[p], curOrder[q]);\n                curCost = newCost;\n\n                if (curCost < bestOverallCost) {\n                    bestOverallCost = curCost;\n                    bestOverallOrder = curOrder;\n                }\n\n                // Feasibility tracking: recompute ops when it can improve bestFeasibleCost\n                if (curCost < bestFeasibleCost) {\n                    int newOps = totalOps(curOrder);\n                    if (newOps <= OP_LIMIT) {\n                        bestFeasibleCost = curCost;\n                        bestFeasibleOrder = curOrder;\n                    }\n                }\n            }\n\n            T *= 0.99997;\n        }\n    }\n\n    if (bestFeasibleOrder.empty()) {\n        // fallback: try a few more greedy and pick best feasible\n        for (int rs = 10; rs < 20; rs++) {\n            auto cand = greedyNN(rs+1);\n            int ops = totalOps(cand);\n            long long cst = totalOuterCost(cand);\n            if (ops <= OP_LIMIT && cst < bestFeasibleCost) {\n                bestFeasibleCost = cst;\n                bestFeasibleOrder = cand;\n            }\n        }\n    }\n    if (bestFeasibleOrder.empty()) bestFeasibleOrder = bestOverallOrder;\n\n    // small hill-climb with improving swaps (feasible-aware)\n    if (!bestFeasibleOrder.empty()) {\n        vector<int> cur = bestFeasibleOrder;\n        long long curCost = totalOuterCost(cur);\n        int curOps = totalOps(cur);\n\n        int iters = min(80000, M * 200);\n        for (int it = 0; it < iters; it++) {\n            int p = rng() % M;\n            int q = rng() % M;\n            if (p == q) continue;\n            if (p > q) swap(p, q);\n\n            long long dCost = swapDeltaCost(cur, p, q);\n            if (dCost >= 0) continue;\n\n            // accept improving cost; verify feasibility by recompute ops (rare + safe)\n            swap(cur[p], cur[q]);\n            int ops = totalOps(cur);\n            if (ops <= OP_LIMIT) {\n                curCost += dCost;\n                curOps = ops;\n                if (curCost < bestFeasibleCost) {\n                    bestFeasibleCost = curCost;\n                    bestFeasibleOrder = cur;\n                }\n            } else {\n                swap(cur[p], cur[q]); // revert\n            }\n        }\n    }\n\n    // -------- Output operations for bestFeasibleOrder --------\n    vector<string> opsOut;\n    opsOut.reserve(100000);\n\n    int r = 0, c = 0;\n    for (int idx : bestFeasibleOrder) {\n        const Job &jb = jobs[idx];\n\n        auto [sr, sc] = cellRC(jb.startId, N);\n        movePath(r, c, sr, sc, opsOut);\n\n        opsOut.push_back(\"+\" + to_string(jb.totalLoad));\n\n        int rr = r, cc = c;\n        for (int t = 0; t < (int)jb.targetIds.size(); t++) {\n            int tid = jb.targetIds[t];\n            int amt = jb.amounts[t];\n            auto [tr, tc] = cellRC(tid, N);\n            movePath(rr, cc, tr, tc, opsOut);\n            opsOut.push_back(\"-\" + to_string(amt));\n        }\n        r = rr; c = cc;\n\n        if ((int)opsOut.size() > OP_LIMIT) return 0;\n    }\n\n    for (auto &s : opsOut) cout << s << \"\\n\";\n    return 0;\n}","ahc035":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\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    int N, M, T;\n    cin >> N >> M >> T;\n\n    const int seed_count = 2 * N * (N - 1);\n    const int C = N * N;\n\n    vector<vector<int>> X(seed_count, vector<int>(M));\n    for (int k = 0; k < seed_count; k++) {\n        for (int l = 0; l < M; l++) cin >> X[k][l];\n    }\n\n    auto posId = [&](int i, int j) { return i * N + j; };\n\n    // Edges (right + down)\n    vector<pair<int,int>> edges;\n    edges.reserve(seed_count);\n    for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) {\n        if (i + 1 < N) edges.push_back({posId(i, j), posId(i + 1, j)});\n        if (j + 1 < N) edges.push_back({posId(i, j), posId(i, j + 1)});\n    }\n    const int E = (int)edges.size(); // 60\n\n    // 4-neighborhood positions + degrees\n    vector<vector<int>> adjPos(C);\n    vector<int> degPos(C, 0);\n    for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) {\n        int u = posId(i, j);\n        auto addNb = [&](int ni, int nj) {\n            if (0 <= ni && ni < N && 0 <= nj && nj < N)\n                adjPos[u].push_back(posId(ni, nj));\n        };\n        addNb(i - 1, j);\n        addNb(i + 1, j);\n        addNb(i, j - 1);\n        addNb(i, j + 1);\n        degPos[u] = (int)adjPos[u].size();\n    }\n\n    // incident edge bitmask per position (E<=60)\n    vector<uint64_t> incMask(C, 0);\n    for (int ei = 0; ei < E; ei++) {\n        auto [u, v] = edges[ei];\n        incMask[u] |= (1ULL << ei);\n        incMask[v] |= (1ULL << ei);\n    }\n\n    // aff[p][q] = edge indices affected by swapping positions p and q\n    vector<vector<vector<int>>> aff(C, vector<vector<int>>(C));\n    for (int p = 0; p < C; p++) for (int q = 0; q < C; q++) if (p != q) {\n        uint64_t m = incMask[p] | incMask[q];\n        vector<int> lst;\n        while (m) {\n            int b = __builtin_ctzll(m);\n            lst.push_back(b);\n            m &= (m - 1);\n        }\n        aff[p][q] = std::move(lst);\n    }\n\n    mt19937_64 rng((uint64_t)chrono::high_resolution_clock::now().time_since_epoch().count());\n\n    auto solve_one_turn = [&]() -> vector<int> {\n        // V_k\n        vector<int> V(seed_count, 0);\n        for (int k = 0; k < seed_count; k++) {\n            int s = 0;\n            for (int l = 0; l < M; l++) s += X[k][l];\n            V[k] = s;\n        }\n\n        // argmax per component\n        vector<int> argMax(M, 0);\n        for (int l = 0; l < M; l++) {\n            int bestk = 0;\n            for (int k = 1; k < seed_count; k++) if (X[k][l] > X[bestk][l]) bestk = k;\n            argMax[l] = bestk;\n        }\n\n        // Score proxy between seeds (60x60) for edges\n        const double Z = 2.0;\n        const double alphaUB = 0.8;\n\n        vector<vector<ll>> score(seed_count, vector<ll>(seed_count, 0));\n\n        for (int a = 0; a < seed_count; a++) {\n            for (int b = a; b < seed_count; b++) {\n                int ub = 0;\n                double EV = (V[a] + V[b]) / 2.0;\n                double varSum = 0.0;\n                for (int l = 0; l < M; l++) {\n                    int xa = X[a][l], xb = X[b][l];\n                    ub += max(xa, xb);\n                    double d = (double)xa - (double)xb;\n                    varSum += (d * d) / 4.0;\n                }\n                double sd = sqrt(max(0.0, varSum));\n                double tail = EV + Z * sd;\n                if (tail > (double)ub) tail = (double)ub;\n\n                ll ub2 = 1LL * ub * ub;\n                ll tail2 = (ll)(tail * tail + 0.5);\n\n                ll sc = (ll)(alphaUB * (double)ub2 + (1.0 - alphaUB) * (double)tail2 + 0.5);\n                score[a][b] = score[b][a] = sc;\n            }\n        }\n\n        // Candidate seeds for (bestA,bestB)\n        vector<int> byV(seed_count);\n        iota(byV.begin(), byV.end(), 0);\n        sort(byV.begin(), byV.end(), [&](int a, int b){ return V[a] > V[b]; });\n\n        vector<int> cand;\n        int topV = min(seed_count, 28);\n        for (int i = 0; i < topV; i++) cand.push_back(byV[i]);\n        for (int l = 0; l < M; l++) cand.push_back(argMax[l]);\n        sort(cand.begin(), cand.end());\n        cand.erase(unique(cand.begin(), cand.end()), cand.end());\n\n        // Best adjacent seed pair under proxy score\n        ll bestPairScore = -1;\n        int bestA = cand[0], bestB = cand[0];\n        for (int i = 0; i < (int)cand.size(); i++) {\n            for (int j = i + 1; j < (int)cand.size(); j++) {\n                int a = cand[i], b = cand[j];\n                ll sc = score[a][b];\n                if (sc > bestPairScore || (sc == bestPairScore && V[a] + V[b] > V[bestA] + V[bestB])) {\n                    bestPairScore = sc;\n                    bestA = a; bestB = b;\n                }\n            }\n        }\n        if (bestA == bestB) bestB = byV[1];\n\n        // -------- Improved seed subset selection (key change) --------\n        // Build a strong core S, then greedily add seeds that pair well with S_top (not just bestA/bestB).\n        vector<char> used(seed_count, 0);\n        vector<int> chosen;\n        chosen.reserve(C);\n\n        auto addSeed = [&](int k) {\n            if (!used[k]) {\n                used[k] = 1;\n                chosen.push_back(k);\n            }\n        };\n\n        addSeed(bestA);\n        addSeed(bestB);\n        for (int l = 0; l < M; l++) addSeed(argMax[l]);\n\n        // function to compute quality of candidate k given chosen\n        auto quality = [&](int k, const vector<int>& S) -> ll {\n            // take top subset by V among S\n            static int Sidx[60];\n            (void)Sidx;\n            vector<int> tmp = S;\n            sort(tmp.begin(), tmp.end(), [&](int a, int b){ return V[a] > V[b]; });\n\n            int take = min<int>(10, tmp.size());\n            ll sumPair = 0;\n            for (int i = 0; i < take; i++) sumPair += score[k][tmp[i]];\n            // small bias toward high total V\n            ll biasV = (ll)V[k] * 500; \n            return sumPair + biasV;\n        };\n\n        while ((int)chosen.size() < C) {\n            // current core S for quality evaluation\n            const vector<int>& S = chosen;\n\n            vector<pair<ll,int>> qlist;\n            qlist.reserve(seed_count - chosen.size());\n            for (int k = 0; k < seed_count; k++) if (!used[k]) {\n                ll q = quality(k, S);\n                qlist.push_back({q, k});\n            }\n\n            // pick among top few to reduce variance\n            int pickTop = min<int>(5, (int)qlist.size());\n            nth_element(qlist.begin(), qlist.begin() + pickTop, qlist.end(),\n                        [&](auto &a, auto &b){ return a.first > b.first; });\n            qlist.resize(pickTop);\n            sort(qlist.begin(), qlist.end(), [&](auto &a, auto &b){ return a.first > b.first; });\n\n            int idx = (pickTop == 1 ? 0 : (int)(rng() % pickTop));\n            addSeed(qlist[idx].second);\n        }\n\n        // Calculate objective for a placement\n        auto calcObj = [&](const vector<int>& Apos) -> ll {\n            ll obj = 0;\n            for (int ei = 0; ei < E; ei++) {\n                auto [u, v] = edges[ei];\n                obj += score[Apos[u]][Apos[v]];\n            }\n            return obj;\n        };\n\n        // placement candidates for (bestA,bestB): top-degree-sum edges (moderate diversity)\n        vector<pair<int,int>> edgeList = edges;\n        sort(edgeList.begin(), edgeList.end(), [&](auto &p, auto &q){\n            int sp = degPos[p.first] + degPos[p.second];\n            int sq = degPos[q.first] + degPos[q.second];\n            return sp > sq;\n        });\n\n        const int topPairEdges = 3; // keep moderate\n        vector<pair<int,int>> placements;\n        for (int i = 0; i < min(topPairEdges, (int)edgeList.size()); i++) {\n            auto [u,v] = edgeList[i];\n            placements.push_back({u,v});\n            if (u != v) placements.push_back({v,u});\n        }\n        sort(placements.begin(), placements.end());\n        placements.erase(unique(placements.begin(), placements.end()), placements.end());\n        if (placements.empty()) placements.push_back({0,1});\n\n        // SA + greedy fill\n        int restarts = 4;\n        int iters = 12000;\n\n        vector<int> globalBestApos(C, 0);\n        ll globalBestObj = LLONG_MIN;\n\n        for (auto [pA0, pB0] : placements) {\n            for (int r = 0; r < restarts; r++) {\n                uint64_t seedR = splitmix64(rng() + (uint64_t)pA0 * 1315423911ULL\n                                                + (uint64_t)pB0 * 2654435761ULL\n                                                + (uint64_t)r * 1013904223ULL);\n                mt19937_64 rg(seedR);\n\n                vector<int> Apos(C, -1);\n                vector<int> remaining = chosen;\n\n                auto takeSeed = [&](int k) {\n                    auto it = find(remaining.begin(), remaining.end(), k);\n                    if (it != remaining.end()) remaining.erase(it);\n                };\n\n                Apos[pA0] = bestA; takeSeed(bestA);\n                if (pB0 == pA0) {\n                    // guard: choose any other cell (should not happen)\n                    for (int pos = 0; pos < C; pos++) if (pos != pA0) { pB0 = pos; break; }\n                }\n                Apos[pB0] = bestB; takeSeed(bestB);\n\n                // filled neighbor counts\n                vector<int> filledCnt(C, 0);\n                vector<char> isFilled(C, 0), isUnfilled(C, 1);\n                int filled = 0;\n                for (int p = 0; p < C; p++) if (Apos[p] != -1) {\n                    isFilled[p] = 1;\n                    isUnfilled[p] = 0;\n                    filled++;\n                }\n                for (int p = 0; p < C; p++) if (isFilled[p]) {\n                    for (int nb : adjPos[p]) filledCnt[nb]++;\n                }\n\n                auto pickNextPos = [&]() -> int {\n                    int bestCnt = -1, bestDeg = -1;\n                    vector<int> ties;\n                    for (int p = 0; p < C; p++) if (isUnfilled[p]) {\n                        int cnt = filledCnt[p];\n                        int dg = degPos[p];\n                        if (cnt > bestCnt || (cnt == bestCnt && dg > bestDeg)) {\n                            bestCnt = cnt;\n                            bestDeg = dg;\n                            ties.clear();\n                            ties.push_back(p);\n                        } else if (cnt == bestCnt && dg == bestDeg) {\n                            ties.push_back(p);\n                        }\n                    }\n                    if (!ties.empty()) return ties[(size_t)(rg() % ties.size())];\n                    for (int p = 0; p < C; p++) if (isUnfilled[p]) return p;\n                    return 0;\n                };\n\n                // Fill remaining cells\n                vector<pair<ll,int>> candGain;\n                candGain.reserve(remaining.size());\n\n                while (filled < C) {\n                    int p = pickNextPos();\n                    candGain.clear();\n\n                    for (int s : remaining) {\n                        ll gsum = 0;\n                        for (int nb : adjPos[p]) {\n                            if (Apos[nb] != -1) gsum += score[s][Apos[nb]];\n                        }\n                        // slight V bias to reduce unlucky picks\n                        gsum += (ll)V[s] * 5;\n                        candGain.push_back({gsum, s});\n                    }\n\n                    int topK = min<int>(7, (int)candGain.size());\n                    nth_element(candGain.begin(), candGain.begin() + topK, candGain.end(),\n                                [&](auto &a, auto &b){ return a.first > b.first; });\n                    candGain.resize(topK);\n                    sort(candGain.begin(), candGain.end(),\n                         [&](auto &a, auto &b){ return a.first > b.first; });\n\n                    int pickIdx = (topK == 1 ? 0 : (int)(rg() % topK));\n                    int seedSel = candGain[pickIdx].second;\n\n                    Apos[p] = seedSel;\n                    takeSeed(seedSel);\n\n                    isUnfilled[p] = 0;\n                    isFilled[p] = 1;\n                    filled++;\n                    for (int nb : adjPos[p]) filledCnt[nb]++;\n                }\n\n                ll curObj = calcObj(Apos);\n                if (curObj > globalBestObj) {\n                    globalBestObj = curObj;\n                    globalBestApos = Apos;\n                }\n\n                double avgEdge = (double)curObj / (double)E;\n                double temp0 = max(1.0, avgEdge * 0.9);\n\n                // SA swaps\n                for (int it = 0; it < iters; it++) {\n                    int p = (int)(rg() % C);\n                    int q = (int)(rg() % C);\n                    if (p == q) continue;\n                    int sp = Apos[p], sq = Apos[q];\n                    if (sp == sq) continue;\n\n                    ll delta = 0;\n                    for (int ei : aff[p][q]) {\n                        auto [u, v] = edges[ei];\n\n                        int su_old = (u == p ? sp : (u == q ? sq : Apos[u]));\n                        int sv_old = (v == p ? sp : (v == q ? sq : Apos[v]));\n                        ll oldTerm = score[su_old][sv_old];\n\n                        int su_new = (u == p ? sq : (u == q ? sp : Apos[u]));\n                        int sv_new = (v == p ? sq : (v == q ? sp : Apos[v]));\n                        ll newTerm = score[su_new][sv_new];\n\n                        delta += newTerm - oldTerm;\n                    }\n\n                    if (delta >= 0) {\n                        swap(Apos[p], Apos[q]);\n                        curObj += delta;\n                    } else {\n                        double frac = (double)it / (double)iters;\n                        double temp = temp0 * (1.0 - frac) * (1.0 - frac) + 1e-6;\n                        double pr = exp((double)delta / temp);\n                        if (uniform_real_distribution<double>(0.0, 1.0)(rg) < pr) {\n                            swap(Apos[p], Apos[q]);\n                            curObj += delta;\n                        }\n                    }\n\n                    if (curObj > globalBestObj) {\n                        globalBestObj = curObj;\n                        globalBestApos = Apos;\n                    }\n                }\n            }\n        }\n\n        return globalBestApos;\n    };\n\n    for (int tt = 0; tt < T; tt++) {\n        vector<int> A = solve_one_turn();\n\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                if (j) cout << ' ';\n                cout << A[posId(i,j)];\n            }\n            cout << '\\n';\n        }\n        cout.flush();\n\n        for (int k = 0; k < seed_count; k++) {\n            for (int l = 0; l < M; l++) cin >> X[k][l];\n        }\n    }\n    return 0;\n}","ahc038":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Pt { int x, y; };\n\nstatic inline char mvChar(uint8_t mv) {\n    static const char MCH[5] = {'.','U','D','L','R'};\n    return MCH[mv];\n}\nstatic inline char rotChar(uint8_t rot) {\n    // rot: 0='.', 1='L'(CCW), 2='R'(CW)\n    static const char RCH[3] = {'.','L','R'};\n    return RCH[rot];\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, V;\n    cin >> N >> M >> V;\n    vector<string> s(N), t(N);\n    for (int i = 0; i < N; i++) cin >> s[i];\n    for (int i = 0; i < N; i++) cin >> t[i];\n\n    auto inRange = [&](int x, int y) {\n        return 0 <= x && x < N && 0 <= y && y < N;\n    };\n    auto cellId = [&](int x, int y) { return x * N + y; };\n\n    vector<int> A_ids; // initial=1 target=0 => must pick\n    vector<int> B_ids; // initial=0 target=1 => must place\n    A_ids.reserve(M); B_ids.reserve(M);\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            bool si = (s[i][j] == '1');\n            bool ti = (t[i][j] == '1');\n            if (si && !ti) A_ids.push_back(cellId(i,j));\n            if (!si && ti) B_ids.push_back(cellId(i,j));\n        }\n    }\n    if (A_ids.empty()) {\n        cout << 2 << \"\\n\" << 0 << \" \" << 1 << \"\\n\" << 0 << \" \" << 0 << \"\\n\";\n        cout << \"...P\\n\";\n        return 0;\n    }\n\n    // ---------------- State graph (independent of edge length L) ----------------\n    // dir=0:R, 1:D, 2:L, 3:U\n    array<int,4> dx{0,1,0,-1};\n    array<int,4> dy{1,0,-1,0};\n\n    int S = N * N * 4;\n    auto encode = [&](int rx, int ry, int dir) {\n        return ((rx * N + ry) * 4 + dir);\n    };\n\n    vector<int> rootX(S), rootY(S), dirOf(S);\n    for (int rx = 0; rx < N; rx++) for (int ry = 0; ry < N; ry++) for (int d = 0; d < 4; d++) {\n        int id = encode(rx, ry, d);\n        rootX[id] = rx; rootY[id] = ry; dirOf[id] = d;\n    }\n\n    // one-turn transitions: op1 (move root) then op2 (rotate subtree at vertex 1)\n    array<pair<int,int>,5> mvDelta{{\n        {0,0},{-1,0},{+1,0},{0,-1},{0,+1} // '.',U,D,L,R\n    }};\n    // rot: 0='.', 1='L'(CCW), 2='R'(CW)\n    auto applyRotDir = [&](int d, uint8_t rot) -> int {\n        if (rot == 1) return (d + 3) & 3; // CCW\n        if (rot == 2) return (d + 1) & 3; // CW\n        return d;\n    };\n\n    struct Edge { int to; uint8_t mv, rot; };\n    vector<vector<Edge>> adj(S);\n    for (int st = 0; st < S; st++) {\n        int rx = rootX[st], ry = rootY[st], d = dirOf[st];\n        adj[st].clear();\n        for (uint8_t mv = 0; mv < 5; mv++) {\n            int nrx = rx + mvDelta[mv].first;\n            int nry = ry + mvDelta[mv].second;\n            if (!inRange(nrx, nry)) continue; // operation 1 constraint\n            for (uint8_t rot = 0; rot < 3; rot++) {\n                int nd = applyRotDir(d, rot);\n                adj[st].push_back({encode(nrx, nry, nd), mv, rot});\n            }\n        }\n    }\n\n    // all-pairs shortest distances and predecessors for reconstruction\n    const uint16_t INF16 = 65535;\n    vector<uint16_t> distAll((size_t)S * S, INF16);\n    vector<uint16_t> prevStateAll((size_t)S * S, INF16);\n    vector<uint8_t> prevMvAll((size_t)S * S, 0);\n    vector<uint8_t> prevRotAll((size_t)S * S, 0);\n\n    vector<int> distRow(S);\n    vector<int> prevRow(S);\n    vector<uint8_t> prevMvRow(S), prevRotRow(S);\n    queue<int> q;\n\n    for (int st = 0; st < S; st++) {\n        fill(distRow.begin(), distRow.end(), -1);\n        while (!q.empty()) q.pop();\n        distRow[st] = 0;\n        prevRow[st] = st;\n        prevMvRow[st] = 0;\n        prevRotRow[st] = 0;\n        q.push(st);\n\n        while (!q.empty()) {\n            int v = q.front(); q.pop();\n            for (auto &e : adj[v]) {\n                int u = e.to;\n                if (distRow[u] != -1) continue;\n                distRow[u] = distRow[v] + 1;\n                prevRow[u] = v;\n                prevMvRow[u] = e.mv;\n                prevRotRow[u] = e.rot;\n                q.push(u);\n            }\n        }\n\n        size_t base = (size_t)st * S;\n        for (int goal = 0; goal < S; goal++) {\n            if (distRow[goal] < 0) continue;\n            distAll[base + goal] = (uint16_t)distRow[goal];\n            prevStateAll[base + goal] = (uint16_t)prevRow[goal];\n            prevMvAll[base + goal] = prevMvRow[goal];\n            prevRotAll[base + goal] = prevRotRow[goal];\n        }\n    }\n\n    auto segTurns = [&](uint16_t dEdge) -> uint32_t {\n        // segment ends with P at goal state:\n        // if already at goal: 1 turn (\"...P\")\n        // else: dEdge turns, with P on the last one\n        if (dEdge == INF16) return UINT32_MAX;\n        return (dEdge == 0 ? 1u : (uint32_t)dEdge);\n    };\n\n    // ---------------- Edge length candidates ----------------\n    vector<int> candLs;\n    auto addL = [&](int L) {\n        if (1 <= L && L <= N-1) candLs.push_back(L);\n    };\n    int a = max(1, (N-1)/4);\n    int b = max(1, (N-1)/3);\n    int c = max(1, (N-1)/2);\n    int d = max(1, 2*(N-1)/3);\n    int e = max(1, 3*(N-1)/4);\n\n    addL(1);\n    addL(a); addL(a+1);\n    addL(b); addL(b+1);\n    addL(c); addL(c-1); addL(c+1);\n    addL(d); addL(d-1);\n    addL(e);\n    addL(N-2);\n    addL(N-1);\n\n    sort(candLs.begin(), candLs.end());\n    candLs.erase(unique(candLs.begin(), candLs.end()), candLs.end());\n    if ((int)candLs.size() > 9) candLs.resize(9);\n\n    int NN = N * N; // cell ids\n\n    struct PrecompL {\n        int L;\n        vector<array<int,4>> statesForCell; // [cell][k] => state whose fingertip==cell\n        vector<uint8_t> cntForCell;\n        vector<uint16_t> pickCostMin;   // [curState*NN + srcCell] with P at end\n        vector<uint16_t> pickBestP;     // argmin pState for pickCostMin\n        vector<uint16_t> bestRelCost;   // [pState*NN + dstCell] with P at end\n        vector<uint16_t> bestRelChoice; // argmin qState for bestRelCost\n    };\n\n    auto buildPrecomp = [&](int L) -> optional<PrecompL> {\n        PrecompL pc;\n        pc.L = L;\n        pc.statesForCell.assign(NN, array<int,4>{-1,-1,-1,-1});\n        pc.cntForCell.assign(NN, 0);\n\n        // fingertip = root + (dx[dir]*L, dy[dir]*L)\n        // => root = cell - (dx[dir]*L, dy[dir]*L)\n        for (int cx = 0; cx < N; cx++) for (int cy = 0; cy < N; cy++) {\n            int cid = cellId(cx,cy);\n            uint8_t cnt = 0;\n            for (int dir = 0; dir < 4; dir++) {\n                int rx = cx - dx[dir] * L;\n                int ry = cy - dy[dir] * L;\n                if (!inRange(rx, ry)) continue;\n                pc.statesForCell[cid][cnt++] = encode(rx, ry, dir);\n                if (cnt == 4) break;\n            }\n            pc.cntForCell[cid] = cnt;\n        }\n\n        // feasibility quick check\n        for (int cid : A_ids) if (pc.cntForCell[cid] == 0) return nullopt;\n        for (int cid : B_ids) if (pc.cntForCell[cid] == 0) return nullopt;\n\n        pc.pickCostMin.assign((size_t)S * NN, INF16);\n        pc.pickBestP.assign((size_t)S * NN, INF16);\n        pc.bestRelCost.assign((size_t)S * NN, INF16);\n        pc.bestRelChoice.assign((size_t)S * NN, INF16);\n\n        // pickCostMin + pickBestP\n        for (int cur = 0; cur < S; cur++) {\n            size_t baseDist = (size_t)cur * S;\n            size_t basePick = (size_t)cur * NN;\n            for (int srcCell = 0; srcCell < NN; srcCell++) {\n                uint8_t cntP = pc.cntForCell[srcCell];\n                if (!cntP) continue;\n                uint32_t bestCost = UINT32_MAX;\n                int bestP = -1;\n                for (int k = 0; k < cntP; k++) {\n                    int pState = pc.statesForCell[srcCell][k];\n                    uint16_t dEdge = distAll[baseDist + pState];\n                    uint32_t cost = segTurns(dEdge);\n                    if (cost < bestCost) { bestCost = cost; bestP = pState; }\n                }\n                if (bestP != -1 && bestCost != UINT32_MAX) {\n                    pc.pickCostMin[basePick + srcCell] = (uint16_t)bestCost;\n                    pc.pickBestP[basePick + srcCell] = (uint16_t)bestP;\n                }\n            }\n        }\n\n        // bestRelCost + choice\n        for (int pState = 0; pState < S; pState++) {\n            size_t baseDist = (size_t)pState * S;\n            size_t baseRel = (size_t)pState * NN;\n            for (int dstCell = 0; dstCell < NN; dstCell++) {\n                uint8_t cntQ = pc.cntForCell[dstCell];\n                if (!cntQ) continue;\n\n                uint32_t bestCost = UINT32_MAX;\n                int bestQ = -1;\n                for (int k = 0; k < cntQ; k++) {\n                    int qState = pc.statesForCell[dstCell][k];\n                    uint16_t dEdge = distAll[baseDist + qState];\n                    uint32_t cost = segTurns(dEdge);\n                    if (cost < bestCost) { bestCost = cost; bestQ = qState; }\n                }\n                if (bestQ != -1 && bestCost != UINT32_MAX) {\n                    pc.bestRelCost[baseRel + dstCell] = (uint16_t)bestCost;\n                    pc.bestRelChoice[baseRel + dstCell] = (uint16_t)bestQ;\n                }\n            }\n        }\n\n        return pc;\n    };\n\n    struct Transfer {\n        int srcCell, dstCell;\n        int pState, qState;\n        uint32_t pairCost;\n    };\n    struct RunRes {\n        uint32_t totalTurns = UINT32_MAX;\n        int L = 1;\n        int rx0 = 0, ry0 = 0;\n        vector<Transfer> transfers;\n    };\n\n    auto chooseInitialRoots = [&](const PrecompL &pc) -> vector<pair<int,int>> {\n        // initial dir=0 => fingertip is (rx, ry+L)\n        // align fingertip to some top sources: root=(sx, sy-L)\n        vector<Pt> sources;\n        sources.reserve(A_ids.size());\n        long long sxSum=0, sySum=0;\n        for (int cid : A_ids) {\n            int x = cid / N, y = cid % N;\n            sources.push_back({x,y});\n            sxSum += x; sySum += y;\n        }\n        int cx = (int)(sxSum / (long long)A_ids.size());\n        int cy = (int)(sySum / (long long)A_ids.size());\n\n        sort(sources.begin(), sources.end(), [&](const Pt& a1, const Pt& b1){\n            int da = abs(a1.x - cx) + abs(a1.y - cy);\n            int db = abs(b1.x - cx) + abs(b1.y - cy);\n            return da < db;\n        });\n\n        vector<pair<int,int>> roots;\n        roots.push_back({0,0});\n        roots.push_back({0, N-1});\n        roots.push_back({N-1, 0});\n        roots.push_back({N-1, N-1});\n\n        int KW = min(6, (int)sources.size());\n        for (int i = 0; i < KW; i++) {\n            int sx = sources[i].x, sy = sources[i].y;\n            int rx = sx;\n            int ry = sy - pc.L;\n            if (inRange(rx, ry)) roots.push_back({rx,ry});\n        }\n        sort(roots.begin(), roots.end());\n        roots.erase(unique(roots.begin(), roots.end()), roots.end());\n        if ((int)roots.size() > 6) roots.resize(6);\n        return roots;\n    };\n\n    auto simulate = [&](const PrecompL &pc, int rx0, int ry0) -> optional<RunRes> {\n        vector<int> Avec = A_ids;\n        vector<int> Bvec = B_ids;\n\n        int curState = encode(rx0, ry0, 0); // dir=0\n        uint32_t total = 0;\n        const uint32_t BUDGET = 100000;\n\n        vector<Transfer> transfers;\n        transfers.reserve(A_ids.size());\n\n        const int Ksrc = 40;\n        const int TopPairs = 10;\n        const int Klook = 8;\n\n        while (!Avec.empty()) {\n            if (total > BUDGET) return nullopt;\n\n            auto pickCostOf = [&](int srcCell, int state) -> uint16_t {\n                return pc.pickCostMin[(size_t)state * NN + srcCell];\n            };\n\n            // build src candidates: Ksrc smallest pickCostMin from curState\n            vector<pair<uint16_t,int>> srcCand; // (cost, index in Avec)\n            srcCand.reserve(Avec.size());\n            for (int i = 0; i < (int)Avec.size(); i++) {\n                int srcCell = Avec[i];\n                uint16_t c = pickCostOf(srcCell, curState);\n                if (c != INF16) srcCand.push_back({c, i});\n            }\n            if (srcCand.empty()) return nullopt;\n            sort(srcCand.begin(), srcCand.end());\n            if ((int)srcCand.size() > Ksrc) srcCand.resize(Ksrc);\n\n            auto evaluatePairs = [&](const vector<pair<uint16_t,int>> &srcCandLocal) -> optional<Transfer> {\n                vector<Transfer> top; top.reserve(TopPairs);\n\n                auto considerTop = [&](Transfer tr) {\n                    if ((int)top.size() < TopPairs) {\n                        top.push_back(tr);\n                        sort(top.begin(), top.end(), [](const Transfer& a, const Transfer& b){\n                            return a.pairCost < b.pairCost;\n                        });\n                    } else if (tr.pairCost < top.back().pairCost) {\n                        top.back() = tr;\n                        sort(top.begin(), top.end(), [](const Transfer& a, const Transfer& b){\n                            return a.pairCost < b.pairCost;\n                        });\n                    }\n                };\n\n                size_t baseDistCur = (size_t)curState * S;\n\n                for (auto [_, ai] : srcCandLocal) {\n                    int srcCell = Avec[ai];\n                    uint8_t cntP = pc.cntForCell[srcCell];\n                    if (!cntP) continue;\n\n                    for (int bj = 0; bj < (int)Bvec.size(); bj++) {\n                        int dstCell = Bvec[bj];\n\n                        uint32_t bestPair = UINT32_MAX;\n                        int bestP = -1, bestQ = -1;\n\n                        for (int k = 0; k < cntP; k++) {\n                            int pState = pc.statesForCell[srcCell][k];\n                            uint16_t dPickEdge = distAll[baseDistCur + pState];\n                            uint32_t pickTurns = segTurns(dPickEdge);\n                            if (pickTurns == UINT32_MAX) continue;\n\n                            uint16_t rel = pc.bestRelCost[(size_t)pState * NN + dstCell];\n                            if (rel == INF16) continue;\n\n                            uint32_t totalPair = pickTurns + (uint32_t)rel;\n                            if (totalPair < bestPair) {\n                                bestPair = totalPair;\n                                bestP = pState;\n                                bestQ = (int)pc.bestRelChoice[(size_t)pState * NN + dstCell];\n                            }\n                        }\n\n                        if (bestP == -1) continue;\n                        if (total + bestPair > BUDGET) continue;\n\n                        considerTop(Transfer{srcCell, dstCell, bestP, bestQ, bestPair});\n                    }\n                }\n\n                if (top.empty()) return nullopt;\n\n                // Lookahead scoring among top candidates\n                Transfer best = top[0];\n                uint32_t bestScore = UINT32_MAX;\n\n                for (auto &cand : top) {\n                    int qState = cand.qState;\n\n                    // choose next source candidates with smallest pickup cost from qState\n                    vector<pair<uint16_t,int>> nextSrc; // (pickupCost, cellValue)\n                    nextSrc.reserve(Avec.size());\n                    for (int srcCell : Avec) {\n                        if (srcCell == cand.srcCell) continue;\n                        uint16_t c = pc.pickCostMin[(size_t)qState * NN + srcCell];\n                        if (c == INF16) continue;\n                        nextSrc.push_back({c, srcCell});\n                    }\n                    if (nextSrc.empty()) {\n                        uint32_t score = cand.pairCost;\n                        if (score < bestScore) { bestScore = score; best = cand; }\n                        continue;\n                    }\n                    sort(nextSrc.begin(), nextSrc.end());\n                    if ((int)nextSrc.size() > Klook) nextSrc.resize(Klook);\n\n                    uint32_t nextLower = UINT32_MAX;\n\n                    // compute for each next source:\n                    //   pickCost(qState->nextSrc) + min_{dst in remaining B} bestRelCost(bestP, dst)\n                    for (auto [pickCost, nextSrcCell] : nextSrc) {\n                        int bestP = (int)pc.pickBestP[(size_t)qState * NN + nextSrcCell];\n                        if (bestP < 0 || bestP >= S) continue;\n\n                        uint32_t relMin = UINT32_MAX;\n                        for (int dstCell : Bvec) {\n                            uint16_t rel = pc.bestRelCost[(size_t)bestP * NN + dstCell];\n                            if (rel == INF16) continue;\n                            relMin = min(relMin, (uint32_t)rel);\n                        }\n                        if (relMin == UINT32_MAX) continue;\n                        nextLower = min(nextLower, (uint32_t)pickCost + relMin);\n                    }\n\n                    if (nextLower == UINT32_MAX) nextLower = 0;\n                    uint32_t score = cand.pairCost + nextLower;\n\n                    if (score < bestScore || (score == bestScore && cand.pairCost < best.pairCost)) {\n                        bestScore = score;\n                        best = cand;\n                    }\n                }\n                return best;\n            };\n\n            // first try with restricted src candidates\n            optional<Transfer> chosen = evaluatePairs(srcCand);\n            if (!chosen) {\n                // fallback: use all sources\n                vector<pair<uint16_t,int>> allCand;\n                allCand.reserve(Avec.size());\n                for (int i = 0; i < (int)Avec.size(); i++) {\n                    int srcCell = Avec[i];\n                    uint16_t c = pickCostOf(srcCell, curState);\n                    if (c != INF16) allCand.push_back({c, i});\n                }\n                if (allCand.empty()) return nullopt;\n                sort(allCand.begin(), allCand.end());\n                chosen = evaluatePairs(allCand);\n            }\n            if (!chosen) return nullopt;\n\n            Transfer tr = *chosen;\n\n            total += tr.pairCost;\n            transfers.push_back(tr);\n            curState = tr.qState;\n\n            // remove srcCell and dstCell from lists (each cell appears at most once in A/B)\n            auto eraseCell = [&](vector<int> &vec, int val) {\n                for (int i = 0; i < (int)vec.size(); i++) {\n                    if (vec[i] == val) { vec[i] = vec.back(); vec.pop_back(); return true; }\n                }\n                return false;\n            };\n            if (!eraseCell(Avec, tr.srcCell)) return nullopt;\n            if (!eraseCell(Bvec, tr.dstCell)) return nullopt;\n        }\n\n        if (!Bvec.empty()) return nullopt;\n        RunRes rr;\n        rr.totalTurns = total;\n        rr.L = pc.L;\n        rr.rx0 = rx0;\n        rr.ry0 = ry0;\n        rr.transfers = std::move(transfers);\n        return rr;\n    };\n\n    // ---------------- Search best L and root ----------------\n    RunRes best;\n    for (int L : candLs) {\n        auto pcOpt = buildPrecomp(L);\n        if (!pcOpt) continue;\n        const auto &pc = *pcOpt;\n\n        auto roots = chooseInitialRoots(pc);\n        for (auto [rx0, ry0] : roots) {\n            auto rrOpt = simulate(pc, rx0, ry0);\n            if (!rrOpt) continue;\n            if (rrOpt->totalTurns < best.totalTurns) best = std::move(*rrOpt);\n        }\n    }\n\n    if (best.totalTurns == UINT32_MAX) {\n        // fallback legal\n        cout << 2 << \"\\n\" << 0 << \" \" << 1 << \"\\n\" << 0 << \" \" << 0 << \"\\n\" << \"...P\\n\";\n        return 0;\n    }\n\n    // ---------------- Output arm + operations ----------------\n    // V' = 2: root=0, fingertip=1, edge length = best.L\n    cout << 2 << \"\\n\";\n    cout << 0 << \" \" << best.L << \"\\n\";\n    cout << best.rx0 << \" \" << best.ry0 << \"\\n\";\n\n    vector<string> ops;\n    ops.reserve(best.transfers.size() * 25);\n\n    auto appendSegmentP = [&](int st, int goal) {\n        if ((int)ops.size() >= 100000) return;\n\n        uint16_t dEdge = distAll[(size_t)st * S + goal];\n        if (dEdge == INF16) return;\n\n        if (dEdge == 0) {\n            ops.push_back(\"...P\");\n            return;\n        }\n\n        int steps = (int)dEdge;\n        vector<pair<uint8_t,uint8_t>> edges;\n        edges.reserve(steps);\n\n        // reconstruct edges st -> goal\n        int cur = goal;\n        for (int i = 0; i < steps; i++) {\n            uint16_t pre = prevStateAll[(size_t)st * S + cur];\n            uint8_t mv = prevMvAll[(size_t)st * S + cur];\n            uint8_t rot = prevRotAll[(size_t)st * S + cur];\n            if (pre == INF16) break;\n            edges.push_back({mv, rot});\n            cur = (int)pre;\n        }\n        reverse(edges.begin(), edges.end());\n\n        for (int i = 0; i < (int)edges.size(); i++) {\n            bool last = (i == (int)edges.size() - 1);\n            string str;\n            str.push_back(mvChar(edges[i].first));\n            str.push_back(rotChar(edges[i].second));\n            str.push_back('.');\n            str.push_back(last ? 'P' : '.');\n            ops.push_back(std::move(str));\n        }\n    };\n\n    int curStateOut = encode(best.rx0, best.ry0, 0);\n    for (auto &tr : best.transfers) {\n        appendSegmentP(curStateOut, tr.pState); // pickup at src cell\n        curStateOut = tr.pState;\n        appendSegmentP(curStateOut, tr.qState); // release at dst cell\n        curStateOut = tr.qState;\n    }\n\n    if ((int)ops.size() > 100000) ops.resize(100000);\n    for (auto &line : ops) cout << line << \"\\n\";\n    return 0;\n}","ahc039":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int MAXC = 100000;\n\nstruct Pt {\n    int x, y;\n    int w; // +1 mackerel, -1 sardine\n};\n\n// Fenwick-of-vectors 2D range sum over inclusive integer rectangles [xL..xR] x [yB..yT]\nstruct RangeSum2D {\n    int nx = 0;\n    vector<int> xvals;\n    vector<vector<int>> yList;\n    vector<vector<long long>> pref;\n\n    RangeSum2D() = default;\n    explicit RangeSum2D(const vector<Pt>& pts) { build(pts); }\n\n    void build(const vector<Pt>& pts) {\n        xvals.clear();\n        xvals.reserve(pts.size());\n        for (auto &p : pts) xvals.push_back(p.x);\n        sort(xvals.begin(), xvals.end());\n        xvals.erase(unique(xvals.begin(), xvals.end()), xvals.end());\n        nx = (int)xvals.size();\n\n        vector<vector<pair<int,int>>> tmp(nx + 1); // BIT nodes: (y,w)\n        for (auto &p : pts) {\n            int xi = (int)(lower_bound(xvals.begin(), xvals.end(), p.x) - xvals.begin()) + 1;\n            for (int i = xi; i <= nx; i += i & -i) tmp[i].push_back({p.y, p.w});\n        }\n\n        yList.assign(nx + 1, {});\n        pref.assign(nx + 1, {});\n        for (int i = 1; i <= nx; i++) {\n            auto &v = tmp[i];\n            sort(v.begin(), v.end(), [](auto &a, auto &b){ return a.first < b.first; });\n            yList[i].resize(v.size());\n            pref[i].resize(v.size());\n            long long run = 0;\n            for (size_t j = 0; j < v.size(); j++) {\n                yList[i][j] = v[j].first;\n                run += (long long)v[j].second;\n                pref[i][j] = run;\n            }\n        }\n    }\n\n    long long prefSum(int X, int Y) const {\n        if (X < 0 || Y < 0) return 0;\n        int xi = (int)(upper_bound(xvals.begin(), xvals.end(), X) - xvals.begin()); // 0..nx\n        long long res = 0;\n        for (int i = xi; i > 0; i -= i & -i) {\n            if (yList[i].empty()) continue;\n            int k = (int)(upper_bound(yList[i].begin(), yList[i].end(), Y) - yList[i].begin());\n            if (k > 0) res += pref[i][k - 1];\n        }\n        return res;\n    }\n\n    long long sumRect(int xL, int xR, int yB, int yT) const {\n        if (xL > xR || yB > yT) return 0;\n        xL = max(xL, 0); xR = min(xR, MAXC);\n        yB = max(yB, 0); yT = min(yT, MAXC);\n        if (xL > xR || yB > yT) return 0;\n\n        long long A = prefSum(xR, yT);\n        long long B = prefSum(xL - 1, yT);\n        long long C = prefSum(xR, yB - 1);\n        long long D = prefSum(xL - 1, yB - 1);\n        return A - B - C + D;\n    }\n};\n\nstatic inline void normalizeRect(int &xL, int &xR, int &yB, int &yT) {\n    xL = max(0, min(MAXC, xL));\n    xR = max(0, min(MAXC, xR));\n    yB = max(0, min(MAXC, yB));\n    yT = max(0, min(MAXC, yT));\n    if (xL > xR) swap(xL, xR);\n    if (yB > yT) swap(yB, yT);\n\n    if (xL == xR) {\n        if (xR < MAXC) xR = xL + 1;\n        else xL = xR - 1;\n    }\n    if (yB == yT) {\n        if (yT < MAXC) yT = yB + 1;\n        else yB = yT - 1;\n    }\n\n    if (xL > xR) swap(xL, xR);\n    if (yB > yT) swap(yB, yT);\n}\n\nstatic inline vector<int> buildAllCandFromPoints(const vector<int> &base) {\n    vector<int> all;\n    all.reserve(base.size() * 3 + 2);\n    all.push_back(0);\n    all.push_back(MAXC);\n    for (int v : base) {\n        if (0 <= v && v <= MAXC) all.push_back(v);\n        if (0 <= v - 1 && v - 1 <= MAXC) all.push_back(v - 1);\n        if (0 <= v + 1 && v + 1 <= MAXC) all.push_back(v + 1);\n    }\n    sort(all.begin(), all.end());\n    all.erase(unique(all.begin(), all.end()), all.end());\n    return all;\n}\n\n// strictInside=true: exclude endpoints; strictInside=false: include endpoints\nstatic inline vector<int> sampleInRange(const vector<int> &sortedUniq, int L, int R,\n                                          int cap, bool strictInside) {\n    if (L > R) swap(L, R);\n    int lo = strictInside ? L + 1 : L;\n    int hi = strictInside ? R - 1 : R;\n    lo = max(lo, 0);\n    hi = min(hi, MAXC);\n    if (lo > hi) return {};\n\n    auto itL = lower_bound(sortedUniq.begin(), sortedUniq.end(), lo);\n    auto itR = upper_bound(sortedUniq.begin(), sortedUniq.end(), hi);\n    vector<int> cand(itL, itR);\n    if ((int)cand.size() <= cap) return cand;\n\n    vector<int> out;\n    out.reserve(cap);\n    int n = (int)cand.size();\n    for (int i = 0; i < cap; i++) out.push_back(cand[(long long)i * n / cap]);\n    sort(out.begin(), out.end());\n    out.erase(unique(out.begin(), out.end()), out.end());\n    return out;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    cin >> N;\n    vector<Pt> pts;\n    pts.reserve(2 * N);\n\n    for (int i = 0; i < N; i++) {\n        int x, y; cin >> x >> y;\n        pts.push_back({x, y, +1});\n    }\n    for (int i = 0; i < N; i++) {\n        int x, y; cin >> x >> y;\n        pts.push_back({x, y, -1});\n    }\n\n    RangeSum2D ds(pts);\n\n    vector<int> xs, ys;\n    xs.reserve(2 * N);\n    ys.reserve(2 * N);\n    for (auto &p : pts) { xs.push_back(p.x); ys.push_back(p.y); }\n    sort(xs.begin(), xs.end()); xs.erase(unique(xs.begin(), xs.end()), xs.end());\n    sort(ys.begin(), ys.end()); ys.erase(unique(ys.begin(), ys.end()), ys.end());\n\n    vector<int> allX = buildAllCandFromPoints(xs);\n    vector<int> allY = buildAllCandFromPoints(ys);\n\n    // Coarse grid to find good outer rectangles\n    const int G = 170;\n    const int SZ = MAXC + 1;\n\n    auto cellOf = [&](int v) -> int { return (int)((long long)v * G / SZ); };\n    auto lowerBoundCell = [&](int c) -> int { return (int)((long long)c * SZ / G); };\n    auto upperBoundCell = [&](int c) -> int {\n        long long ub = (long long)(c + 1) * SZ / G - 1;\n        ub = max(0LL, min((long long)MAXC, ub));\n        return (int)ub;\n    };\n\n    vector<vector<int>> A(G, vector<int>(G, 0));\n    for (auto &p : pts) A[cellOf(p.x)][cellOf(p.y)] += p.w;\n\n    auto kadane = [&](const vector<long long> &arr)->tuple<long long,int,int> {\n        long long cur = arr[0], best = arr[0];\n        int curL = 0, bestL = 0, bestR = 0;\n        for (int i = 1; i < G; i++) {\n            if (cur < 0) { cur = arr[i]; curL = i; }\n            else cur += arr[i];\n            if (cur > best) { best = cur; bestL = curL; bestR = i; }\n        }\n        return {best, bestL, bestR};\n    };\n\n    struct CellRect { long long sum; int x0,x1,y0,y1; };\n    struct MinCmp { bool operator()(const CellRect& a, const CellRect& b) const { return a.sum > b.sum; } };\n\n    const int TOPK = 24;\n    priority_queue<CellRect, vector<CellRect>, MinCmp> minpq;\n    vector<long long> temp(G);\n\n    for (int x0 = 0; x0 < G; x0++) {\n        fill(temp.begin(), temp.end(), 0LL);\n        for (int x1 = x0; x1 < G; x1++) {\n            for (int y = 0; y < G; y++) temp[y] += A[x1][y];\n            auto [s, yl, yr] = kadane(temp);\n            CellRect cr{s, x0, x1, yl, yr};\n            if ((int)minpq.size() < TOPK) minpq.push(cr);\n            else if (cr.sum > minpq.top().sum) { minpq.pop(); minpq.push(cr); }\n        }\n    }\n\n    vector<CellRect> candCells;\n    while (!minpq.empty()) { candCells.push_back(minpq.top()); minpq.pop(); }\n    sort(candCells.begin(), candCells.end(), [](auto &a, auto &b){ return a.sum > b.sum; });\n\n    mt19937_64 rng((uint64_t)chrono::high_resolution_clock::now().time_since_epoch().count());\n\n    enum Kind { RECT=0, L=1 };\n    Kind bestKind = RECT;\n    long long bestScore = LLONG_MIN;\n\n    int best_xL=0, best_xR=0, best_yB=0, best_yT=0;\n    int best_xM=0, best_yM=0, best_type=0;\n\n    auto considerRect = [&](int xL,int xR,int yB,int yT){\n        normalizeRect(xL,xR,yB,yT);\n        long long d = ds.sumRect(xL,xR,yB,yT);\n        if (d > bestScore) {\n            bestScore = d;\n            bestKind = RECT;\n            best_xL=xL; best_xR=xR; best_yB=yB; best_yT=yT;\n        }\n    };\n\n    auto considerL = [&](int xL,int xR,int yB,int yT,\n                         long long outerSum,\n                         int xM,int yM,int type){\n        if (!(xL < xM && xM < xR && yB < yM && yM < yT)) return;\n\n        // excluded quadrant sums (strictly outside along the cut lines)\n        long long excluded = 0;\n        if (type == 0) excluded = ds.sumRect(xL, xM-1, yM+1, yT);          // remove top-left\n        else if (type == 1) excluded = ds.sumRect(xM+1, xR, yM+1, yT);    // remove top-right\n        else if (type == 2) excluded = ds.sumRect(xL, xM-1, yB, yM-1);    // remove bottom-left\n        else excluded = ds.sumRect(xM+1, xR, yB, yM-1);                  // remove bottom-right\n\n        long long d = outerSum - excluded;\n        if (d > bestScore) {\n            bestScore = d;\n            bestKind = L;\n            best_xL=xL; best_xR=xR; best_yB=yB; best_yT=yT;\n            best_xM=xM; best_yM=yM; best_type=type;\n        }\n    };\n\n    auto localImproveRect = [&](int xL,int xR,int yB,int yT) -> array<int,4> {\n        normalizeRect(xL,xR,yB,yT);\n        long long curBest = ds.sumRect(xL,xR,yB,yT);\n\n        const int RANGE = 9000;\n        const int CAP = 260;\n\n        vector<int> candX = sampleInRange(allX, xL - RANGE, xR + RANGE, CAP, false);\n        vector<int> candY = sampleInRange(allY, yB - RANGE, yT + RANGE, CAP, false);\n\n        candX.push_back(xL); candX.push_back(xR);\n        candY.push_back(yB); candY.push_back(yT);\n        sort(candX.begin(), candX.end()); candX.erase(unique(candX.begin(), candX.end()), candX.end());\n        sort(candY.begin(), candY.end()); candY.erase(unique(candY.begin(), candY.end()), candY.end());\n\n        if (candX.size() < 2 || candY.size() < 2) {\n            considerRect(xL,xR,yB,yT);\n            return {xL,xR,yB,yT};\n        }\n\n        auto rndIdx = [&](int sz)->int { return (int)(rng() % (uint64_t)sz); };\n\n        // Random perturbation\n        int RND_TRIES = 650;\n        for (int it = 0; it < RND_TRIES; it++) {\n            int a = candX[rndIdx((int)candX.size())];\n            int b = candX[rndIdx((int)candX.size())];\n            int c = candY[rndIdx((int)candY.size())];\n            int d = candY[rndIdx((int)candY.size())];\n            int nL=min(a,b), nR=max(a,b), nB=min(c,d), nT=max(c,d);\n            if (nR - nL < 1 || nT - nB < 1) continue;\n            long long val = ds.sumRect(nL,nR,nB,nT);\n            if (val > curBest) {\n                curBest = val;\n                xL=nL; xR=nR; yB=nB; yT=nT;\n            }\n        }\n\n        // Coordinate descent\n        int sweeps = 5;\n        for (int sw = 0; sw < sweeps; sw++) {\n            bool improved = false;\n\n            // xL\n            {\n                long long bestV = curBest;\n                int bestX = xL;\n                for (int nxL : candX) {\n                    if (nxL >= xR) continue;\n                    long long val = ds.sumRect(nxL, xR, yB, yT);\n                    if (val > bestV) { bestV = val; bestX = nxL; }\n                }\n                if (bestX != xL) { xL = bestX; curBest = bestV; improved = true; }\n            }\n            // xR\n            {\n                long long bestV = curBest;\n                int bestX = xR;\n                for (int nxR : candX) {\n                    if (nxR <= xL) continue;\n                    long long val = ds.sumRect(xL, nxR, yB, yT);\n                    if (val > bestV) { bestV = val; bestX = nxR; }\n                }\n                if (bestX != xR) { xR = bestX; curBest = bestV; improved = true; }\n            }\n            // yB\n            {\n                long long bestV = curBest;\n                int bestY = yB;\n                for (int nyB : candY) {\n                    if (nyB >= yT) continue;\n                    long long val = ds.sumRect(xL, xR, nyB, yT);\n                    if (val > bestV) { bestV = val; bestY = nyB; }\n                }\n                if (bestY != yB) { yB = bestY; curBest = bestV; improved = true; }\n            }\n            // yT\n            {\n                long long bestV = curBest;\n                int bestY = yT;\n                for (int nyT : candY) {\n                    if (nyT <= yB) continue;\n                    long long val = ds.sumRect(xL, xR, yB, nyT);\n                    if (val > bestV) { bestV = val; bestY = nyT; }\n                }\n                if (bestY != yT) { yT = bestY; curBest = bestV; improved = true; }\n            }\n\n            if (!improved) break;\n        }\n\n        considerRect(xL,xR,yB,yT);\n        return {xL,xR,yB,yT};\n    };\n\n    // Improve outer rectangles from grid\n    int rectCandidatesToImprove = min(32, (int)candCells.size());\n    vector<array<int,4>> improvedRects;\n    improvedRects.reserve(rectCandidatesToImprove);\n\n    for (int i = 0; i < rectCandidatesToImprove; i++) {\n        auto &cc = candCells[i];\n        int xL = lowerBoundCell(cc.x0);\n        int xR = upperBoundCell(cc.x1);\n        int yB = lowerBoundCell(cc.y0);\n        int yT = upperBoundCell(cc.y1);\n        improvedRects.push_back(localImproveRect(xL,xR,yB,yT));\n    }\n\n    sort(improvedRects.begin(), improvedRects.end(), [&](auto &a, auto &b){\n        long long sa = ds.sumRect(a[0],a[1],a[2],a[3]);\n        long long sb = ds.sumRect(b[0],b[1],b[2],b[3]);\n        return sa > sb;\n    });\n\n    int keepRects = min(12, (int)improvedRects.size());\n\n    // L search\n    for (int ri = 0; ri < keepRects; ri++) {\n        auto r = improvedRects[ri];\n        int xL=r[0], xR=r[1], yB=r[2], yT=r[3];\n        if (!(xL + 1 < xR && yB + 1 < yT)) continue;\n\n        long long outerSum = ds.sumRect(xL,xR,yB,yT);\n\n        // Inner candidates strictly inside outer\n        const int CAPX = 120, CAPY = 120;\n        vector<int> innerX = sampleInRange(allX, xL, xR, CAPX, true);\n        vector<int> innerY = sampleInRange(allY, yB, yT, CAPY, true);\n        if (innerX.empty() || innerY.empty()) continue;\n\n        // Cap cross-product\n        long long pairs = 1LL * innerX.size() * innerY.size();\n        const long long PAIR_CAP = 25000;\n        if (pairs > PAIR_CAP) {\n            int targetY = (int)(PAIR_CAP / max<size_t>(1, innerX.size()));\n            targetY = max(targetY, 1);\n            if ((int)innerY.size() > targetY) {\n                shuffle(innerY.begin(), innerY.end(), rng);\n                innerY.resize(targetY);\n                sort(innerY.begin(), innerY.end());\n                innerY.erase(unique(innerY.begin(), innerY.end()), innerY.end());\n            }\n        }\n\n        long long localBest = LLONG_MIN;\n        int local_xM=-1, local_yM=-1, local_type=0;\n\n        auto scoreL_local = [&](int xM,int yM,int type)->long long{\n            if (!(xL < xM && xM < xR && yB < yM && yM < yT)) return LLONG_MIN/4;\n            long long excluded = 0;\n            if (type == 0) excluded = ds.sumRect(xL, xM-1, yM+1, yT);\n            else if (type == 1) excluded = ds.sumRect(xM+1, xR, yM+1, yT);\n            else if (type == 2) excluded = ds.sumRect(xL, xM-1, yB, yM-1);\n            else excluded = ds.sumRect(xM+1, xR, yB, yM-1);\n            return outerSum - excluded;\n        };\n\n        auto considerL_local = [&](int xM,int yM,int type){\n            long long d = scoreL_local(xM,yM,type);\n            if (d > localBest) {\n                localBest = d;\n                local_xM = xM;\n                local_yM = yM;\n                local_type = type;\n            }\n            considerL(xL,xR,yB,yT,outerSum,xM,yM,type);\n        };\n\n        // Semi-exhaustive\n        for (int type = 0; type < 4; type++) {\n            for (int xM : innerX) {\n                for (int yM : innerY) {\n                    considerL_local(xM,yM,type);\n                }\n            }\n        }\n\n        // Random trials (more budget now that L eval is cheap)\n        int TRIES = 1600;\n        uniform_int_distribution<int> dx(0, (int)innerX.size()-1);\n        uniform_int_distribution<int> dy(0, (int)innerY.size()-1);\n        uniform_int_distribution<int> dt(0, 3);\n        for (int it = 0; it < TRIES; it++) {\n            int xM = innerX[dx(rng)];\n            int yM = innerY[dy(rng)];\n            int type = dt(rng);\n            considerL_local(xM,yM,type);\n        }\n\n        // Coordinate descent on the best local split (and allow type switch at the end)\n        if (local_xM != -1) {\n            int type = local_type;\n            int xM = local_xM, yM = local_yM;\n\n            const int RADX = 2200, RADY = 2200;\n            const int CD_CAPX = 90, CD_CAPY = 90;\n\n            vector<int> cdX = sampleInRange(allX, xM - RADX, xM + RADX, CD_CAPX, true);\n            vector<int> cdY = sampleInRange(allY, yM - RADY, yM + RADY, CD_CAPY, true);\n            if (xL < xM && xM < xR) cdX.push_back(xM);\n            if (yB < yM && yM < yT) cdY.push_back(yM);\n\n            sort(cdX.begin(), cdX.end());\n            cdX.erase(unique(cdX.begin(), cdX.end()), cdX.end());\n            sort(cdY.begin(), cdY.end());\n            cdY.erase(unique(cdY.begin(), cdY.end()), cdY.end());\n\n            for (int step = 0; step < 4; step++) {\n                // optimize xM\n                {\n                    long long bestV = localBest;\n                    int bestX = xM;\n                    for (int nxM : cdX) {\n                        if (!(xL < nxM && nxM < xR)) continue;\n                        long long d = scoreL_local(nxM, yM, type);\n                        if (d > bestV) { bestV = d; bestX = nxM; }\n                    }\n                    if (bestX != xM) {\n                        xM = bestX;\n                        considerL_local(xM, yM, type);\n                    }\n                }\n                // optimize yM\n                {\n                    long long bestV = localBest;\n                    int bestY = yM;\n                    for (int nyM : cdY) {\n                        if (!(yB < nyM && nyM < yT)) continue;\n                        long long d = scoreL_local(xM, nyM, type);\n                        if (d > bestV) { bestV = d; bestY = nyM; }\n                    }\n                    if (bestY != yM) {\n                        yM = bestY;\n                        considerL_local(xM, yM, type);\n                    }\n                }\n            }\n\n            // Try other types at final (xM, yM)\n            for (int t2 = 0; t2 < 4; t2++) considerL_local(xM, yM, t2);\n\n            // Final local random shake around (xM,yM)\n            // (cheap and tends to escape local minima)\n            const int SHAKE_TRIES = 520;\n            uniform_int_distribution<int> sx(0, max(1,(int)cdX.size())-1);\n            uniform_int_distribution<int> sy(0, max(1,(int)cdY.size())-1);\n            uniform_int_distribution<int> st(0,3);\n\n            for (int it = 0; it < SHAKE_TRIES; it++) {\n                int nxM = cdX[sx(rng)];\n                int nyM = cdY[sy(rng)];\n                int t = st(rng);\n                if (nxM <= xL || nxM >= xR || nyM <= yB || nyM >= yT) continue;\n                considerL_local(nxM, nyM, t);\n            }\n        }\n    }\n\n    // Output polygon\n    auto outRect = [&](int xL,int xR,int yB,int yT){\n        cout << 4 << \"\\n\";\n        cout << xL << \" \" << yB << \"\\n\";\n        cout << xR << \" \" << yB << \"\\n\";\n        cout << xR << \" \" << yT << \"\\n\";\n        cout << xL << \" \" << yT << \"\\n\";\n    };\n\n    if (bestKind == RECT) {\n        outRect(best_xL,best_xR,best_yB,best_yT);\n    } else {\n        int xL=best_xL, xR=best_xR, yB=best_yB, yT=best_yT;\n        int xM=best_xM, yM=best_yM, type=best_type;\n\n        vector<pair<int,int>> v;\n        // CCW, 6 vertices\n        if (type == 0) { // missing top-left\n            v = {{xR,yB},{xL,yB},{xL,yM},{xM,yM},{xM,yT},{xR,yT}};\n        } else if (type == 1) { // missing top-right\n            v = {{xL,yB},{xR,yB},{xR,yM},{xM,yM},{xM,yT},{xL,yT}};\n        } else if (type == 2) { // missing bottom-left\n            v = {{xM,yM},{xL,yM},{xL,yT},{xR,yT},{xR,yB},{xM,yB}};\n        } else { // missing bottom-right\n            v = {{xM,yM},{xR,yM},{xR,yT},{xL,yT},{xL,yB},{xM,yB}};\n        }\n\n        cout << 6 << \"\\n\";\n        for (auto &p: v) cout << p.first << \" \" << p.second << \"\\n\";\n    }\n\n    return 0;\n}","ahc040":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct SplitMix64 {\n    uint64_t x;\n    explicit SplitMix64(uint64_t seed) : x(seed) {}\n    uint64_t next_u64() {\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 next_int(int l, int r) { // inclusive\n        return l + (int)(next_u64() % (uint64_t)(r - l + 1));\n    }\n    double next_double() { // [0,1)\n        return (next_u64() >> 11) * (1.0 / 9007199254740992.0);\n    }\n};\n\nstatic inline long long choosePrefRotU(int i, const vector<long long>& wp, const vector<long long>& hp) {\n    // dir U: x step uses width -> minimize width\n    // rot=0 => width=wp, rot=1 => width=hp\n    return (hp[i] < wp[i]) ? 1LL : 0LL;\n}\nstatic inline long long choosePrefRotL(int i, const vector<long long>& wp, const vector<long long>& hp) {\n    // dir L: y step uses height -> minimize height\n    // rot=0 => height=hp, rot=1 => height=wp\n    return (wp[i] < hp[i]) ? 1LL : 0LL;\n}\n\nstruct Layout {\n    vector<int> rot;      // 0/1\n    vector<char> dir;     // 'U' or 'L'\n};\n\nstatic long long simulateObjBprev(const Layout& lay,\n                                   const vector<long long>& wp,\n                                   const vector<long long>& hp,\n                                   int N) {\n    // b_i = i-1 (and b_0 = -1), overlap-free guaranteed by slide simulation.\n    vector<long long> x(N), y(N), w(N), h(N);\n\n    long long W = 0, H = 0;\n    for (int i = 0; i < N; i++) {\n        if (lay.rot[i] == 0) { w[i] = wp[i]; h[i] = hp[i]; }\n        else { w[i] = hp[i]; h[i] = wp[i]; }\n\n        if (lay.dir[i] == 'U') {\n            if (i == 0) x[i] = 0;\n            else x[i] = x[i-1] + w[i-1]; // align with right edge of b=i-1\n            long long yy = 0;\n            for (int j = 0; j < i; j++) {\n                // x intervals overlap?\n                if (x[i] < x[j] + w[j] && x[j] < x[i] + w[i]) {\n                    yy = max(yy, y[j] + h[j]);\n                }\n            }\n            y[i] = yy;\n        } else { // 'L'\n            if (i == 0) y[i] = 0;\n            else y[i] = y[i-1] + h[i-1]; // align with bottom edge of b=i-1\n            long long xx = 0;\n            for (int j = 0; j < i; j++) {\n                // y intervals overlap?\n                if (y[i] < y[j] + h[j] && y[j] < y[i] + h[i]) {\n                    xx = max(xx, x[j] + w[j]);\n                }\n            }\n            x[i] = xx;\n        }\n        W = max(W, x[i] + w[i]);\n        H = max(H, y[i] + h[i]);\n    }\n    return W + H;\n}\n\nstatic long long simulateWHEvalBprev(const Layout& lay,\n                                      const vector<long long>& wp,\n                                      const vector<long long>& hp,\n                                      int N,\n                                      long long &Wout, long long &Hout) {\n    vector<long long> x(N), y(N), w(N), h(N);\n    long long W = 0, H = 0;\n\n    for (int i = 0; i < N; i++) {\n        if (lay.rot[i] == 0) { w[i] = wp[i]; h[i] = hp[i]; }\n        else { w[i] = hp[i]; h[i] = wp[i]; }\n\n        if (lay.dir[i] == 'U') {\n            if (i == 0) x[i] = 0;\n            else x[i] = x[i-1] + w[i-1];\n            long long yy = 0;\n            for (int j = 0; j < i; j++) {\n                if (x[i] < x[j] + w[j] && x[j] < x[i] + w[i]) {\n                    yy = max(yy, y[j] + h[j]);\n                }\n            }\n            y[i] = yy;\n        } else {\n            if (i == 0) y[i] = 0;\n            else y[i] = y[i-1] + h[i-1];\n            long long xx = 0;\n            for (int j = 0; j < i; j++) {\n                if (y[i] < y[j] + h[j] && y[j] < y[i] + h[i]) {\n                    xx = max(xx, x[j] + w[j]);\n                }\n            }\n            x[i] = xx;\n        }\n        W = max(W, x[i] + w[i]);\n        H = max(H, y[i] + h[i]);\n    }\n    Wout = W; Hout = H;\n    return W + H;\n}\n\n// Exact rotation optimization for the all-U chain:\n// objective = sum(width_i) + max(height_i), with width/height depend on rot.\nstatic vector<int> bestRotAllU(const vector<long long>& wp, const vector<long long>& hp) {\n    int N = (int)wp.size();\n    vector<long long> cand;\n    cand.reserve(2*N);\n    for(int i=0;i<N;i++){ cand.push_back(hp[i]); cand.push_back(wp[i]); }\n    sort(cand.begin(), cand.end());\n    cand.erase(unique(cand.begin(), cand.end()), cand.end());\n\n    const long long INF = (1LL<<62);\n    long long bestObj = INF;\n    long long bestH = cand[0];\n    vector<int> bestRot(N,0);\n\n    for(long long Hcap: cand) {\n        bool ok = true;\n        long long sumW = 0;\n        vector<int> rot(N,0);\n        for(int i=0;i<N;i++){\n            bool can0 = (hp[i] <= Hcap); // rot=0 => height=hp\n            bool can1 = (wp[i] <= Hcap); // rot=1 => height=wp\n            if(!can0 && !can1){ ok=false; break; }\n            int r;\n            long long w0 = wp[i], w1 = hp[i];\n            if(can0 && can1){\n                r = (w0 < w1) ? 0 : 1; // minimize width\n                if(w0==w1) r=0;\n            } else r = can0 ? 0 : 1;\n            rot[i]=r;\n            long long wi = (rot[i]==0 ? wp[i] : hp[i]);\n            sumW += wi;\n        }\n        if(!ok) continue;\n        long long obj = sumW + Hcap;\n        if(obj < bestObj){\n            bestObj = obj;\n            bestH = Hcap;\n            bestRot = rot;\n        }\n    }\n    (void)bestH;\n    return bestRot;\n}\n\n// Exact rotation optimization for the all-L chain:\n// objective = max(width_i) + sum(height_i)\nstatic vector<int> bestRotAllL(const vector<long long>& wp, const vector<long long>& hp) {\n    int N = (int)wp.size();\n    vector<long long> cand;\n    cand.reserve(2*N);\n    for(int i=0;i<N;i++){ cand.push_back(wp[i]); cand.push_back(hp[i]); }\n    sort(cand.begin(), cand.end());\n    cand.erase(unique(cand.begin(), cand.end()), cand.end());\n\n    const long long INF = (1LL<<62);\n    long long bestObj = INF;\n    long long bestW = cand[0];\n    vector<int> bestRot(N,0);\n\n    for(long long Wcap: cand) {\n        bool ok = true;\n        long long sumH = 0;\n        vector<int> rot(N,0);\n        for(int i=0;i<N;i++){\n            bool can0 = (wp[i] <= Wcap); // rot=0 => width=wp\n            bool can1 = (hp[i] <= Wcap); // rot=1 => width=hp\n            if(!can0 && !can1){ ok=false; break; }\n            int r;\n            long long h0 = hp[i], h1 = wp[i]; // height contributed\n            if(can0 && can1){\n                r = (h0 < h1) ? 0 : 1; // minimize height\n                if(h0==h1) r=0;\n            } else r = can0 ? 0 : 1;\n            rot[i]=r;\n            long long hi = (rot[i]==0 ? hp[i] : wp[i]);\n            sumH += hi;\n        }\n        if(!ok) continue;\n        long long obj = Wcap + sumH;\n        if(obj < bestObj){\n            bestObj = obj;\n            bestW = Wcap;\n            bestRot = rot;\n        }\n    }\n    (void)bestW;\n    return bestRot;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, T;\n    long long sigma;\n    cin >> N >> T >> sigma;\n    vector<long long> wp(N), hp(N);\n    for(int i=0;i<N;i++) cin >> wp[i] >> hp[i];\n\n    // Seed\n    uint64_t seed = 0x123456789abcdef0ULL;\n    seed ^= (uint64_t)N * 1000003ULL;\n    seed ^= (uint64_t)T * 10007ULL;\n    seed ^= (uint64_t)sigma * 911382323ULL;\n    for(int i=0;i<N;i++){\n        seed ^= (uint64_t)(wp[i] + 1000003LL*hp[i] + (i+1)*10007LL);\n        seed *= 1099511628211ULL;\n    }\n    SplitMix64 rng(seed);\n\n    // Baselines\n    Layout allU, allL;\n    allU.dir.assign(N,'U');\n    allL.dir.assign(N,'L');\n    allU.rot = bestRotAllU(wp,hp);\n    allL.rot = bestRotAllL(wp,hp);\n\n    vector<Layout> init;\n    init.push_back(allU);\n    init.push_back(allL);\n\n    // Split patterns\n    vector<int> splits = {N/4, N/2, 3*N/4};\n    for(int s: splits){\n        s = max(0, min(N, s));\n        Layout lay;\n        lay.dir.resize(N);\n        lay.rot.resize(N);\n        for(int i=0;i<N;i++){\n            lay.dir[i] = (i < s ? 'U' : 'L');\n            if(lay.dir[i]=='U') lay.rot[i] = (int)choosePrefRotU(i, wp, hp);\n            else lay.rot[i] = (int)choosePrefRotL(i, wp, hp);\n        }\n        init.push_back(lay);\n        // also reverse\n        Layout lay2 = lay;\n        for(int i=0;i<N;i++) lay2.dir[i] = (lay2.dir[i]=='U'?'L':'U');\n        for(int i=0;i<N;i++){\n            lay2.rot[i] = (lay2.dir[i]=='U' ? (int)choosePrefRotU(i,wp,hp) : (int)choosePrefRotL(i,wp,hp));\n        }\n        init.push_back(lay2);\n    }\n\n    // Alternating\n    for(int start=0; start<2; start++){\n        Layout lay;\n        lay.dir.resize(N);\n        lay.rot.resize(N);\n        for(int i=0;i<N;i++){\n            lay.dir[i] = ((i+start)%2==0 ? 'U' : 'L');\n            lay.rot[i] = (lay.dir[i]=='U' ? (int)choosePrefRotU(i,wp,hp) : (int)choosePrefRotL(i,wp,hp));\n        }\n        init.push_back(lay);\n    }\n\n    // Random initial\n    for(int k=0;k<4;k++){\n        Layout lay;\n        lay.dir.resize(N);\n        lay.rot.resize(N);\n        for(int i=0;i<N;i++){\n            lay.dir[i] = (rng.next_int(0,1)==0 ? 'U' : 'L');\n            // correlate rotation with dir preference, with some randomness\n            int pref = (lay.dir[i]=='U' ? (int)choosePrefRotU(i,wp,hp) : (int)choosePrefRotL(i,wp,hp));\n            lay.rot[i] = (rng.next_double() < 0.85 ? pref : pref^1);\n        }\n        init.push_back(lay);\n    }\n\n    // Rank init by predicted objective and pick top few to try\n    vector<pair<long long,int>> order;\n    order.reserve(init.size());\n    for(int i=0;i<(int)init.size();i++){\n        long long pred = simulateObjBprev(init[i], wp, hp, N);\n        order.push_back({pred,i});\n    }\n    sort(order.begin(), order.end());\n\n    int K = min(T, 10);\n    vector<Layout> tried;\n    tried.reserve(K);\n\n    Layout cur = init[order[0].second];\n    long long curMeas = (1LL<<62);\n\n    Layout bestLay = cur;\n    long long bestMeas = (1LL<<62);\n\n    auto outputLayout = [&](const Layout& lay){\n        cout << N << \"\\n\";\n        for(int i=0;i<N;i++){\n            int p = i;\n            int r = lay.rot[i];\n            char d = lay.dir[i];\n            int b = (i==0 ? -1 : i-1); // fixed b=i-1 for legality\n            cout << p << \" \" << r << \" \" << d << \" \" << b << \"\\n\";\n        }\n        cout << flush;\n    };\n\n    for(int ti=0; ti<K; ti++){\n        int idx = order[ti].second;\n        Layout cand = init[idx];\n        outputLayout(cand);\n        long long Wp,Hp;\n        cin >> Wp >> Hp;\n        long long meas = Wp + Hp;\n\n        tried.push_back(cand);\n\n        if(meas < bestMeas){\n            bestMeas = meas;\n            bestLay = cand;\n        }\n        if(meas < curMeas){\n            curMeas = meas;\n            cur = cand;\n        }\n    }\n\n    // For critical-index bias, compute from current best layout\n    auto computeCritical = [&](const Layout& lay, vector<int>& critical){\n        // run full simulation with arrays to identify indices reaching max W or max H (in predicted world).\n        vector<long long> x(N), y(N), w(N), h(N);\n        long long W=0,H=0;\n        for(int i=0;i<N;i++){\n            if(lay.rot[i]==0){ w[i]=wp[i]; h[i]=hp[i]; }\n            else { w[i]=hp[i]; h[i]=wp[i]; }\n            if(lay.dir[i]=='U'){\n                x[i] = (i==0?0:x[i-1]+w[i-1]);\n                long long yy=0;\n                for(int j=0;j<i;j++){\n                    if(x[i] < x[j]+w[j] && x[j] < x[i]+w[i]) yy=max(yy, y[j]+h[j]);\n                }\n                y[i]=yy;\n            } else {\n                y[i] = (i==0?0:y[i-1]+h[i-1]);\n                long long xx=0;\n                for(int j=0;j<i;j++){\n                    if(y[i] < y[j]+h[j] && y[j] < y[i]+h[i]) xx=max(xx, x[j]+w[j]);\n                }\n                x[i]=xx;\n            }\n            W=max(W, x[i]+w[i]);\n            H=max(H, y[i]+h[i]);\n        }\n        critical.clear();\n        for(int i=0;i<N;i++){\n            if(x[i]+w[i]==W || y[i]+h[i]==H) critical.push_back(i);\n        }\n        if(critical.empty()) critical.push_back(0);\n    };\n\n    vector<int> critical;\n    computeCritical(bestLay, critical);\n\n    auto mutateCandidate = [&](const Layout& base) {\n        Layout cand = base;\n\n        // sometimes do a global split reset\n        if(rng.next_double() < 0.12){\n            int s = rng.next_int(0, N);\n            for(int i=0;i<N;i++){\n                cand.dir[i] = (i < s ? 'U' : 'L');\n                cand.rot[i] = (cand.dir[i]=='U' ? (int)choosePrefRotU(i,wp,hp) : (int)choosePrefRotL(i,wp,hp));\n            }\n        } else {\n            int k = rng.next_int(1, 4);\n            for(int t=0;t<k;t++){\n                int i;\n                if(rng.next_double() < 0.55) i = critical[rng.next_int(0,(int)critical.size()-1)];\n                else i = rng.next_int(0, N-1);\n\n                int op = rng.next_int(0, 5);\n                if(op <= 1){\n                    // flip dir, maybe re-pick rotation for that dir\n                    cand.dir[i] = (cand.dir[i]=='U' ? 'L' : 'U');\n                    if(rng.next_double() < 0.7){\n                        cand.rot[i] = (cand.dir[i]=='U' ? (int)choosePrefRotU(i,wp,hp) : (int)choosePrefRotL(i,wp,hp));\n                    }\n                } else if(op <= 3){\n                    // flip rotation\n                    cand.rot[i] ^= 1;\n                } else {\n                    // set to preferred rotation for current dir\n                    cand.rot[i] = (cand.dir[i]=='U' ? (int)choosePrefRotU(i,wp,hp) : (int)choosePrefRotL(i,wp,hp));\n                    // sometimes also flip dir\n                    if(rng.next_double() < 0.25) cand.dir[i] = (cand.dir[i]=='U' ? 'L' : 'U');\n                }\n            }\n        }\n\n        return cand;\n    };\n\n    long long dummyW,dummyH;\n    for(int t = K; t < T; t++){\n        // choose base to mutate from\n        const Layout& base = (rng.next_double() < 0.75 ? bestLay : cur);\n\n        // generate several candidates and pick the best predicted\n        const int M = 8;\n        Layout bestCand = base;\n        long long bestPred = (1LL<<62);\n\n        for(int j=0;j<M;j++){\n            Layout cand = mutateCandidate(base);\n            long long pred = simulateObjBprev(cand, wp, hp, N);\n            if(pred < bestPred){\n                bestPred = pred;\n                bestCand = std::move(cand);\n            }\n        }\n\n        // Output best predicted candidate\n        outputLayout(bestCand);\n        cin >> dummyW >> dummyH;\n        long long meas = dummyW + dummyH;\n\n        if(meas < bestMeas){\n            bestMeas = meas;\n            bestLay = bestCand;\n            computeCritical(bestLay, critical);\n        }\n\n        // SA-like update of current using measured objective\n        bool accept = false;\n        if(meas <= curMeas){\n            accept = true;\n        } else {\n            // temperature schedule\n            long double prog = (long double)(t+1) / (long double)T;\n            long double temp = 200000.0L * (1.0L - prog) + 20000.0L; // tuned\n            long double delta = (long double)meas - (long double)curMeas;\n            long double prob = expl(-delta / temp);\n            if(rng.next_double() < prob) accept = true;\n        }\n\n        if(accept){\n            cur = bestCand;\n            curMeas = meas;\n        }\n    }\n\n    return 0;\n}","ahc041":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct RNG {\n    mt19937 rng;\n    RNG() : rng((uint32_t)chrono::steady_clock::now().time_since_epoch().count()) {}\n    uint32_t next_u32() { return rng(); }\n    int randint(int l, int r) { // inclusive\n        return l + (int)(next_u32() % (uint32_t)(r - l + 1));\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, H;\n    cin >> N >> M >> H;\n\n    vector<int> A(N);\n    for (int i = 0; i < N; i++) cin >> A[i];\n\n    vector<vector<int>> g(N);\n    for (int i = 0; i < M; i++) {\n        int u, v;\n        cin >> u >> v;\n        g[u].push_back(v);\n        g[v].push_back(u);\n    }\n    for (int i = 0; i < N; i++) {\n        int x, y;\n        cin >> x >> y; // unused\n    }\n\n    // Bias neighbor traversal order (affects BFS-tree shape)\n    for (int v = 0; v < N; v++) {\n        auto &adj = g[v];\n        sort(adj.begin(), adj.end(), [&](int a, int b) {\n            if (A[a] != A[b]) return A[a] > A[b];\n            return a < b;\n        });\n    }\n\n    // Candidate selection potential: pot[s] = sum_{u dist(s,u)<=H} (dist+1)*A[u] on full graph\n    vector<long long> pot(N, 0);\n    vector<int> dist(N, -1);\n    queue<int> q;\n    for (int s = 0; s < N; s++) {\n        fill(dist.begin(), dist.end(), -1);\n        while (!q.empty()) q.pop();\n        dist[s] = 0;\n        q.push(s);\n        long long ps = 0;\n        while (!q.empty()) {\n            int x = q.front(); q.pop();\n            ps += 1LL * (dist[x] + 1) * A[x];\n            if (dist[x] == H) continue;\n            for (int y : g[x]) {\n                if (dist[y] != -1) continue;\n                dist[y] = dist[x] + 1;\n                q.push(y);\n            }\n        }\n        pot[s] = ps;\n    }\n\n    vector<int> orderPot(N), orderA(N);\n    iota(orderPot.begin(), orderPot.end(), 0);\n    iota(orderA.begin(), orderA.end(), 0);\n    sort(orderPot.begin(), orderPot.end(), [&](int i, int j) {\n        if (pot[i] != pot[j]) return pot[i] > pot[j];\n        if (A[i] != A[j]) return A[i] > A[j];\n        return i < j;\n    });\n    sort(orderA.begin(), orderA.end(), [&](int i, int j) {\n        if (A[i] != A[j]) return A[i] > A[j];\n        if (pot[i] != pot[j]) return pot[i] > pot[j];\n        return i < j;\n    });\n\n    RNG R;\n    const double TL = 1.95; // slightly under 2 sec\n\n    vector<int> bestParent(N, -1);\n    long long bestScore = LLONG_MIN;\n\n    // Unassigned set\n    vector<int> unass, posInUnass;\n    unass.reserve(N);\n    posInUnass.assign(N, -1);\n\n    // Global attempt arrays\n    vector<char> assigned(N);\n    vector<int> parentOut(N, -1);\n\n    // BFS eval buffers\n    vector<int> seen(N, 0), dtmp(N, 0);\n    int timerEval = 1;\n\n    // Component claim buffers\n    vector<int> inCompStamp(N, 0), compDepth(N, 0);\n    int compStamp = 1;\n    vector<int> parentHigh(N, -1), parentLow(N, -1);\n\n    // For reroot: reusable local arrays (max size N)\n    vector<int> head, to, nxt;\n    vector<int> dist1, dist2, distTmp, qbuf, parLocal, parentL, order;\n    vector<long long> subW, downS, S;\n    vector<int> loc(N, -1);\n\n    auto remove_from_unass = [&](int v) {\n        int p = posInUnass[v];\n        int w = unass.back();\n        unass[p] = w;\n        posInUnass[w] = p;\n        unass.pop_back();\n        posInUnass[v] = -1;\n    };\n\n    auto eval_root = [&](int root) -> long long {\n        timerEval++;\n        long long sc = 0;\n\n        // BFS with truncated depth H on remaining vertices\n        int qh = 0, qt = 0;\n        if ((int)qbuf.size() < N) qbuf.assign(N, 0);\n        qbuf[qt++] = root;\n        seen[root] = timerEval;\n        dtmp[root] = 0;\n        sc += 1LL * (dtmp[root] + 1) * A[root];\n\n        while (qh < qt) {\n            int x = qbuf[qh++];\n            int dx = dtmp[x];\n            if (dx == H) continue;\n            for (int y : g[x]) {\n                if (assigned[y]) continue;\n                if (seen[y] == timerEval) continue;\n                seen[y] = timerEval;\n                dtmp[y] = dx + 1;\n                sc += 1LL * (dtmp[y] + 1) * A[y];\n                qbuf[qt++] = y;\n            }\n        }\n        return sc;\n    };\n\n    // Reroot DP on a tree defined by parentArr[v] for v in nodes (root has parent -1).\n    auto reroot_component = [&](const vector<int>& nodes, const vector<int>& parentArr, vector<int>& outPar) -> long long {\n        int sz = (int)nodes.size();\n        if (sz == 1) {\n            outPar[nodes[0]] = -1;\n            return A[nodes[0]];\n        }\n\n        // local index mapping\n        for (int i = 0; i < sz; i++) loc[nodes[i]] = i;\n\n        // Build adjacency of the tree\n        head.assign(sz, -1);\n        to.assign(2 * (sz - 1), 0);\n        nxt.assign(2 * (sz - 1), -1);\n        int ec = 0;\n        auto addEdge = [&](int u, int v) {\n            to[ec] = v;\n            nxt[ec] = head[u];\n            head[u] = ec++;\n        };\n\n        for (int gv : nodes) {\n            int p = parentArr[gv];\n            if (p == -1) continue;\n            int u = loc[gv], v = loc[p];\n            addEdge(u, v);\n            addEdge(v, u);\n        }\n\n        auto bfs_far = [&](int src, vector<int>& distOut) -> int {\n            distOut.assign(sz, -1);\n            int qh = 0, qt = 0;\n            if ((int)qbuf.size() < sz) qbuf.assign(sz, 0);\n            qbuf[qt++] = src;\n            distOut[src] = 0;\n            int far = src;\n            while (qh < qt) {\n                int x = qbuf[qh++];\n                if (distOut[x] > distOut[far]) far = x;\n                for (int e = head[x]; e != -1; e = nxt[e]) {\n                    int y = to[e];\n                    if (distOut[y] != -1) continue;\n                    distOut[y] = distOut[x] + 1;\n                    qbuf[qt++] = y;\n                }\n            }\n            return far;\n        };\n\n        // Diameter endpoints and distances\n        int end1 = bfs_far(0, distTmp);\n        int end2 = bfs_far(end1, dist1);\n        (void)end2;\n        bfs_far(end2, dist2);\n\n        // Root at local 0 for DP\n        parentL.assign(sz, -2);\n        order.clear();\n        order.reserve(sz);\n        vector<int> st;\n        st.reserve(sz);\n        st.push_back(0);\n        parentL[0] = -1;\n        while (!st.empty()) {\n            int x = st.back(); st.pop_back();\n            order.push_back(x);\n            for (int e = head[x]; e != -1; e = nxt[e]) {\n                int y = to[e];\n                if (parentL[y] != -2) continue;\n                parentL[y] = x;\n                st.push_back(y);\n            }\n        }\n\n        // Postorder for subtree weights and downS\n        subW.assign(sz, 0);\n        downS.assign(sz, 0);\n        S.assign(sz, 0);\n\n        for (int i = sz - 1; i >= 0; i--) {\n            int x = order[i];\n            long long wsum = A[nodes[x]];\n            long long dsum = 0;\n            for (int e = head[x]; e != -1; e = nxt[e]) {\n                int y = to[e];\n                if (parentL[y] == x) {\n                    wsum += subW[y];\n                    dsum += downS[y] + subW[y];\n                }\n            }\n            subW[x] = wsum;\n            downS[x] = dsum;\n        }\n\n        long long totalW = subW[0];\n        S[0] = downS[0];\n\n        // Reroot transitions\n        for (int x : order) {\n            for (int e = head[x]; e != -1; e = nxt[e]) {\n                int y = to[e];\n                if (parentL[y] == x) {\n                    S[y] = S[x] + totalW - 2LL * subW[y];\n                }\n            }\n        }\n\n        // Choose best feasible root with eccentricity <= H\n        long long bestS = LLONG_MIN;\n        int bestLocal = 0;\n        for (int i = 0; i < sz; i++) {\n            int ecc = max(dist1[i], dist2[i]);\n            if (ecc <= H) {\n                if (S[i] > bestS) {\n                    bestS = S[i];\n                    bestLocal = i;\n                }\n            }\n        }\n        if (bestS == LLONG_MIN) { // should not happen\n            bestLocal = 0;\n            bestS = S[0];\n        }\n\n        // Orient tree from bestLocal to fill outPar\n        parLocal.assign(sz, -2);\n        int qh = 0, qt = 0;\n        if ((int)qbuf.size() < sz) qbuf.assign(sz, 0);\n        parLocal[bestLocal] = -1;\n        qbuf[qt++] = bestLocal;\n        while (qh < qt) {\n            int x = qbuf[qh++];\n            for (int e = head[x]; e != -1; e = nxt[e]) {\n                int y = to[e];\n                if (parLocal[y] != -2) continue;\n                parLocal[y] = x;\n                qbuf[qt++] = y;\n            }\n        }\n\n        for (int i = 0; i < sz; i++) {\n            int gv = nodes[i];\n            int pLocal = parLocal[i];\n            outPar[gv] = (pLocal == -1 ? -1 : nodes[pLocal]);\n        }\n\n        return totalW + bestS; // sum(A) + sum(A*dist)\n    };\n\n    auto tStart = chrono::steady_clock::now();\n    int attempts = 0;\n\n    while (true) {\n        double elapsed = chrono::duration<double>(chrono::steady_clock::now() - tStart).count();\n        if (elapsed > TL) break;\n        attempts++;\n\n        fill(assigned.begin(), assigned.end(), 0);\n        fill(parentOut.begin(), parentOut.end(), -1);\n\n        unass.clear();\n        unass.reserve(N);\n        for (int i = 0; i < N; i++) {\n            posInUnass[i] = i;\n            unass.push_back(i);\n        }\n\n        timerEval = 1;\n        compStamp = 1;\n\n        long long totalScore = 0;\n\n        // candidate marking\n        vector<int> candMark(N, 0);\n        int candTimer = 1;\n\n        while (!unass.empty()) {\n            int remaining = (int)unass.size();\n            int K = min(22, remaining);\n            int topPot = min(12, K);\n            int topA = min(8, K - topPot);\n            int topKeep = min(5, K);\n\n            candTimer++;\n            vector<int> cand;\n            cand.reserve(K);\n\n            auto addCand = [&](int v) {\n                if (assigned[v]) return;\n                if (candMark[v] == candTimer) return;\n                candMark[v] = candTimer;\n                cand.push_back(v);\n            };\n\n            for (int v : orderPot) {\n                if ((int)cand.size() == topPot) break;\n                if (!assigned[v]) addCand(v);\n            }\n            for (int v : orderA) {\n                if ((int)cand.size() == topPot + topA) break;\n                if (!assigned[v]) addCand(v);\n            }\n\n            while ((int)cand.size() < K) {\n                int v = unass[R.next_u32() % (uint32_t)remaining];\n                addCand(v);\n            }\n\n            vector<pair<long long,int>> scored;\n            scored.reserve(K);\n            for (int r : cand) scored.push_back({eval_root(r), r});\n\n            sort(scored.begin(), scored.end(), [&](auto &x, auto &y) {\n                if (x.first != y.first) return x.first > y.first;\n                return A[x.second] > A[y.second];\n            });\n\n            int pickIdx = (topKeep <= 1 ? 0 : (int)(R.next_u32() % (uint32_t)topKeep));\n            int chosenRoot = scored[pickIdx].second;\n\n            // ---- Claim component: build two variants of parent pointers ----\n            compStamp++;\n            int stamp = compStamp;\n\n            vector<int> nodes;\n            nodes.reserve(256);\n\n            vector<int> curr, next;\n            curr.clear(); next.clear();\n\n            inCompStamp[chosenRoot] = stamp;\n            compDepth[chosenRoot] = 0;\n            parentHigh[chosenRoot] = -1;\n            parentLow[chosenRoot] = -1;\n            nodes.push_back(chosenRoot);\n            curr.push_back(chosenRoot);\n\n            for (int depth = 0; depth < H; depth++) {\n                next.clear();\n                for (int x : curr) {\n                    for (int y : g[x]) {\n                        if (assigned[y]) continue;\n\n                        if (inCompStamp[y] != stamp) {\n                            inCompStamp[y] = stamp;\n                            compDepth[y] = depth + 1;\n                            parentHigh[y] = x;\n                            parentLow[y] = x;\n                            next.push_back(y);\n                            nodes.push_back(y);\n                        } else {\n                            // already in component; tie-break only on same shortest layer\n                            if (compDepth[y] == depth + 1) {\n                                int ph = parentHigh[y];\n                                if (ph == -1 || A[x] > A[ph] || (A[x] == A[ph] && (R.next_u32() & 1u))) {\n                                    parentHigh[y] = x;\n                                }\n                                int pl = parentLow[y];\n                                if (pl == -1 || A[x] < A[pl] || (A[x] == A[pl] && (R.next_u32() & 1u))) {\n                                    parentLow[y] = x;\n                                }\n                            }\n                        }\n                    }\n                }\n                if (next.empty()) break;\n                curr.swap(next);\n            }\n\n            // mark component nodes as assigned & remove from unassigned\n            for (int v : nodes) {\n                assigned[v] = 1;\n                remove_from_unass(v);\n            }\n\n            // reroot both variants; keep the better one\n            vector<int> tempPar(N, -1);\n            long long bestCompScore = LLONG_MIN;\n\n            // If component is tiny, rerooting twice might be wasteful\n            if ((int)nodes.size() <= 30) {\n                bestCompScore = reroot_component(nodes, parentHigh, parentOut);\n            } else {\n                // variant High -> tempPar\n                long long scHigh = reroot_component(nodes, parentHigh, tempPar);\n                // commit tempPar into parentOut later if better\n                vector<int> parHighBackup = tempPar; // N=1000, acceptable\n\n                // variant Low -> tempPar\n                fill(tempPar.begin(), tempPar.end(), -1);\n                long long scLow = reroot_component(nodes, parentLow, tempPar);\n\n                if (scHigh >= scLow) {\n                    bestCompScore = scHigh;\n                    // write backup to parentOut (only nodes are relevant)\n                    for (int v : nodes) parentOut[v] = parHighBackup[v];\n                } else {\n                    bestCompScore = scLow;\n                    for (int v : nodes) parentOut[v] = tempPar[v];\n                }\n            }\n\n            totalScore += bestCompScore;\n        }\n\n        if (totalScore > bestScore) {\n            bestScore = totalScore;\n            bestParent = parentOut;\n        }\n    }\n\n    for (int i = 0; i < N; i++) {\n        cout << bestParent[i] << (i + 1 == N ? '\\n' : ' ');\n    }\n    return 0;\n}","ahc042":"#include <bits/stdc++.h>\nusing namespace std;\n\nenum Dir { UP = 0, DOWN = 1, LEFT = 2, RIGHT = 3 };\n\nstruct Option {\n    int var; // which line-direction variable\n    int L;   // required shift length for this Oni\n    Dir d;\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<char>> fuku(N, vector<char>(N, 0));\n    vector<pair<int,int>> oni;\n    oni.reserve(2 * N);\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (C[i][j] == 'o') fuku[i][j] = 1;\n            else if (C[i][j] == 'x') oni.push_back({i, j});\n        }\n    }\n\n    const int M = (int)oni.size(); // guaranteed = 2N\n    const int V = 4 * N;          // variables: UP cols, DOWN cols, LEFT rows, RIGHT rows\n    const int64_t Tlimit = 4LL * N * N;\n    const int64_t limitSum = Tlimit / 2; // sum of line lengths (since T=2*sum)\n\n    auto varUp = [&](int col){ return col; };\n    auto varDown = [&](int col){ return N + col; };\n    auto varLeft = [&](int row){ return 2*N + row; };\n    auto varRight = [&](int row){ return 3*N + row; };\n\n    // Precompute maximum safe lengths per line-direction:\n    // UP on column j: remove top L cells [0..L-1], safe iff no fuku in those => L <= firstFukuRow\n    // DOWN on column j: remove bottom L cells [N-L..N-1], safe iff no fuku in those => L <= N-1-lastFukuRow\n    vector<int> maxUp(N), maxDown(N), maxLeft(N), maxRight(N);\n\n    for (int j = 0; j < N; j++) {\n        int first = N, last = -1;\n        for (int i = 0; i < N; i++) if (fuku[i][j]) {\n            first = min(first, i);\n            last = max(last, i);\n        }\n        maxUp[j] = first;\n        maxDown[j] = (last == -1 ? N : (N - 1 - last));\n    }\n    for (int i = 0; i < N; i++) {\n        int first = N, last = -1;\n        for (int j = 0; j < N; j++) if (fuku[i][j]) {\n            first = min(first, j);\n            last = max(last, j);\n        }\n        maxLeft[i] = first;\n        maxRight[i] = (last == -1 ? N : (N - 1 - last));\n    }\n\n    // Build options for each Oni\n    vector<vector<Option>> options(M);\n    for (int id = 0; id < M; id++) {\n        int i = oni[id].first, j = oni[id].second;\n\n        // UP: L = i+1\n        int Lup = i + 1;\n        if (Lup <= maxUp[j]) options[id].push_back({varUp(j), Lup, UP});\n\n        // DOWN: L = N-i\n        int Ldown = N - i;\n        if (Ldown <= maxDown[j]) options[id].push_back({varDown(j), Ldown, DOWN});\n\n        // LEFT: L = j+1\n        int Lleft = j + 1;\n        if (Lleft <= maxLeft[i]) options[id].push_back({varLeft(i), Lleft, LEFT});\n\n        // RIGHT: L = N-j\n        int Lright = N - j;\n        if (Lright <= maxRight[i]) options[id].push_back({varRight(i), Lright, RIGHT});\n\n        // By problem guarantee, at least one option exists.\n        if (options[id].empty()) {\n            // Fallback (should not happen)\n            // choose UP if possible else nothing\n        }\n    }\n\n    auto computeT_from_vals = [&](const vector<int>& val) -> int64_t {\n        int64_t sum = 0;\n        for (int x : val) sum += x;\n        return 2 * sum;\n    };\n\n    mt19937 rng((uint32_t)chrono::steady_clock::now().time_since_epoch().count());\n\n    auto randomInit = [&]() -> void {\n        // assignment arrays in outer scope\n    };\n\n    // Helper: build assignment structures from chosen option indices\n    auto buildFromAssignment = [&](const vector<int>& chosenIdx,\n                                   vector<int>& assignVar,\n                                   vector<int>& assignL,\n                                   vector<vector<int>>& bucket,\n                                   vector<int>& val,\n                                   int64_t& sumVal,\n                                   int64_t& T) {\n        assignVar.assign(M, -1);\n        assignL.assign(M, 0);\n        bucket.assign(V, {});\n        val.assign(V, 0);\n\n        for (int id = 0; id < M; id++) {\n            int idx = chosenIdx[id];\n            auto &op = options[id][idx];\n            assignVar[id] = op.var;\n            assignL[id] = op.L;\n            bucket[op.var].push_back(id);\n        }\n\n        for (int v = 0; v < V; v++) {\n            int mx = 0;\n            for (int id : bucket[v]) mx = max(mx, assignL[id]);\n            val[v] = mx;\n        }\n\n        sumVal = 0;\n        for (int x : val) sumVal += x;\n        T = 2 * sumVal;\n    };\n\n    // Local search step with O(|bucket[oldVar]|) recomputation for oldVar max-after-removal.\n    auto localSearch = [&](vector<int>& assignVar,\n                            vector<int>& assignL,\n                            vector<vector<int>>& bucket,\n                            vector<int>& val,\n                            int64_t& sumVal,\n                            int64_t& bestT,\n                            vector<int>& bestAssignVar,\n                            vector<int>& bestAssignL,\n                            int steps) {\n        // Maintain pos[id] for O(1) deletion from bucket[var]\n        vector<int> pos(M, -1);\n        for (int v = 0; v < V; v++) {\n            for (int k = 0; k < (int)bucket[v].size(); k++) {\n                pos[bucket[v][k]] = k;\n            }\n        }\n\n        auto tryMove = [&](int id, const Option& alt, double temp)->bool{\n            int oldVar = assignVar[id];\n            int newVar = alt.var;\n            if (newVar == oldVar) return false;\n\n            int newL = alt.L;\n\n            // newValOld = max assignL among bucket[oldVar] excluding id\n            int candOld = 0;\n            for (int other : bucket[oldVar]) {\n                if (other == id) continue;\n                candOld = max(candOld, assignL[other]);\n            }\n\n            int candNew = max(val[newVar], newL);\n\n            int deltaSum = (candOld - val[oldVar]) + (candNew - val[newVar]);\n\n            int64_t newSum = sumVal + deltaSum;\n            if (newSum > limitSum) return false;\n\n            if (deltaSum < 0) {\n                // accept\n            } else {\n                // simulated annealing\n                double prob = exp(-(double)deltaSum / temp);\n                uniform_real_distribution<double> U(0.0, 1.0);\n                if (U(rng) >= prob) return false;\n            }\n\n            // Apply move\n            // remove from oldVar\n            int idx = pos[id];\n            int lastId = bucket[oldVar].back();\n            bucket[oldVar][idx] = lastId;\n            pos[lastId] = idx;\n            bucket[oldVar].pop_back();\n\n            // update val oldVar\n            val[oldVar] = candOld;\n\n            // add to newVar\n            pos[id] = (int)bucket[newVar].size();\n            bucket[newVar].push_back(id);\n\n            // update val newVar\n            val[newVar] = candNew;\n\n            // update assignment\n            assignVar[id] = newVar;\n            assignL[id] = newL;\n\n            sumVal = newSum;\n\n            int64_t T = 2 * sumVal;\n            if (T < bestT) {\n                bestT = T;\n                bestAssignVar = assignVar;\n                bestAssignL = assignL;\n            }\n            return true;\n        };\n\n        vector<int> optOrder; optOrder.reserve(M);\n        for (int it = 0; it < steps; it++) {\n            int id = uniform_int_distribution<int>(0, M - 1)(rng);\n            int oldVar = assignVar[id];\n\n            // If there is only 1 option, skip\n            if ((int)options[id].size() <= 1) continue;\n\n            // Compute best alternative among options for this id\n            double temp = 8.0 * (1.0 - (double)it / steps) + 1.0;\n\n            // Evaluate minimal deltaSum option\n            int bestIdx = -1;\n            int bestDelta = INT_MAX;\n            // precompute candOld once (since removing id from oldVar doesn't depend on alt)\n            int candOld = 0;\n            for (int other : bucket[oldVar]) {\n                if (other == id) continue;\n                candOld = max(candOld, assignL[other]);\n            }\n            for (int k = 0; k < (int)options[id].size(); k++) {\n                auto &alt = options[id][k];\n                int newVar = alt.var;\n                if (newVar == oldVar) continue;\n                int newL = alt.L;\n                int candNew = max(val[newVar], newL);\n                int deltaSum = (candOld - val[oldVar]) + (candNew - val[newVar]);\n\n                int64_t newSum = sumVal + deltaSum;\n                if (newSum > limitSum) continue;\n\n                if (deltaSum < bestDelta) {\n                    bestDelta = deltaSum;\n                    bestIdx = k;\n                }\n            }\n\n            if (bestIdx != -1) {\n                // accept best option (annealed inside)\n                tryMove(id, options[id][bestIdx], temp);\n            } else {\n                // random perturbation with small probability\n                if ((it % 20) == 0) {\n                    // choose a random different option\n                    vector<int> diffs;\n                    for (int k = 0; k < (int)options[id].size(); k++) {\n                        if (options[id][k].var != oldVar) diffs.push_back(k);\n                    }\n                    if (!diffs.empty()) {\n                        int kk = diffs[uniform_int_distribution<int>(0, (int)diffs.size()-1)(rng)];\n                        tryMove(id, options[id][kk], temp);\n                    }\n                }\n            }\n        }\n    };\n\n    int64_t bestT = (1LL<<60);\n    vector<int> bestAssignVar, bestAssignL;\n\n    const int RESTARTS = 120;   // increase for more strength\n    const int STEPS = 7000;     // per restart\n\n    // Build initial assignment and run local search repeatedly\n    for (int r = 0; r < RESTARTS; r++) {\n        // choose initial option for each Oni\n        vector<int> chosenIdx(M, 0);\n\n        for (int id = 0; id < M; id++) {\n            auto &opts = options[id];\n            // weighted pick: smaller L more likely, but allow others\n            // weight = (N + 1 - L), at least 1\n            long long total = 0;\n            vector<long long> w(opts.size());\n            for (int k = 0; k < (int)opts.size(); k++) {\n                int L = opts[k].L;\n                long long weight = (long long)(N + 1 - L);\n                if (weight < 1) weight = 1;\n                w[k] = weight;\n                total += weight;\n            }\n            long long rnum = uniform_int_distribution<long long>(0, total - 1)(rng);\n            long long acc = 0;\n            int pick = 0;\n            for (int k = 0; k < (int)opts.size(); k++) {\n                acc += w[k];\n                if (rnum < acc) { pick = k; break; }\n            }\n            // Occasionally force minimal-L for exploitation\n            if ((r % 5) == 0) {\n                int minL = INT_MAX;\n                for (auto &op : opts) minL = min(minL, op.L);\n                vector<int> mins;\n                for (int k = 0; k < (int)opts.size(); k++) if (opts[k].L == minL) mins.push_back(k);\n                pick = mins[uniform_int_distribution<int>(0, (int)mins.size()-1)(rng)];\n            }\n            chosenIdx[id] = pick;\n        }\n\n        vector<int> assignVar, assignL;\n        vector<vector<int>> bucket;\n        vector<int> val;\n        int64_t sumVal = 0, T = 0;\n\n        buildFromAssignment(chosenIdx, assignVar, assignL, bucket, val, sumVal, T);\n\n        if (T > Tlimit) continue;\n\n        // local improvement\n        int64_t curBestT = T;\n        vector<int> curBestVar = assignVar, curBestL = assignL;\n        localSearch(assignVar, assignL, bucket, val, sumVal, curBestT, curBestVar, curBestL, STEPS);\n\n        if (curBestT < bestT) {\n            bestT = curBestT;\n            bestAssignVar = move(curBestVar);\n            bestAssignL = move(curBestL);\n        }\n    }\n\n    // Reconstruct line lengths from best assignment\n    vector<int> val(V, 0);\n    for (int id = 0; id < M; id++) {\n        int v = bestAssignVar[id];\n        val[v] = max(val[v], bestAssignL[id]);\n    }\n\n    // Output operations for each line-direction variable.\n    // UP col j length L: U j L times then D j L times\n    // DOWN col j length L: D j L times then U j L times\n    // LEFT row i length L: L i L times then R i L times\n    // RIGHT row i length L: R i L times then L i L times\n    vector<pair<char,int>> ops;\n    ops.reserve((size_t)bestT);\n\n    for (int j = 0; j < N; j++) {\n        int Lup = val[varUp(j)];\n        for (int k = 0; k < Lup; k++) ops.push_back({'U', j});\n        for (int k = 0; k < Lup; k++) ops.push_back({'D', j});\n\n        int Ldown = val[varDown(j)];\n        for (int k = 0; k < Ldown; k++) ops.push_back({'D', j});\n        for (int k = 0; k < Ldown; k++) ops.push_back({'U', j});\n    }\n    for (int i = 0; i < N; i++) {\n        int Lleft = val[varLeft(i)];\n        for (int k = 0; k < Lleft; k++) ops.push_back({'L', i});\n        for (int k = 0; k < Lleft; k++) ops.push_back({'R', i});\n\n        int Lright = val[varRight(i)];\n        for (int k = 0; k < Lright; k++) ops.push_back({'R', i});\n        for (int k = 0; k < Lright; k++) ops.push_back({'L', i});\n    }\n\n    if ((int64_t)ops.size() > Tlimit) ops.resize((size_t)Tlimit);\n\n    for (auto [ch, p] : ops) {\n        cout << ch << ' ' << p << \"\\n\";\n    }\n    return 0;\n}","ahc044":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int MAXN = 100;\nstatic constexpr int L_CONST = 500000;\n\nstruct State {\n    long long err;\n    array<int, MAXN> cnt{};\n    array<int, MAXN> oddUse{};\n    array<int, MAXN> evenUse{};\n};\n\nstatic inline long long calcErrFromCnt(const array<int, MAXN>& cnt, const array<int, MAXN>& T, int N) {\n    long long e = 0;\n    for (int i = 0; i < N; i++) e += llabs((long long)cnt[i] - (long long)T[i]);\n    return e;\n}\n\nstatic long long simulate(const vector<int>& a, const vector<int>& b,\n                           const array<int, MAXN>& T,\n                           int N, int L,\n                           State &st) {\n    st.cnt.fill(0);\n    st.oddUse.fill(0);\n    st.evenUse.fill(0);\n\n    int x = 0;\n    st.cnt[x] = 1;\n    for (int week = 2; week <= L; week++) {\n        if (st.cnt[x] & 1) {\n            st.oddUse[x]++;\n            x = a[x];\n        } else {\n            st.evenUse[x]++;\n            x = b[x];\n        }\n        st.cnt[x]++;\n    }\n    st.err = calcErrFromCnt(st.cnt, T, N);\n    return st.err;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, L;\n    cin >> N >> L;\n    array<int, MAXN> T{};\n    for (int i = 0; i < N; i++) cin >> T[i];\n\n    // RNG\n    mt19937_64 rng((uint64_t)chrono::high_resolution_clock::now().time_since_epoch().count());\n\n    // Choose destination using residual rem (bigger is more desirable).\n    auto chooseCandidate = [&](const vector<long long>& rem) -> int {\n        const int K = min(25, N);\n        vector<pair<long long,int>> v;\n        v.reserve(N);\n        for (int i = 0; i < N; i++) v.push_back({rem[i], i});\n        nth_element(v.begin(), v.begin() + K, v.end(),\n                    [&](auto &p, auto &q){ return p.first > q.first; });\n        v.resize(K);\n        long long mn = v[0].first, mx = v[0].first;\n        for (auto &p : v) { mn = min(mn, p.first); mx = max(mx, p.first); }\n        long long offset = -mn + 1; // make weights positive\n        vector<long long> w(K);\n        long long sumw = 0;\n        for (int i = 0; i < K; i++) {\n            w[i] = v[i].first + offset;\n            if (w[i] < 1) w[i] = 1;\n            sumw += w[i];\n        }\n        uniform_int_distribution<long long> dist(1, sumw);\n        long long r = dist(rng);\n        for (int i = 0; i < K; i++) {\n            if (r <= w[i]) return v[i].second;\n            r -= w[i];\n        }\n        return v.back().second;\n    };\n\n    // Randomized greedy constructor (similar spirit to yours, but slightly stronger).\n    auto buildMapping = [&](int seedOffset) -> pair<long long, pair<vector<int>, vector<int>>> {\n        // unique seed per build\n        // (We can't reseed rng globally safely; we'll just use it as-is and vary behavior via seedOffset.)\n        vector<int> a(N, -1), b(N, -1);\n        vector<long long> rem(N);\n        for (int i = 0; i < N; i++) rem[i] = T[i];\n\n        array<int, MAXN> cnt{};\n        cnt.fill(0);\n\n        int x = 0;\n        cnt[x] = 1;\n        rem[x]--;\n\n        for (int week = 2; week <= L; week++) {\n            if (cnt[x] & 1) {\n                if (a[x] == -1) {\n                    // small random perturbation by swapping a little preference\n                    int y = chooseCandidate(rem);\n                    if ((seedOffset + week) % 17 == 0) {\n                        // diversify: sometimes pick a random among top 10 by rem\n                        vector<pair<long long,int>> v;\n                        v.reserve(N);\n                        for (int i = 0; i < N; i++) v.push_back({rem[i], i});\n                        sort(v.begin(), v.end(), [&](auto &p, auto &q){ return p.first > q.first; });\n                        int R = min(10, N);\n                        uniform_int_distribution<int> d(0, R-1);\n                        y = v[d(rng)].second;\n                    }\n                    a[x] = y;\n                }\n                x = a[x];\n            } else {\n                if (b[x] == -1) {\n                    int y = chooseCandidate(rem);\n                    if ((seedOffset + week) % 23 == 0) {\n                        vector<pair<long long,int>> v;\n                        v.reserve(N);\n                        for (int i = 0; i < N; i++) v.push_back({rem[i], i});\n                        sort(v.begin(), v.end(), [&](auto &p, auto &q){ return p.first > q.first; });\n                        int R = min(10, N);\n                        uniform_int_distribution<int> d(0, R-1);\n                        y = v[d(rng)].second;\n                    }\n                    b[x] = y;\n                }\n                x = b[x];\n            }\n            cnt[x]++;\n            rem[x]--;\n        }\n\n        for (int i = 0; i < N; i++) {\n            if (a[i] == -1) a[i] = 0;\n            if (b[i] == -1) b[i] = 0;\n        }\n\n        State st;\n        long long err = simulate(a, b, T, N, L, st);\n        return {err, {std::move(a), std::move(b)}};\n    };\n\n    // Time control\n    using Clock = chrono::steady_clock;\n    auto start = Clock::now();\n    auto elapsed = [&]() -> double {\n        return chrono::duration<double>(Clock::now() - start).count();\n    };\n    const double TL = 1.95; // leave a bit of margin\n\n    long long bestErr = (1LL<<62);\n    vector<int> bestA(N, 0), bestB(N, 0);\n\n    // Initial restarts\n    for (int it = 0; it < 40 && elapsed() < TL * 0.35; it++) {\n        auto [err, ab] = buildMapping(it * 100 + 7);\n        if (err < bestErr) {\n            bestErr = err;\n            bestA = std::move(ab.first);\n            bestB = std::move(ab.second);\n        }\n    }\n\n    // Simulated annealing\n    vector<int> curA = bestA, curB = bestB;\n\n    State curSt, newSt;\n    long long curErr = simulate(curA, curB, T, N, L, curSt);\n    bestErr = min(bestErr, curErr);\n\n    // residual arrays (computed from curSt.cnt)\n    auto computeResidualOrder = [&](const State& st) {\n        vector<pair<int,int>> under; under.reserve(N);\n        vector<pair<int,int>> all; all.reserve(N);\n        for (int i = 0; i < N; i++) {\n            int r = T[i] - st.cnt[i];\n            all.push_back({abs(r), i});\n            if (r > 0) under.push_back({r, i});\n        }\n        sort(under.begin(), under.end(), [&](auto &p, auto &q){ return p.first > q.first; });\n        sort(all.begin(), all.end(), [&](auto &p, auto &q){ return p.first > q.first; });\n        return pair<vector<pair<int,int>>, vector<pair<int,int>>>(under, all);\n    };\n\n    vector<pair<int,int>> underList, allAbsList;\n\n    size_t iter = 0;\n    while (elapsed() < TL) {\n        iter++;\n\n        // compute residual lists occasionally\n        if ((iter & 3) == 1) {\n            auto lists = computeResidualOrder(curSt);\n            underList = std::move(lists.first);\n            allAbsList = std::move(lists.second);\n        }\n\n        // choose i with roulette on abs residual (approx)\n        int i = 0;\n        {\n            long long sumAbs = 0;\n            array<long long, MAXN> absw{};\n            for (int k = 0; k < N; k++) {\n                long long r = (long long)T[k] - (long long)curSt.cnt[k];\n                long long w = llabs(r);\n                absw[k] = w;\n                sumAbs += w;\n            }\n            if (sumAbs == 0) {\n                i = uniform_int_distribution<int>(0, N-1)(rng);\n            } else {\n                uniform_int_distribution<long long> dist(1, sumAbs);\n                long long r = dist(rng);\n                for (int k = 0; k < N; k++) {\n                    if (r <= absw[k]) { i = k; break; }\n                    r -= absw[k];\n                }\n            }\n        }\n\n        // choose which edge to modify (a[i] if oddUse dominates)\n        bool changeAedge = true;\n        int ou = curSt.oddUse[i];\n        int eu = curSt.evenUse[i];\n        if (ou + eu == 0) {\n            changeAedge = (uniform_int_distribution<int>(0,1)(rng) == 0);\n        } else {\n            long long r = (long long)uniform_int_distribution<int>(0, 1000000)(rng);\n            changeAedge = (r % (ou + eu) < ou);\n        }\n\n        // choose destination j among underrepresented (prefer positive residual)\n        int curDest = changeAedge ? curA[i] : curB[i];\n\n        int j = curDest;\n        if (!underList.empty()) {\n            int K = min(20, (int)underList.size());\n            // pick among top K with weights proportional to (need+1)\n            long long sumw = 0;\n            for (int t = 0; t < K; t++) sumw += (long long)underList[t].first + 1;\n            uniform_int_distribution<long long> dist(1, sumw);\n            long long r = dist(rng);\n            for (int t = 0; t < K; t++) {\n                long long w = (long long)underList[t].first + 1;\n                if (r <= w) { j = underList[t].second; break; }\n                r -= w;\n            }\n        } else {\n            // fallback: pick from top abs residual indices\n            int K = min(20, (int)allAbsList.size());\n            j = allAbsList[uniform_int_distribution<int>(0, K-1)(rng)].second;\n        }\n\n        // make sure it's actually a change if possible\n        if (N > 1 && j == curDest) {\n            j = (j + 1) % N;\n        }\n\n        // propose change\n        vector<int> aTry = curA;\n        vector<int> bTry = curB;\n\n        if (changeAedge) aTry[i] = j;\n        else bTry[i] = j;\n\n        // occasional double-edge move to escape\n        if (uniform_int_distribution<int>(0, 9)(rng) == 0) {\n            int i2 = allAbsList.empty() ? uniform_int_distribution<int>(0, N-1)(rng)\n                                        : allAbsList[uniform_int_distribution<int>(0, min(30, N)-1)(rng)].second;\n            bool changeA2 = (uniform_int_distribution<int>(0,1)(rng) == 0);\n\n            int dest2 = changeA2 ? aTry[i2] : bTry[i2];\n            int needJ = dest2;\n            if (!underList.empty()) {\n                int K = min(20, (int)underList.size());\n                needJ = underList[uniform_int_distribution<int>(0, K-1)(rng)].second;\n            } else {\n                needJ = allAbsList[uniform_int_distribution<int>(0, min(30, N)-1)(rng)].second;\n            }\n            if (N > 1 && needJ == dest2) needJ = (needJ + 2) % N;\n\n            if (changeA2) aTry[i2] = needJ;\n            else bTry[i2] = needJ;\n        }\n\n        long long newErr = simulate(aTry, bTry, T, N, L, newSt);\n\n        // temperature schedule\n        double frac = elapsed() / TL;\n        double temp = 50000.0 * (1.0 - frac) + 2000.0; // decreases over time\n\n        bool accept = false;\n        if (newErr <= curErr) accept = true;\n        else {\n            double diff = (double)(curErr - newErr); // negative\n            double prob = exp(diff / temp); // exp(-delta/temp)\n            double u = uniform_real_distribution<double>(0.0, 1.0)(rng);\n            if (u < prob) accept = true;\n        }\n\n        if (accept) {\n            curA.swap(aTry);\n            curB.swap(bTry);\n            curErr = newErr;\n            curSt = std::move(newSt);\n            if (curErr < bestErr) {\n                bestErr = curErr;\n                bestA = curA;\n                bestB = curB;\n            }\n        }\n    }\n\n    // Output\n    for (int i = 0; i < N; i++) {\n        cout << bestA[i] << ' ' << bestB[i] << '\\n';\n    }\n    return 0;\n}","ahc045":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\n\nstruct DSU {\n    vector<int> p, r;\n    DSU(int n=0){ init(n); }\n    void init(int n){\n        p.resize(n);\n        r.assign(n,0);\n        iota(p.begin(), p.end(), 0);\n    }\n    int find(int x){ return p[x]==x? x : p[x]=find(p[x]); }\n    bool unite(int a,int b){\n        a=find(a); b=find(b);\n        if(a==b) return false;\n        if(r[a]<r[b]) swap(a,b);\n        p[b]=a;\n        if(r[a]==r[b]) r[a]++;\n        return true;\n    }\n};\n\nstatic inline uint64_t morton2d(uint32_t x, uint32_t y) {\n    // x,y in [0,2^14)\n    uint64_t z = 0;\n    for (uint32_t i = 0; i < 14; i++) {\n        z |= (uint64_t)((x >> i) & 1u) << (2 * i + 1);\n        z |= (uint64_t)((y >> i) & 1u) << (2 * i);\n    }\n    return z;\n}\n\n// rectangle lower bound squared distance between city a and b\nstatic inline ll rectLowerBoundSq(\n    int a, int b,\n    const vector<int>& lx, const vector<int>& rx,\n    const vector<int>& ly, const vector<int>& ry\n) {\n    ll dx = 0;\n    if (rx[a] < lx[b]) dx = (ll)lx[b] - rx[a];\n    else if (rx[b] < lx[a]) dx = (ll)lx[a] - rx[b];\n\n    ll dy = 0;\n    if (ry[a] < ly[b]) dy = (ll)ly[b] - ry[a];\n    else if (ry[b] < ly[a]) dy = (ll)ly[a] - ry[b];\n\n    return dx * dx + dy * dy;\n}\n\nstatic vector<int> reorderNNProxy(\n    const vector<int>& ids,\n    const vector<int>& lx, const vector<int>& rx,\n    const vector<int>& ly, const vector<int>& ry,\n    const vector<uint64_t>& mortonKey\n) {\n    int sz = (int)ids.size();\n    if (sz <= 2) return ids;\n\n    // choose a couple of starts: min/max morton\n    int smin = 0, smax = 0;\n    for (int i = 1; i < sz; i++) {\n        if (mortonKey[ids[i]] < mortonKey[ids[smin]]) smin = i;\n        if (mortonKey[ids[i]] > mortonKey[ids[smax]]) smax = i;\n    }\n\n    auto build = [&](int startPos) {\n        vector<char> used(sz, 0);\n        vector<int> path;\n        path.reserve(sz);\n        int cur = startPos;\n        used[cur] = 1;\n        ll total = 0;\n\n        for (int step = 0; step < sz; step++) {\n            path.push_back(ids[cur]);\n            if (step == sz - 1) break;\n            int best = -1;\n            ll bestW = (1LL<<62);\n            for (int j = 0; j < sz; j++) if (!used[j]) {\n                ll w = rectLowerBoundSq(ids[cur], ids[j], lx, rx, ly, ry);\n                if (w < bestW) bestW = w, best = j;\n            }\n            total += bestW;\n            cur = best;\n            used[cur] = 1;\n        }\n        return pair<ll, vector<int>>(total, path);\n    };\n\n    auto [t1, p1] = build(smin);\n    auto [t2, p2] = build(smax);\n    return (t2 < t1 ? p2 : p1);\n}\n\nstruct CandEdge {\n    int u, v;          // city indices\n    bool oracle;       // primary preference\n    ll w;              // proxy weight\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, Q, L, W;\n    cin >> N >> M >> Q >> L >> W;\n\n    vector<int> G(M);\n    for (int i = 0; i < M; i++) cin >> G[i];\n\n    vector<int> lx(N), rx(N), ly(N), ry(N);\n    for (int i = 0; i < N; i++) cin >> lx[i] >> rx[i] >> ly[i] >> ry[i];\n\n    vector<int> cx_i(N), cy_i(N);\n    vector<uint64_t> mortonKey(N);\n    for (int i = 0; i < N; i++) {\n        cx_i[i] = (lx[i] + rx[i]) / 2;\n        cy_i[i] = (ly[i] + ry[i]) / 2;\n        mortonKey[i] = morton2d((uint32_t)cx_i[i], (uint32_t)cy_i[i]);\n    }\n\n    // Morton sort\n    vector<int> cities(N);\n    iota(cities.begin(), cities.end(), 0);\n    sort(cities.begin(), cities.end(), [&](int a, int b){\n        if (mortonKey[a] != mortonKey[b]) return mortonKey[a] < mortonKey[b];\n        return a < b;\n    });\n\n    // Precompute adjacency proxy along Morton order\n    vector<ll> adjProxy(N-1, 0);\n    for (int i = 0; i < N-1; i++) {\n        adjProxy[i] = rectLowerBoundSq(cities[i], cities[i+1], lx, rx, ly, ry);\n    }\n    vector<ll> pref(N, 0);\n    for (int i = 0; i < N-1; i++) pref[i+1] = pref[i] + adjProxy[i];\n\n    // Greedy segment assignment of group sizes to minimize average adjProxy\n    vector<vector<int>> groupCities(M);\n    int ptr = 0;\n\n    // list of remaining group indices\n    vector<int> rem;\n    rem.reserve(M);\n    for (int i = 0; i < M; i++) rem.push_back(i);\n\n    while (!rem.empty()) {\n        int bestIdx = -1;\n        double bestAvg = 1e300;\n\n        for (int gi : rem) {\n            int sz = G[gi];\n            if (ptr + sz > N) continue;\n            // sum of adjProxy over edges inside segment [ptr..ptr+sz-1]\n            ll sum = pref[ptr + sz - 1] - pref[ptr]; // length sz-1\n            double avg = (sz <= 1 ? 0.0 : (double)sum / (double)(sz-1));\n            if (avg < bestAvg) {\n                bestAvg = avg;\n                bestIdx = gi;\n            }\n        }\n\n        int gi = bestIdx;\n        int sz = G[gi];\n        groupCities[gi].assign(cities.begin() + ptr, cities.begin() + ptr + sz);\n        ptr += sz;\n\n        rem.erase(find(rem.begin(), rem.end(), gi));\n    }\n\n    vector<vector<pair<int,int>>> roads(M);\n    int queriesUsed = 0;\n\n    for (int gi = 0; gi < M; gi++) {\n        auto base = groupCities[gi];\n        int sz = (int)base.size();\n\n        if (sz <= 1) {\n            roads[gi].clear();\n            continue;\n        }\n\n        // Reorder inside group using NN proxy\n        vector<int> ord = reorderNNProxy(base, lx, rx, ly, ry, mortonKey);\n\n        // local index mapping\n        vector<int> local(N, -1);\n        for (int i = 0; i < sz; i++) local[ord[i]] = i;\n\n        // Candidate edges\n        vector<CandEdge> cand;\n        cand.reserve((sz-1) + 6000);\n\n        auto addEdge = [&](int u, int v, bool oracle){\n            if (u == v) return;\n            if (u > v) swap(u, v);\n            ll w = rectLowerBoundSq(u, v, lx, rx, ly, ry);\n            cand.push_back({u, v, oracle, w});\n        };\n\n        // Always add chain edges\n        for (int i = 0; i + 1 < sz; i++) {\n            addEdge(ord[i], ord[i+1], false);\n        }\n\n        // Oracle queries\n        if (sz >= 3 && queriesUsed < Q) {\n            int s = min(L, sz);\n            int step = max(2, s - 1); // s>=3 => step>=2\n            for (int start = 0; start + s <= sz && queriesUsed < Q; start += step) {\n                // query subset ord[start..start+s-1]\n                cout << \"? \" << s;\n                for (int t = 0; t < s; t++) cout << ' ' << ord[start+t];\n                cout << '\\n' << flush;\n\n                // read s-1 edges\n                for (int k = 0; k < s - 1; k++) {\n                    int a, b;\n                    cin >> a >> b;\n                    addEdge(a, b, true);\n                }\n                queriesUsed++;\n            }\n        }\n\n        // Kruskal: prefer oracle edges first, then proxy weight\n        sort(cand.begin(), cand.end(), [&](const CandEdge& e1, const CandEdge& e2){\n            if (e1.oracle != e2.oracle) return e1.oracle > e2.oracle; // oracle first\n            if (e1.w != e2.w) return e1.w < e2.w;\n            if (e1.u != e2.u) return e1.u < e2.u;\n            return e1.v < e2.v;\n        });\n\n        DSU dsu(sz);\n        vector<pair<int,int>> chosen;\n        chosen.reserve(sz-1);\n\n        for (auto &e : cand) {\n            int lu = local[e.u], lv = local[e.v];\n            if (lu < 0 || lv < 0) continue;\n            if (dsu.unite(lu, lv)) {\n                int a = e.u, b = e.v;\n                if (a > b) swap(a, b);\n                chosen.push_back({a, b});\n                if ((int)chosen.size() == sz - 1) break;\n            }\n        }\n\n        // Safety fallback: if somehow not connected, use pure chain\n        if ((int)chosen.size() != sz - 1) {\n            chosen.clear();\n            for (int i = 1; i < sz; i++) {\n                int a = ord[i-1], b = ord[i];\n                if (a > b) swap(a, b);\n                chosen.push_back({a, b});\n            }\n        }\n\n        roads[gi] = std::move(chosen);\n\n        // Output order can be ord (doesn't matter)\n        groupCities[gi] = std::move(ord);\n    }\n\n    cout << \"!\" << '\\n' << flush;\n\n    for (int gi = 0; gi < M; gi++) {\n        auto &vec = groupCities[gi];\n        for (int i = 0; i < (int)vec.size(); i++) {\n            if (i) cout << ' ';\n            cout << vec[i];\n        }\n        cout << '\\n';\n        for (auto [u,v] : roads[gi]) {\n            cout << u << ' ' << v << '\\n';\n        }\n    }\n    cout << flush;\n    return 0;\n}","ahc046":"#include <bits/stdc++.h>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M;\n    cin >> N >> M;\n    vector<pair<int,int>> in(M);\n    for (int i = 0; i < M; i++) cin >> in[i].first >> in[i].second;\n\n    const int Vpos = N * N;\n    auto posIdx = [&](int x, int y) { return x * N + y; };\n    auto inside = [&](int x, int y) { return 0 <= x && x < N && 0 <= y && y < N; };\n\n    // Required targets in order: visit in[1], in[2], ... in[M-1]\n    const int R = M - 1; // 39\n    vector<int> reqPos(R);\n    for (int i = 0; i < R; i++) reqPos[i] = posIdx(in[i+1].first, in[i+1].second);\n\n    int startPos = posIdx(in[0].first, in[0].second);\n\n    // Neighbors for Move/Alter\n    int dx[4] = {-1, 1, 0, 0};\n    int dy[4] = {0, 0, -1, 1};\n    vector<array<int,4>> neigh(Vpos);\n    for (int p = 0; p < Vpos; p++) {\n        int x = p / N, y = p % N;\n        for (int d = 0; d < 4; d++) {\n            int nx = x + dx[d], ny = y + dy[d];\n            neigh[p][d] = inside(nx, ny) ? posIdx(nx, ny) : -1;\n        }\n    }\n\n    static const char DIRCH[4] = {'U','D','L','R'};\n    static const char ACTCH[3] = {'M','S','A'};\n\n    // ---------- Candidate selection ----------\n    // Weight each cell by how many required targets have it adjacent (4-neighborhood).\n    vector<int> weight(Vpos, 0);\n    for (int rp : reqPos) {\n        int x = rp / N, y = rp % N;\n        for (int d = 0; d < 4; d++) {\n            int nx = x + dx[d], ny = y + dy[d];\n            if (inside(nx, ny)) weight[posIdx(nx, ny)]++;\n        }\n    }\n    // Encourage including vicinity of start\n    {\n        int sx = startPos / N, sy = startPos % N;\n        weight[startPos] += 1;\n        for (int d = 0; d < 4; d++) {\n            int nx = sx + dx[d], ny = sy + dy[d];\n            if (inside(nx, ny)) weight[posIdx(nx, ny)] += 1;\n        }\n    }\n\n    // We will allow up to 4 blocks, so keep candidates small.\n    const int CC = 14;     // small enough for fast subset enumeration\n    const int MAXB = 4;    // allow 4 blocks simultaneously\n\n    vector<int> all;\n    all.reserve(Vpos);\n    for (int p = 0; p < Vpos; p++) if (weight[p] > 0) all.push_back(p);\n\n    sort(all.begin(), all.end(), [&](int a, int b){\n        if (weight[a] != weight[b]) return weight[a] > weight[b];\n        return a < b;\n    });\n\n    vector<int> cand;\n    cand.reserve(CC);\n\n    // Always take all weight>=2 first (up to CC)\n    for (int p : all) {\n        if ((int)cand.size() >= CC) break;\n        if (weight[p] >= 2) cand.push_back(p);\n    }\n    // Fill the rest with best remaining\n    for (int p : all) {\n        if ((int)cand.size() >= CC) break;\n        bool ok = true;\n        for (int q : cand) if (q == p) { ok = false; break; }\n        if (ok) cand.push_back(p);\n    }\n    // If still empty (extremely unlikely), fall back\n    if (cand.empty()) cand.push_back(startPos);\n    // If less than CC, pad with some cells near start\n    if ((int)cand.size() < CC) {\n        int sx = startPos / N, sy = startPos % N;\n        vector<int> pad;\n        pad.push_back(startPos);\n        for (int d = 0; d < 4; d++) {\n            int nx = sx + dx[d], ny = sy + dy[d];\n            if (inside(nx, ny)) pad.push_back(posIdx(nx, ny));\n        }\n        for (int p : pad) {\n            if ((int)cand.size() >= CC) break;\n            if (find(cand.begin(), cand.end(), p) == cand.end()) cand.push_back(p);\n        }\n    }\n    if ((int)cand.size() > CC) cand.resize(CC);\n\n    const int C = (int)cand.size(); // <=14\n\n    // Map cell -> candidate index\n    vector<int> candIndexOfCell(Vpos, -1);\n    for (int i = 0; i < C; i++) candIndexOfCell[cand[i]] = i;\n\n    // ---------- Enumerate masks with popcount <= MAXB ----------\n    // For C<=14, subset enumeration over [0..(1<<C)-1] is cheap.\n    const uint32_t LIM = 1u << C;\n    vector<int> idOf(LIM, -1);\n    vector<uint32_t> masks;\n    masks.reserve(2000);\n\n    for (uint32_t m = 0; m < LIM; m++) {\n        if (__builtin_popcount(m) <= MAXB) {\n            idOf[m] = (int)masks.size();\n            masks.push_back(m);\n        }\n    }\n    const int maskCount = (int)masks.size();\n\n    // For each mask: store block cell indices (up to MAXB), pad with -1.\n    vector<array<int,MAXB>> maskBlocks(maskCount);\n    for (int mid = 0; mid < maskCount; mid++) {\n        uint32_t m = masks[mid];\n        array<int,MAXB> arr;\n        arr.fill(-1);\n        int t = 0;\n        for (int i = 0; i < C; i++) if ((m>>i)&1u) {\n            arr[t++] = cand[i];\n            if (t == MAXB) break;\n        }\n        maskBlocks[mid] = arr;\n    }\n\n    // blocked[mid][pos] boolean\n    vector<uint8_t> blocked((size_t)maskCount * Vpos, 0);\n    for (int mid = 0; mid < maskCount; mid++) {\n        for (int bi = 0; bi < MAXB; bi++) {\n            int cell = maskBlocks[mid][bi];\n            if (cell != -1) blocked[(size_t)mid * Vpos + cell] = 1;\n        }\n    }\n    auto isBlocked = [&](int mid, int pos) -> bool {\n        return blocked[(size_t)mid * Vpos + pos] != 0;\n    };\n\n    // toggleNext[mid][ci] -> newMid or -1\n    vector<vector<int16_t>> toggleNext(maskCount, vector<int16_t>(C, -1));\n    for (int mid = 0; mid < maskCount; mid++) {\n        uint32_t m = masks[mid];\n        int pc = __builtin_popcount(m);\n        for (int ci = 0; ci < C; ci++) {\n            bool has = (m >> ci) & 1u;\n            if (has) {\n                uint32_t nm = m & ~(1u << ci);\n                toggleNext[mid][ci] = (idOf[nm] == -1 ? -1 : (int16_t)idOf[nm]);\n            } else {\n                if (pc >= MAXB) continue;\n                uint32_t nm = m | (1u << ci);\n                toggleNext[mid][ci] = (idOf[nm] == -1 ? -1 : (int16_t)idOf[nm]);\n            }\n        }\n    }\n\n    // slideStop[mid][dir][pos] => stop cell index\n    vector<uint16_t> slideStop((size_t)maskCount * 4 * Vpos);\n    auto slideRef = [&](int mid, int dir, int pos) -> uint16_t& {\n        return slideStop[((size_t)mid * 4 + dir) * Vpos + pos];\n    };\n\n    for (int mid = 0; mid < maskCount; mid++) {\n        auto blocks = maskBlocks[mid];\n        for (int pos = 0; pos < Vpos; pos++) {\n            int x = pos / N, y = pos % N;\n\n            for (int dir = 0; dir < 4; dir++) {\n                if (dir == 0) { // U\n                    int best = -1; // max bx < x with same column\n                    for (int bi = 0; bi < MAXB; bi++) if (blocks[bi] != -1) {\n                        int bx = blocks[bi] / N;\n                        int by = blocks[bi] % N;\n                        if (by == y && bx < x) best = max(best, bx);\n                    }\n                    int stopX = (best == -1) ? 0 : best + 1;\n                    slideRef(mid,dir,pos) = (uint16_t)posIdx(stopX, y);\n                } else if (dir == 1) { // D\n                    int best = N; // min bx > x\n                    for (int bi = 0; bi < MAXB; bi++) if (blocks[bi] != -1) {\n                        int bx = blocks[bi] / N;\n                        int by = blocks[bi] % N;\n                        if (by == y && bx > x) best = min(best, bx);\n                    }\n                    int stopX = (best == N) ? (N-1) : best - 1;\n                    slideRef(mid,dir,pos) = (uint16_t)posIdx(stopX, y);\n                } else if (dir == 2) { // L\n                    int best = -1; // max by < y with same row\n                    for (int bi = 0; bi < MAXB; bi++) if (blocks[bi] != -1) {\n                        int bx = blocks[bi] / N;\n                        int by = blocks[bi] % N;\n                        if (bx == x && by < y) best = max(best, by);\n                    }\n                    int stopY = (best == -1) ? 0 : best + 1;\n                    slideRef(mid,dir,pos) = (uint16_t)posIdx(x, stopY);\n                } else { // R\n                    int best = N; // min by > y\n                    for (int bi = 0; bi < MAXB; bi++) if (blocks[bi] != -1) {\n                        int bx = blocks[bi] / N;\n                        int by = blocks[bi] % N;\n                        if (bx == x && by > y) best = min(best, by);\n                    }\n                    int stopY = (best == N) ? (N-1) : best - 1;\n                    slideRef(mid,dir,pos) = (uint16_t)posIdx(x, stopY);\n                }\n            }\n        }\n    }\n\n    // ---------- Global BFS over (k visited, position, mask) ----------\n    // k in [0..R]. k==R means all required targets visited.\n    const int Kst = R + 1; // 40\n    const int TOTAL = Kst * Vpos * maskCount;\n\n    auto sid = [&](int k, int pos, int mid) -> int {\n        return (k * Vpos + pos) * maskCount + mid;\n    };\n\n    vector<int16_t> dist(TOTAL, -1);\n    vector<int> parent(TOTAL, -1);\n    vector<uint8_t> parentCode(TOTAL, 0); // act*4+dir\n\n    int startMid = idOf[0u];\n    int startState = sid(0, startPos, startMid);\n    dist[startState] = 0;\n\n    vector<int> q;\n    q.reserve(30'000'000);\n    q.push_back(startState);\n    size_t head = 0;\n\n    int goalState = -1;\n\n    while (head < q.size()) {\n        int v = q[head++];\n        int dcur = dist[v];\n\n        int mid = v % maskCount;\n        int tmp = v / maskCount;\n        int pos = tmp % Vpos;\n        int k = tmp / Vpos;\n\n        // If already at/over goal, stop (BFS => minimal).\n        if (k == R) {\n            goalState = v;\n            break;\n        }\n        if (isBlocked(mid, pos)) continue; // cannot stand on a block\n\n        for (int dir = 0; dir < 4; dir++) {\n            // 1) Move\n            {\n                int np = neigh[pos][dir];\n                if (np != -1 && !isBlocked(mid, np)) {\n                    int nk = k;\n                    if (nk < R && np == reqPos[nk]) nk++;\n                    int to = sid(nk, np, mid);\n                    if (dist[to] == -1) {\n                        dist[to] = (int16_t)(dcur + 1);\n                        parent[to] = v;\n                        parentCode[to] = (uint8_t)(0 * 4 + dir); // M\n                        q.push_back(to);\n                    }\n                }\n            }\n\n            // 2) Slide\n            {\n                int sp = (int)slideRef(mid, dir, pos);\n                // stop cell should be unblocked; still check:\n                if (!isBlocked(mid, sp)) {\n                    int nk = k;\n                    if (nk < R && sp == reqPos[nk]) nk++;\n                    int to = sid(nk, sp, mid);\n                    if (dist[to] == -1) {\n                        dist[to] = (int16_t)(dcur + 1);\n                        parent[to] = v;\n                        parentCode[to] = (uint8_t)(1 * 4 + dir); // S\n                        q.push_back(to);\n                    }\n                }\n            }\n\n            // 3) Alter (toggle adjacent candidate cell, if it stays within popcount<=MAXB)\n            {\n                int ap = neigh[pos][dir];\n                if (ap != -1) {\n                    int ci = candIndexOfCell[ap];\n                    if (ci != -1) {\n                        int16_t nm = toggleNext[mid][ci];\n                        if (nm != -1) {\n                            int to = sid(k, pos, (int)nm);\n                            if (dist[to] == -1) {\n                                dist[to] = (int16_t)(dcur + 1);\n                                parent[to] = v;\n                                parentCode[to] = (uint8_t)(2 * 4 + dir); // A\n                                q.push_back(to);\n                            }\n                        }\n                    }\n                }\n            }\n        }\n    }\n\n    // Safety fallback: move-only (always fits limit) if somehow no goal found.\n    auto outputMoveOnly = [&]() {\n        vector<pair<char,char>> ans;\n        ans.reserve(2000);\n        int cx = in[0].first, cy = in[0].second;\n        for (int k = 0; k < R; k++) {\n            int tx = in[k+1].first, ty = in[k+1].second;\n            while (cx != tx) {\n                int nx = cx + (tx > cx ? 1 : -1);\n                ans.push_back({'M', (tx > cx) ? 'D' : 'U'});\n                cx = nx;\n            }\n            while (cy != ty) {\n                int ny = cy + (ty > cy ? 1 : -1);\n                ans.push_back({'M', (ty > cy) ? 'R' : 'L'});\n                cy = ny;\n            }\n        }\n        int limit = 2 * N * M;\n        if ((int)ans.size() > limit) ans.resize(limit);\n        for (auto &e : ans) cout << e.first << ' ' << e.second << \"\\n\";\n    };\n\n    if (goalState == -1) {\n        outputMoveOnly();\n        return 0;\n    }\n\n    vector<pair<char,char>> actions;\n    actions.reserve(2000);\n    int cur = goalState;\n    while (cur != startState) {\n        uint8_t code = parentCode[cur];\n        int prev = parent[cur];\n        int act = code / 4;\n        int dir = code % 4;\n        actions.push_back({ACTCH[act], DIRCH[dir]});\n        cur = prev;\n    }\n    reverse(actions.begin(), actions.end());\n\n    int limit = 2 * N * M; // 1600\n    if ((int)actions.size() > limit) {\n        outputMoveOnly();\n        return 0;\n    }\n\n    for (auto &e : actions) {\n        cout << e.first << ' ' << e.second << \"\\n\";\n    }\n    return 0;\n}"}}}