{"model_name":"gpt-5.1-thinking","codes":{"1":{"ahc001":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Rect {\n    int a, b, c, d; // [a,c) x [b,d)\n};\n\nint n;\nvector<int> xs, ys;\nvector<long long> rs;\n\n// Compute total satisfaction for a layout\nlong double compute_score(const vector<Rect> &rect) {\n    long double sum = 0.0L;\n    for (int i = 0; i < n; ++i) {\n        long long w = rect[i].c - rect[i].a;\n        long long h = rect[i].d - rect[i].b;\n        if (w <= 0 || h <= 0) continue; // shouldn't happen\n        long long s = w * h;\n        long double sd = (long double)s;\n        long double rd = (long double)rs[i];\n        long double ratio = sd / rd;\n        if (ratio > 1.0L) ratio = rd / sd; // safety; ideally s <= r always\n        long double pi = 1.0L - (1.0L - ratio) * (1.0L - ratio);\n        sum += pi;\n    }\n    return sum;\n}\n\n// Grow rectangles in the given order, produce layout in 'rect' and return score\nlong double run_order(const vector<int> &order, vector<Rect> &rect) {\n    rect.assign(n, Rect());\n    vector<long long> area(n);\n\n    // Initialize as 1x1 cells at seeds\n    for (int i = 0; i < n; ++i) {\n        rect[i].a = xs[i];\n        rect[i].c = xs[i] + 1;\n        rect[i].b = ys[i];\n        rect[i].d = ys[i] + 1;\n        area[i] = 1;\n    }\n\n    // For each company in the chosen order, grow its rectangle\n    for (int idx_pos = 0; idx_pos < n; ++idx_pos) {\n        int i = order[idx_pos];\n        long long target = rs[i];\n        if (target <= 1) continue; // already at desired area\n\n        while (area[i] < target) {\n            Rect &cur = rect[i];\n            int w = cur.c - cur.a;\n            int h = cur.d - cur.b;\n            if (w <= 0 || h <= 0) break;\n            long long remaining = target - area[i];\n\n            int bestDir = -1;\n            int bestL = 0;\n            long long bestDelta = 0;\n\n            // Direction 0: up (increase d)\n            if (cur.d < 10000 && remaining >= w) {\n                long long L_area = remaining / w;\n                if (L_area > 0) {\n                    int limit = 10000 - cur.d; // board boundary\n                    if (limit > 0) {\n                        for (int j = 0; j < n; ++j) {\n                            if (j == i) continue;\n                            const Rect &s = rect[j];\n                            // x-overlap?\n                            if (s.a >= cur.c || s.c <= cur.a) continue;\n                            // if obstacle is completely below or touching at top\n                            if (cur.d >= s.d) continue;\n                            // now s.d > cur.d\n                            if (s.b <= cur.d) {\n                                // s.b <= d < s.d -> any extension up hits s\n                                limit = 0;\n                                break;\n                            } else {\n                                int cand = s.b - cur.d;\n                                if (cand < limit) {\n                                    limit = cand;\n                                    if (limit <= 0) {\n                                        limit = 0;\n                                        break;\n                                    }\n                                }\n                            }\n                        }\n                        if (limit > 0) {\n                            int L = (int)min<long long>(limit, L_area);\n                            if (L > 0) {\n                                long long delta = 1LL * L * w;\n                                if (delta > bestDelta) {\n                                    bestDelta = delta;\n                                    bestDir = 0;\n                                    bestL = L;\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n\n            // Direction 1: down (decrease b)\n            if (cur.b > 0 && remaining >= w) {\n                long long L_area = remaining / w;\n                if (L_area > 0) {\n                    int limit = cur.b; // distance to 0\n                    if (limit > 0) {\n                        for (int j = 0; j < n; ++j) {\n                            if (j == i) continue;\n                            const Rect &s = rect[j];\n                            // x-overlap?\n                            if (s.a >= cur.c || s.c <= cur.a) continue;\n                            if (s.b >= cur.b) continue; // s is above or touching\n                            // s.b < cur.b\n                            if (s.d > cur.b) {\n                                // s.b < b < s.d, any extension down hits s\n                                limit = 0;\n                                break;\n                            } else {\n                                // s.d <= cur.b\n                                int cand = cur.b - s.d;\n                                if (cand < limit) {\n                                    limit = cand;\n                                    if (limit <= 0) {\n                                        limit = 0;\n                                        break;\n                                    }\n                                }\n                            }\n                        }\n                        if (limit > 0) {\n                            int L = (int)min<long long>(limit, L_area);\n                            if (L > 0) {\n                                long long delta = 1LL * L * w;\n                                if (delta > bestDelta) {\n                                    bestDelta = delta;\n                                    bestDir = 1;\n                                    bestL = L;\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n\n            // Direction 2: left (decrease a)\n            if (cur.a > 0 && remaining >= h) {\n                long long L_area = remaining / h;\n                if (L_area > 0) {\n                    int limit = cur.a; // distance to 0\n                    if (limit > 0) {\n                        for (int j = 0; j < n; ++j) {\n                            if (j == i) continue;\n                            const Rect &s = rect[j];\n                            // y-overlap?\n                            if (s.d <= cur.b || cur.d <= s.b) continue;\n                            if (s.a >= cur.a) {\n                                // s entirely to the right or touching at a\n                                continue;\n                            } else {\n                                // s.a < cur.a\n                                if (s.c > cur.a) {\n                                    // s crosses vertical line x = cur.a,\n                                    // any extension left hits s\n                                    limit = 0;\n                                    break;\n                                } else {\n                                    // s.c <= cur.a, s entirely left\n                                    int cand = cur.a - s.c;\n                                    if (cand < limit) {\n                                        limit = cand;\n                                        if (limit <= 0) {\n                                            limit = 0;\n                                            break;\n                                        }\n                                    }\n                                }\n                            }\n                        }\n                        if (limit > 0) {\n                            int L = (int)min<long long>(limit, L_area);\n                            if (L > 0) {\n                                long long delta = 1LL * L * h;\n                                if (delta > bestDelta) {\n                                    bestDelta = delta;\n                                    bestDir = 2;\n                                    bestL = L;\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n\n            // Direction 3: right (increase c)\n            if (cur.c < 10000 && remaining >= h) {\n                long long L_area = remaining / h;\n                if (L_area > 0) {\n                    int limit = 10000 - cur.c; // board boundary\n                    if (limit > 0) {\n                        for (int j = 0; j < n; ++j) {\n                            if (j == i) continue;\n                            const Rect &s = rect[j];\n                            // y-overlap?\n                            if (s.d <= cur.b || cur.d <= s.b) continue;\n                            if (cur.c >= s.c) {\n                                // s entirely to the left or touching at c\n                                continue;\n                            } else {\n                                // cur.c < s.c\n                                if (s.a <= cur.c) {\n                                    // s crosses vertical line x = cur.c\n                                    limit = 0;\n                                    break;\n                                } else {\n                                    // s.a > cur.c, s entirely to the right\n                                    int cand = s.a - cur.c;\n                                    if (cand < limit) {\n                                        limit = cand;\n                                        if (limit <= 0) {\n                                            limit = 0;\n                                            break;\n                                        }\n                                    }\n                                }\n                            }\n                        }\n                        if (limit > 0) {\n                            int L = (int)min<long long>(limit, L_area);\n                            if (L > 0) {\n                                long long delta = 1LL * L * h;\n                                if (delta > bestDelta) {\n                                    bestDelta = delta;\n                                    bestDir = 3;\n                                    bestL = L;\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n\n            if (bestDir == -1 || bestL <= 0 || bestDelta <= 0) {\n                break; // no further growth possible\n            }\n\n            // Apply the best extension\n            switch (bestDir) {\n                case 0: // up\n                    cur.d += bestL;\n                    break;\n                case 1: // down\n                    cur.b -= bestL;\n                    break;\n                case 2: // left\n                    cur.a -= bestL;\n                    break;\n                case 3: // right\n                    cur.c += bestL;\n                    break;\n            }\n            area[i] += bestDelta;\n        }\n    }\n\n    return compute_score(rect);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> n;\n    xs.resize(n);\n    ys.resize(n);\n    rs.resize(n);\n\n    for (int i = 0; i < n; ++i) {\n        cin >> xs[i] >> ys[i] >> rs[i];\n    }\n\n    vector<int> base(n);\n    iota(base.begin(), base.end(), 0);\n\n    vector<Rect> rect, bestRect;\n    long double bestScore = -1.0L;\n\n    // 1) order by increasing r_i\n    {\n        vector<int> order = base;\n        sort(order.begin(), order.end(), [&](int a, int b) {\n            if (rs[a] != rs[b]) return rs[a] < rs[b];\n            return a < b;\n        });\n        long double sc = run_order(order, rect);\n        if (sc > bestScore) {\n            bestScore = sc;\n            bestRect = rect;\n        }\n    }\n\n    // 2) order by decreasing r_i\n    {\n        vector<int> order = base;\n        sort(order.begin(), order.end(), [&](int a, int b) {\n            if (rs[a] != rs[b]) return rs[a] > rs[b];\n            return a < b;\n        });\n        long double sc = run_order(order, rect);\n        if (sc > bestScore) {\n            bestScore = sc;\n            bestRect = rect;\n        }\n    }\n\n    // 3) order by increasing x\n    {\n        vector<int> order = base;\n        sort(order.begin(), order.end(), [&](int a, int b) {\n            if (xs[a] != xs[b]) return xs[a] < xs[b];\n            return a < b;\n        });\n        long double sc = run_order(order, rect);\n        if (sc > bestScore) {\n            bestScore = sc;\n            bestRect = rect;\n        }\n    }\n\n    // 4) order by increasing y\n    {\n        vector<int> order = base;\n        sort(order.begin(), order.end(), [&](int a, int b) {\n            if (ys[a] != ys[b]) return ys[a] < ys[b];\n            return a < b;\n        });\n        long double sc = run_order(order, rect);\n        if (sc > bestScore) {\n            bestScore = sc;\n            bestRect = rect;\n        }\n    }\n\n    // Randomized orders\n    std::mt19937_64 rng(123456789ULL);\n    int randomRuns = 48; // total ~52 runs including 4 deterministic\n\n    for (int t = 0; t < randomRuns; ++t) {\n        vector<int> order = base;\n        shuffle(order.begin(), order.end(), rng);\n        long double sc = run_order(order, rect);\n        if (sc > bestScore) {\n            bestScore = sc;\n            bestRect = rect;\n        }\n    }\n\n    // Output best layout\n    for (int i = 0; i < n; ++i) {\n        cout << bestRect[i].a << ' ' << bestRect[i].b << ' '\n             << bestRect[i].c << ' ' << bestRect[i].d << '\\n';\n    }\n    return 0;\n}","ahc002":"#include <bits/stdc++.h>\nusing namespace std;\n\n// Fast xorshift RNG\nstruct XorShift64 {\n    uint64_t x;\n    XorShift64() {\n        uint64_t seed = chrono::steady_clock::now().time_since_epoch().count();\n        x = seed ^ (seed << 13);\n    }\n    inline uint64_t next() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return x;\n    }\n    inline uint32_t next_u32() {\n        return static_cast<uint32_t>(next());\n    }\n};\n\nstruct Path {\n    int score;\n    vector<int> seq;\n};\n\n// Globals for simplicity (grid is fixed 50x50)\nconstexpr int H = 50;\nconstexpr int W = 50;\nconstexpr int N = H * W;\nconstexpr int MAX_TILES = 2500;\n\nint tileID[N];                 // tile index for each cell\nint valCell[N];                // score of each cell\nint nei[N][4];                 // neighbors (cell indices)\nint neiCnt[N];                 // number of neighbors for each cell\nint visitedTime[MAX_TILES];    // last iteration stamp when tile was visited\nint startCell;                 // starting cell index\nint maxTileId;                 // max tile id in input\n\nint iterStamp = 0;\nXorShift64 rng;\n\n// Check if tile t is visited in current walk\ninline bool isVisitedTile(int t) {\n    return visitedTime[t] == iterStamp;\n}\n\n// Build one path using a given mode (0,1,2)\nPath build_path(int mode) {\n    ++iterStamp;\n    Path path;\n    path.seq.reserve(N);\n    path.score = 0;\n\n    int cur = startCell;\n    path.seq.push_back(cur);\n    path.score += valCell[cur];\n    visitedTime[tileID[cur]] = iterStamp;\n\n    while (true) {\n        int cand[4];\n        int candCount = 0;\n\n        // Collect candidate neighbors: adjacent cells whose tile is not yet visited\n        for (int k = 0; k < neiCnt[cur]; ++k) {\n            int v = nei[cur][k];\n            int t = tileID[v];\n            if (isVisitedTile(t)) continue; // tile already visited\n            cand[candCount++] = v;\n        }\n\n        if (candCount == 0) break;\n\n        int deg[4];\n\n        // Compute \"forward degree\" for each candidate: how many moves are possible after stepping there\n        for (int i = 0; i < candCount; ++i) {\n            int v = cand[i];\n            int tv = tileID[v];\n            int d = 0;\n            for (int k = 0; k < neiCnt[v]; ++k) {\n                int w = nei[v][k];\n                int tw = tileID[w];\n                if (tw == tv) continue;                 // same tile, won't be allowed after step\n                if (isVisitedTile(tw)) continue;        // tile already used\n                ++d;\n            }\n            deg[i] = d;\n        }\n\n        int chosenIdx = 0;\n\n        if (mode == 0) {\n            // Mode 0: balanced\n            // Prefer class 0 (deg>=2), then 1 (deg==1), then 2 (deg==0)\n            // Within class: smaller deg first, then higher value\n            int bestClass = 3;\n            int bestDeg = 1000;\n            int bestVal = -1;\n            for (int i = 0; i < candCount; ++i) {\n                int d = deg[i];\n                int cls = (d >= 2 ? 0 : (d == 1 ? 1 : 2));\n                int v = cand[i];\n                int pv = valCell[v];\n                bool better = false;\n\n                if (cls < bestClass) {\n                    better = true;\n                } else if (cls == bestClass) {\n                    if (d < bestDeg) {\n                        better = true;\n                    } else if (d == bestDeg) {\n                        if (pv > bestVal) {\n                            better = true;\n                        } else if (pv == bestVal) {\n                            // random tie-break\n                            if (rng.next_u32() & 1u) better = true;\n                        }\n                    }\n                }\n\n                if (better) {\n                    bestClass = cls;\n                    bestDeg = d;\n                    bestVal = pv;\n                    chosenIdx = i;\n                }\n            }\n        } else if (mode == 1) {\n            // Mode 1: pure Warnsdorff (minimize deg), tie by high value\n            int bestDeg = 1000;\n            int bestVal = -1;\n            for (int i = 0; i < candCount; ++i) {\n                int d = deg[i];\n                int v = cand[i];\n                int pv = valCell[v];\n                bool better = false;\n\n                if (d < bestDeg) {\n                    better = true;\n                } else if (d == bestDeg) {\n                    if (pv > bestVal) {\n                        better = true;\n                    } else if (pv == bestVal) {\n                        if (rng.next_u32() & 1u) better = true;\n                    }\n                }\n\n                if (better) {\n                    bestDeg = d;\n                    bestVal = pv;\n                    chosenIdx = i;\n                }\n            }\n        } else {\n            // Mode 2: value-first, tie by larger deg\n            int bestVal = -1;\n            int bestDeg = -1;\n            for (int i = 0; i < candCount; ++i) {\n                int v = cand[i];\n                int pv = valCell[v];\n                int d = deg[i];\n                bool better = false;\n\n                if (pv > bestVal) {\n                    better = true;\n                } else if (pv == bestVal) {\n                    if (d > bestDeg) {\n                        better = true;\n                    } else if (d == bestDeg) {\n                        if (rng.next_u32() & 1u) better = true;\n                    }\n                }\n\n                if (better) {\n                    bestVal = pv;\n                    bestDeg = d;\n                    chosenIdx = i;\n                }\n            }\n        }\n\n        // Small random exploration: 5% chance choose totally random candidate\n        if (candCount > 1 && (rng.next_u32() % 20u == 0u)) {\n            chosenIdx = rng.next_u32() % candCount;\n        }\n\n        int nextCell = cand[chosenIdx];\n        cur = nextCell;\n        path.seq.push_back(cur);\n        path.score += valCell[cur];\n        visitedTime[tileID[cur]] = iterStamp;\n    }\n\n    return path;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int si, sj;\n    if (!(cin >> si >> sj)) {\n        return 0;\n    }\n\n    maxTileId = -1;\n\n    // Read tiles\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            int t;\n            cin >> t;\n            int idx = i * W + j;\n            tileID[idx] = t;\n            if (t > maxTileId) maxTileId = t;\n        }\n    }\n\n    // Read cell values\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            int p;\n            cin >> p;\n            int idx = i * W + j;\n            valCell[idx] = p;\n        }\n    }\n\n    // Precompute neighbors on the grid (4-neighborhood)\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            int idx = i * W + j;\n            int cnt = 0;\n            if (i > 0)    nei[idx][cnt++] = (i - 1) * W + j;\n            if (i + 1 < H) nei[idx][cnt++] = (i + 1) * W + j;\n            if (j > 0)    nei[idx][cnt++] = i * W + (j - 1);\n            if (j + 1 < W) nei[idx][cnt++] = i * W + (j + 1);\n            neiCnt[idx] = cnt;\n        }\n    }\n\n    // Initialize visitedTime\n    for (int i = 0; i <= maxTileId; ++i) visitedTime[i] = 0;\n\n    startCell = si * W + sj;\n\n    auto startTime = chrono::steady_clock::now();\n    const double TIME_LIMIT = 1.9; // seconds\n\n    Path best;\n    best.score = -1;\n\n    int iterations = 0;\n    while (true) {\n        int mode = static_cast<int>(rng.next_u32() % 3u); // 0,1,2\n        Path cur = build_path(mode);\n\n        if (cur.score > best.score ||\n            (cur.score == best.score && cur.seq.size() > best.seq.size())) {\n            best = std::move(cur);\n        }\n\n        ++iterations;\n        if ((iterations & 7) == 0) { // check time every 8 iterations\n            auto now = chrono::steady_clock::now();\n            double elapsed = chrono::duration<double>(now - startTime).count();\n            if (elapsed > TIME_LIMIT) break;\n        }\n    }\n\n    // Convert best.seq (cells) into moves string\n    string ans;\n    ans.reserve(best.seq.size());\n    for (size_t k = 1; k < best.seq.size(); ++k) {\n        int prev = best.seq[k - 1];\n        int cur = best.seq[k];\n        int pi = prev / W, pj = prev % W;\n        int ci = cur / W, cj = cur % W;\n        if (ci == pi) {\n            if (cj == pj + 1) ans.push_back('R');\n            else if (cj == pj - 1) ans.push_back('L');\n        } else if (cj == pj) {\n            if (ci == pi + 1) ans.push_back('D');\n            else if (ci == pi - 1) ans.push_back('U');\n        }\n        // Since we only move along neighbors, no other case should occur.\n    }\n\n    cout << ans << '\\n';\n    return 0;\n}","ahc003":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const int H = 30;\nstatic const int W = 30;\nstatic const int N = H * W;\nstatic const int EH = H * (W - 1);\nstatic const int EV = (H - 1) * W;\nstatic const int E = EH + EV;\nstatic const double INF = 1e100;\n\n// Edge indices for canonical orientations\nint h_id[H][W - 1]; // horizontal: (i,j)-(i,j+1) -> h_id[i][j]\nint v_id[H - 1][W]; // vertical:   (i,j)-(i+1,j) -> v_id[i][j]\n\n// Adjacency: for each vertex, (to, edge_id)\nvector<pair<int,int>> adj[N];\n\n// Edge weights (our estimates) and their randomized version per query\nvector<double> w(E), eff_w(E);\n\n// Dijkstra buffers\ndouble dist_arr[N];\nint prev_v_arr[N];\nint prev_e_arr[N];\n\ninline int vid(int i, int j) {\n    return i * W + j;\n}\n\n// RNG for jitter\nmt19937_64 rng(71236782123ULL);\n\ninline double rand01() {\n    return std::generate_canonical<double, 53>(rng); // [0,1)\n}\n\n// Dijkstra using eff_w, returns path as \"UDLR\"\nstring dijkstra_path(int si, int sj, int ti, int tj, int query_id) {\n    // Jitter decreases over time\n    const double JITTER0 = 0.03;\n    double jitter = JITTER0 * max(0.0, 1.0 - (double)query_id / 800.0);\n    if (jitter < 0.0) jitter = 0.0;\n\n    // Build jittered weights\n    for (int e = 0; e < E; ++e) {\n        double u = 2.0 * rand01() - 1.0; // [-1,1)\n        double factor = 1.0 + jitter * u;\n        if (factor < 0.5) factor = 0.5; // safety\n        eff_w[e] = w[e] * factor;\n        if (eff_w[e] < 1.0) eff_w[e] = 1.0; // strictly positive\n    }\n\n    int s = vid(si, sj);\n    int t = vid(ti, tj);\n\n    // Initialize Dijkstra\n    for (int i = 0; i < N; ++i) {\n        dist_arr[i] = INF;\n        prev_v_arr[i] = -1;\n        prev_e_arr[i] = -1;\n    }\n    dist_arr[s] = 0.0;\n\n    using P = pair<double,int>;\n    priority_queue<P, vector<P>, greater<P>> pq;\n    pq.emplace(0.0, s);\n\n    while (!pq.empty()) {\n        auto [d, u] = pq.top();\n        pq.pop();\n        if (d != dist_arr[u]) continue;\n        if (u == t) break;\n        for (auto &pe : adj[u]) {\n            int v = pe.first;\n            int eid = pe.second;\n            double nd = d + eff_w[eid];\n            if (nd < dist_arr[v]) {\n                dist_arr[v] = nd;\n                prev_v_arr[v] = u;\n                prev_e_arr[v] = eid;\n                pq.emplace(nd, v);\n            }\n        }\n    }\n\n    // Reconstruct path\n    string rev;\n    int v = t;\n    while (v != s) {\n        int u = prev_v_arr[v];\n        if (u == -1) {\n            // Fallback: Manhattan path if something goes wrong\n            rev.clear();\n            int ci = si, cj = sj;\n            while (ci < ti) { rev.push_back('D'); ++ci; }\n            while (ci > ti) { rev.push_back('U'); --ci; }\n            while (cj < tj) { rev.push_back('R'); ++cj; }\n            while (cj > tj) { rev.push_back('L'); --cj; }\n            break;\n        }\n        int ui = u / W, uj = u % W;\n        int vi = v / W, vj = v % W;\n        if (vi == ui) {\n            if (vj == uj + 1) rev.push_back('R');\n            else if (vj == uj - 1) rev.push_back('L');\n        } else if (vj == uj) {\n            if (vi == ui + 1) rev.push_back('D');\n            else if (vi == ui - 1) rev.push_back('U');\n        }\n        v = u;\n    }\n    reverse(rev.begin(), rev.end());\n    return rev;\n}\n\n// Convert move string into list of edge IDs\nvoid path_to_edges(int si, int sj, const string &path, vector<int> &edges) {\n    edges.clear();\n    edges.reserve(path.size());\n    int i = si, j = sj;\n    for (char c : path) {\n        int eid = -1;\n        if (c == 'U') {\n            int ni = i - 1;\n            eid = v_id[ni][j]; // edge between (ni,j) and (ni+1,j)\n            i = ni;\n        } else if (c == 'D') {\n            eid = v_id[i][j]; // edge between (i,j) and (i+1,j)\n            i = i + 1;\n        } else if (c == 'L') {\n            int nj = j - 1;\n            eid = h_id[i][nj]; // edge between (i,nj) and (i,nj+1)\n            j = nj;\n        } else if (c == 'R') {\n            eid = h_id[i][j]; // edge between (i,j) and (i,j+1)\n            j = j + 1;\n        }\n        edges.push_back(eid);\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // Build graph and edge indexing\n    int eid = 0;\n    // Horizontal edges\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W - 1; ++j) {\n            h_id[i][j] = eid;\n            int u = vid(i, j);\n            int v = vid(i, j + 1);\n            adj[u].emplace_back(v, eid);\n            adj[v].emplace_back(u, eid);\n            ++eid;\n        }\n    }\n    // Vertical edges\n    for (int i = 0; i < H - 1; ++i) {\n        for (int j = 0; j < W; ++j) {\n            v_id[i][j] = eid;\n            int u = vid(i, j);\n            int v = vid(i + 1, j);\n            adj[u].emplace_back(v, eid);\n            adj[v].emplace_back(u, eid);\n            ++eid;\n        }\n    }\n\n    // Initialize weights\n    w.assign(E, 5000.0);\n    eff_w.assign(E, 5000.0);\n\n    vector<int> edges;\n    const double ETA = 0.5; // learning rate multiplier\n\n    for (int q = 0; q < 1000; ++q) {\n        int si, sj, ti, tj;\n        if (!(cin >> si >> sj >> ti >> tj)) {\n            return 0; // EOF / error\n        }\n\n        // Compute path\n        string path = dijkstra_path(si, sj, ti, tj, q);\n\n        // Output and flush\n        cout << path << '\\n';\n        cout.flush();\n\n        long long y_ll;\n        if (!(cin >> y_ll)) {\n            return 0; // EOF / error\n        }\n        double y = (double)y_ll;\n\n        // Update weights based on feedback\n        path_to_edges(si, sj, path, edges);\n        int L = (int)edges.size();\n        if (L == 0) continue; // shouldn't happen (distance >= 10)\n\n        double pred = 0.0;\n        for (int e : edges) {\n            pred += w[e];\n        }\n        double error = y - pred;\n\n        double lr = ETA / (double)L;\n        for (int e : edges) {\n            w[e] += lr * error;\n            if (w[e] < 1000.0) w[e] = 1000.0;\n            else if (w[e] > 9000.0) w[e] = 9000.0;\n        }\n    }\n\n    return 0;\n}","ahc004":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const int MAX_N = 20;\nstatic const int MAX_M = 800;\nstatic const int ALPHA = 8;\n\nint N, M;\nvector<string> patterns;\n\n// Aho-Corasick automaton\nstruct Node {\n    int next[ALPHA];\n    int link;\n    vector<int> out;\n    Node() {\n        fill(next, next + ALPHA, -1);\n        link = -1;\n    }\n};\nvector<Node> ac;\n\n// grid\nchar grid[MAX_N][MAX_N];\n\n// pattern occurrence flags\n// store as unsigned char 0/1\nunsigned char row_has[MAX_N][MAX_M];\nunsigned char col_has[MAX_N][MAX_M];\nint pattern_cov_count[MAX_M]; // how many rows+cols contain pattern i\nint current_c = 0;\n\n// scratch for SA\nbool mark_row[MAX_M];\nbool mark_col[MAX_M];\n\n// random generator\nmt19937_64 rng;\n\n/// Map character 'A'..'H' to 0..7\ninline int ch_idx(char c) {\n    return c - 'A';\n}\n\nvoid build_automaton() {\n    ac.clear();\n    ac.emplace_back(); // root\n\n    // build trie\n    for (int i = 0; i < M; ++i) {\n        const string &s = patterns[i];\n        int v = 0;\n        for (char ch : s) {\n            int c = ch_idx(ch);\n            if (ac[v].next[c] == -1) {\n                ac[v].next[c] = (int)ac.size();\n                ac.emplace_back();\n            }\n            v = ac[v].next[c];\n        }\n        ac[v].out.push_back(i);\n    }\n\n    // build failure links\n    queue<int> q;\n    // root link to 0\n    ac[0].link = 0;\n    for (int c = 0; c < ALPHA; ++c) {\n        int u = ac[0].next[c];\n        if (u != -1) {\n            ac[u].link = 0;\n            q.push(u);\n        } else {\n            ac[0].next[c] = 0; // missing edge loops to root\n        }\n    }\n\n    while (!q.empty()) {\n        int v = q.front(); q.pop();\n        int link = ac[v].link;\n        // propagate outputs\n        if (!ac[link].out.empty()) {\n            // append pattern indices from link to v\n            ac[v].out.insert(ac[v].out.end(), ac[link].out.begin(), ac[link].out.end());\n        }\n        for (int c = 0; c < ALPHA; ++c) {\n            int u = ac[v].next[c];\n            if (u != -1) {\n                ac[u].link = ac[link].next[c];\n                q.push(u);\n            } else {\n                ac[v].next[c] = ac[link].next[c];\n            }\n        }\n    }\n}\n\n// scan a line (length len) through AC, mark which patterns appear\ninline void scan_line(const char *s, int len, bool *mark) {\n    int v = 0;\n    for (int i = 0; i < len; ++i) {\n        int c = ch_idx(s[i]);\n        v = ac[v].next[c];\n        const vector<int> &out = ac[v].out;\n        for (int id : out) {\n            if (id < M) mark[id] = true;\n        }\n    }\n}\n\n// recompute one row r and update global counts\nvoid recalc_row(int r) {\n    char line[2 * MAX_N];\n    for (int j = 0; j < N; ++j) line[j] = grid[r][j];\n    for (int j = 0; j < N; ++j) line[N + j] = line[j];\n\n    static bool mark[MAX_M];\n    fill(mark, mark + M, false);\n    scan_line(line, 2 * N, mark);\n\n    for (int i = 0; i < M; ++i) {\n        int oldFlag = row_has[r][i];\n        int newFlag = mark[i] ? 1 : 0;\n        if (oldFlag == newFlag) continue;\n        if (newFlag) {\n            row_has[r][i] = 1;\n            if (pattern_cov_count[i] == 0) current_c++;\n            pattern_cov_count[i]++;\n        } else {\n            row_has[r][i] = 0;\n            pattern_cov_count[i]--;\n            if (pattern_cov_count[i] == 0) current_c--;\n        }\n    }\n}\n\n// recompute one column c and update global counts\nvoid recalc_col(int c) {\n    char line[2 * MAX_N];\n    for (int i = 0; i < N; ++i) line[i] = grid[i][c];\n    for (int i = 0; i < N; ++i) line[N + i] = line[i];\n\n    static bool mark[MAX_M];\n    fill(mark, mark + M, false);\n    scan_line(line, 2 * N, mark);\n\n    for (int i = 0; i < M; ++i) {\n        int oldFlag = col_has[c][i];\n        int newFlag = mark[i] ? 1 : 0;\n        if (oldFlag == newFlag) continue;\n        if (newFlag) {\n            col_has[c][i] = 1;\n            if (pattern_cov_count[i] == 0) current_c++;\n            pattern_cov_count[i]++;\n        } else {\n            col_has[c][i] = 0;\n            pattern_cov_count[i]--;\n            if (pattern_cov_count[i] == 0) current_c--;\n        }\n    }\n}\n\n// pattern \"kick\" move: force-place a random pattern somewhere\nvoid apply_pattern_kick() {\n    uniform_int_distribution<int> pat_dist(0, M - 1);\n    int pid = pat_dist(rng);\n    const string &s = patterns[pid];\n    int len = (int)s.size();\n\n    uniform_int_distribution<int> dir_dist(0, 1);\n    int dir = dir_dist(rng); // 0: horizontal, 1: vertical\n\n    bool rowChanged[MAX_N] = {false};\n    bool colChanged[MAX_N] = {false};\n\n    if (dir == 0) {\n        // horizontal\n        uniform_int_distribution<int> row_dist(0, N - 1);\n        uniform_int_distribution<int> col_dist(0, N - 1);\n        int r = row_dist(rng);\n        int c0 = col_dist(rng);\n\n        for (int t = 0; t < len; ++t) {\n            int cc = c0 + t;\n            if (cc >= N) cc -= N;\n            if (grid[r][cc] != s[t]) {\n                grid[r][cc] = s[t];\n                rowChanged[r] = true;\n                colChanged[cc] = true;\n            }\n        }\n    } else {\n        // vertical\n        uniform_int_distribution<int> row_dist(0, N - 1);\n        uniform_int_distribution<int> col_dist(0, N - 1);\n        int r0 = row_dist(rng);\n        int c = col_dist(rng);\n\n        for (int t = 0; t < len; ++t) {\n            int rr = r0 + t;\n            if (rr >= N) rr -= N;\n            if (grid[rr][c] != s[t]) {\n                grid[rr][c] = s[t];\n                rowChanged[rr] = true;\n                colChanged[c] = true;\n            }\n        }\n    }\n\n    for (int r = 0; r < N; ++r) if (rowChanged[r]) recalc_row(r);\n    for (int c = 0; c < N; ++c) if (colChanged[c]) recalc_col(c);\n}\n\ndouble my_rand_double() {\n    // 53-bit mantissa random double in [0,1)\n    return (rng() >> 11) * (1.0 / (1ull << 53));\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> M;\n    patterns.resize(M);\n    for (int i = 0; i < M; ++i) {\n        cin >> patterns[i];\n    }\n\n    // init RNG\n    uint64_t seed = chrono::high_resolution_clock::now().time_since_epoch().count();\n    rng.seed(seed);\n\n    build_automaton();\n\n    // initial grid: random letters\n    uniform_int_distribution<int> letter_dist(0, ALPHA - 1);\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            grid[i][j] = char('A' + letter_dist(rng));\n        }\n    }\n\n    // constructive pass: greedily place patterns to align with existing letters\n    vector<int> order(M);\n    iota(order.begin(), order.end(), 0);\n    shuffle(order.begin(), order.end(), rng);\n\n    for (int idx = 0; idx < M; ++idx) {\n        int pid = order[idx];\n        const string &s = patterns[pid];\n        int len = (int)s.size();\n\n        int bestScore = -1;\n        int bestDir = 0;\n        int bestR = 0;\n        int bestC = 0;\n\n        // horizontal candidates\n        for (int r = 0; r < N; ++r) {\n            for (int c0 = 0; c0 < N; ++c0) {\n                int score = 0;\n                int c = c0;\n                for (int t = 0; t < len; ++t) {\n                    if (grid[r][c] == s[t]) score++;\n                    c++;\n                    if (c == N) c = 0;\n                }\n                if (score > bestScore) {\n                    bestScore = score;\n                    bestDir = 0;\n                    bestR = r;\n                    bestC = c0;\n                } else if (score == bestScore) {\n                    if (my_rand_double() < 0.5) {\n                        bestScore = score;\n                        bestDir = 0;\n                        bestR = r;\n                        bestC = c0;\n                    }\n                }\n            }\n        }\n\n        // vertical candidates\n        for (int c = 0; c < N; ++c) {\n            for (int r0 = 0; r0 < N; ++r0) {\n                int score = 0;\n                int r = r0;\n                for (int t = 0; t < len; ++t) {\n                    if (grid[r][c] == s[t]) score++;\n                    r++;\n                    if (r == N) r = 0;\n                }\n                if (score > bestScore) {\n                    bestScore = score;\n                    bestDir = 1;\n                    bestR = r0;\n                    bestC = c;\n                } else if (score == bestScore) {\n                    if (my_rand_double() < 0.5) {\n                        bestScore = score;\n                        bestDir = 1;\n                        bestR = r0;\n                        bestC = c;\n                    }\n                }\n            }\n        }\n\n        // apply best placement\n        if (bestDir == 0) {\n            int r = bestR;\n            int c = bestC;\n            for (int t = 0; t < len; ++t) {\n                grid[r][c] = s[t];\n                c++;\n                if (c == N) c = 0;\n            }\n        } else {\n            int c = bestC;\n            int r = bestR;\n            for (int t = 0; t < len; ++t) {\n                grid[r][c] = s[t];\n                r++;\n                if (r == N) r = 0;\n            }\n        }\n    }\n\n    // Initialize evaluation\n    memset(row_has, 0, sizeof(row_has));\n    memset(col_has, 0, sizeof(col_has));\n    fill(pattern_cov_count, pattern_cov_count + M, 0);\n    current_c = 0;\n\n    for (int r = 0; r < N; ++r) recalc_row(r);\n    for (int c = 0; c < N; ++c) recalc_col(c);\n\n    // SA parameters\n    const double TIME_LIMIT = 2.8; // seconds (stay below 3.0)\n    auto start_time = chrono::high_resolution_clock::now();\n    double T0 = 2.0;\n    double T1 = 0.1;\n\n    // keep best grid\n    char best_grid[MAX_N][MAX_N];\n    int best_c = current_c;\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            best_grid[i][j] = grid[i][j];\n\n    int iter = 0;\n    uniform_int_distribution<int> row_dist(0, N - 1);\n    uniform_int_distribution<int> col_dist(0, N - 1);\n\n    while (true) {\n        auto now = chrono::high_resolution_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        if (elapsed > TIME_LIMIT) break;\n        double progress = elapsed / TIME_LIMIT;\n        double T = T0 + (T1 - T0) * progress;\n\n        // occasional pattern kick in early phase\n        if ((iter % 1000 == 0) && (progress < 0.5)) {\n            apply_pattern_kick();\n            if (current_c > best_c) {\n                best_c = current_c;\n                for (int i = 0; i < N; ++i)\n                    for (int j = 0; j < N; ++j)\n                        best_grid[i][j] = grid[i][j];\n            }\n        }\n\n        int r = row_dist(rng);\n        int c = col_dist(rng);\n        char oldCh = grid[r][c];\n\n        char newCh;\n        do {\n            newCh = char('A' + letter_dist(rng));\n        } while (newCh == oldCh);\n\n        // build candidate row line\n        char row_line[2 * MAX_N];\n        for (int j = 0; j < N; ++j) {\n            row_line[j] = (j == c) ? newCh : grid[r][j];\n        }\n        for (int j = 0; j < N; ++j) row_line[N + j] = row_line[j];\n\n        fill(mark_row, mark_row + M, false);\n        scan_line(row_line, 2 * N, mark_row);\n\n        // candidate column line\n        char col_line[2 * MAX_N];\n        for (int i = 0; i < N; ++i) {\n            col_line[i] = (i == r) ? newCh : grid[i][c];\n        }\n        for (int i = 0; i < N; ++i) col_line[N + i] = col_line[i];\n\n        fill(mark_col, mark_col + M, false);\n        scan_line(col_line, 2 * N, mark_col);\n\n        int new_c = current_c;\n        // compute new_c\n        for (int i = 0; i < M; ++i) {\n            int oldCov = pattern_cov_count[i];\n            int newCov = oldCov;\n\n            int oldRow = row_has[r][i];\n            int newRow = mark_row[i] ? 1 : 0;\n            newCov += newRow - oldRow;\n\n            int oldCol = col_has[c][i];\n            int newCol = mark_col[i] ? 1 : 0;\n            newCov += newCol - oldCol;\n\n            if (oldCov <= 0 && newCov > 0) new_c++;\n            else if (oldCov > 0 && newCov <= 0) new_c--;\n        }\n\n        int delta = new_c - current_c;\n        bool accept = false;\n        if (delta >= 0) {\n            accept = true;\n        } else {\n            double prob = exp((double)delta / T);\n            if (prob > my_rand_double()) accept = true;\n        }\n\n        if (accept) {\n            // commit\n            grid[r][c] = newCh;\n            for (int i = 0; i < M; ++i) {\n                int oldCov = pattern_cov_count[i];\n                int newCov = oldCov;\n\n                int oldRow = row_has[r][i];\n                int newRow = mark_row[i] ? 1 : 0;\n                newCov += newRow - oldRow;\n\n                int oldCol = col_has[c][i];\n                int newCol = mark_col[i] ? 1 : 0;\n                newCov += newCol - oldCol;\n\n                pattern_cov_count[i] = newCov;\n                row_has[r][i] = (unsigned char)newRow;\n                col_has[c][i] = (unsigned char)newCol;\n            }\n            current_c = new_c;\n\n            if (current_c > best_c) {\n                best_c = current_c;\n                for (int i = 0; i < N; ++i)\n                    for (int j = 0; j < N; ++j)\n                        best_grid[i][j] = grid[i][j];\n            }\n        }\n\n        ++iter;\n    }\n\n    // Output best grid\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cout << best_grid[i][j];\n        }\n        cout << '\\n';\n    }\n\n    return 0;\n}","ahc005":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Edge {\n    int to;\n    int w;\n};\n\nconst int INF = 1e9;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, si, sj;\n    if (!(cin >> N >> si >> sj)) return 0;\n    vector<string> grid(N);\n    for (int i = 0; i < N; ++i) cin >> grid[i];\n\n    // Map each road cell to an id\n    static int idOf[70][70];\n    int r = 0;\n    vector<pair<int,int>> pos;   // id -> (i,j)\n    vector<int> cost;            // id -> cell cost (5-9)\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (grid[i][j] != '#') {\n                idOf[i][j] = r++;\n                pos.emplace_back(i, j);\n                cost.push_back(grid[i][j] - '0');\n            } else {\n                idOf[i][j] = -1;\n            }\n        }\n    }\n\n    if (r == 0) {\n        // Should not happen (start is road), but just in case\n        cout << \"\\n\";\n        return 0;\n    }\n\n    int startId = idOf[si][sj];\n\n    // Build graph\n    vector<vector<Edge>> G(r);\n    int di[4] = {-1, 1, 0, 0};\n    int dj[4] = {0, 0, -1, 1};\n    for (int id = 0; id < r; ++id) {\n        auto [i, j] = pos[id];\n        for (int d = 0; d < 4; ++d) {\n            int ni = i + di[d], nj = j + dj[d];\n            if (0 <= ni && ni < N && 0 <= nj && nj < N && idOf[ni][nj] != -1) {\n                int v = idOf[ni][nj];\n                G[id].push_back({v, cost[v]});\n            }\n        }\n    }\n\n    // -------- Build fallback DFS route (simple traversal of all cells) --------\n    auto buildDFSRoute = [&]() -> vector<int> {\n        vector<int> route;\n        route.reserve(2 * r + 5);\n        vector<char> used(r, 0);\n        vector<int> st;\n        vector<int> edgeIdx(r, 0);\n\n        route.push_back(startId);\n        used[startId] = 1;\n        st.push_back(startId);\n\n        while (!st.empty()) {\n            int u = st.back();\n            bool advanced = false;\n            auto &ei = edgeIdx[u];\n            while (ei < (int)G[u].size()) {\n                int v = G[u][ei].to;\n                ++ei;\n                if (!used[v]) {\n                    used[v] = 1;\n                    st.push_back(v);\n                    route.push_back(v);\n                    advanced = true;\n                    break;\n                }\n            }\n            if (!advanced) {\n                st.pop_back();\n                if (!st.empty()) {\n                    route.push_back(st.back());\n                }\n            }\n        }\n        return route; // starts and ends at startId\n    };\n\n    auto computeTravelTime = [&](const vector<int> &route) -> long long {\n        long long t = 0;\n        for (int i = 1; i < (int)route.size(); ++i) {\n            t += cost[route[i]];\n        }\n        return t;\n    };\n\n    vector<int> fallbackRoute = buildDFSRoute();\n    long long fallbackTime = computeTravelTime(fallbackRoute);\n\n    // -------- Build horizontal and vertical segments --------\n    vector<vector<int>> rowSegCells;\n    vector<int> rowSegIdOfCell(r, -1);\n\n    for (int i = 0; i < N; ++i) {\n        int j = 0;\n        while (j < N) {\n            if (grid[i][j] == '#') {\n                ++j;\n                continue;\n            }\n            int segIdx = (int)rowSegCells.size();\n            rowSegCells.emplace_back();\n            while (j < N && grid[i][j] != '#') {\n                int id = idOf[i][j];\n                rowSegIdOfCell[id] = segIdx;\n                rowSegCells.back().push_back(id);\n                ++j;\n            }\n        }\n    }\n\n    vector<vector<int>> colSegCells;\n    vector<int> colSegIdOfCell(r, -1);\n\n    for (int j = 0; j < N; ++j) {\n        int i = 0;\n        while (i < N) {\n            if (grid[i][j] == '#') {\n                ++i;\n                continue;\n            }\n            int segIdx = (int)colSegCells.size();\n            colSegCells.emplace_back();\n            while (i < N && grid[i][j] != '#') {\n                int id = idOf[i][j];\n                colSegIdOfCell[id] = segIdx;\n                colSegCells.back().push_back(id);\n                ++i;\n            }\n        }\n    }\n\n    // -------- Precompute visibility (coverage) for *all* cells --------\n    vector<vector<int>> coverageAll(r);\n    for (int id = 0; id < r; ++id) {\n        auto &v = coverageAll[id];\n        auto &rowV = rowSegCells[rowSegIdOfCell[id]];\n        auto &colV = colSegCells[colSegIdOfCell[id]];\n        v.reserve(rowV.size() + colV.size());\n        for (int x : rowV) v.push_back(x);\n        for (int x : colV) v.push_back(x);\n    }\n\n    // -------- Build candidate vantage cells --------\n    vector<char> isIntersection(r, 0);\n    vector<char> hasInterRow(rowSegCells.size(), 0);\n    vector<char> hasInterCol(colSegCells.size(), 0);\n\n    for (int id = 0; id < r; ++id) {\n        auto [i, j] = pos[id];\n        bool hor = false, ver = false;\n        if (j > 0 && idOf[i][j-1] != -1) hor = true;\n        if (j+1 < N && idOf[i][j+1] != -1) hor = true;\n        if (i > 0 && idOf[i-1][j] != -1) ver = true;\n        if (i+1 < N && idOf[i+1][j] != -1) ver = true;\n        if (hor && ver) {\n            isIntersection[id] = 1;\n            hasInterRow[rowSegIdOfCell[id]] = 1;\n            hasInterCol[colSegIdOfCell[id]] = 1;\n        }\n    }\n\n    vector<char> isCandidate(r, 0);\n    vector<int> candidateCells;\n    candidateCells.reserve(r);\n\n    // Intersection cells as candidates\n    for (int id = 0; id < r; ++id) {\n        if (isIntersection[id]) {\n            isCandidate[id] = 1;\n            candidateCells.push_back(id);\n        }\n    }\n\n    // Segments without intersections: pick a midpoint cell as candidate\n    for (int s = 0; s < (int)rowSegCells.size(); ++s) {\n        if (!hasInterRow[s]) {\n            int mid = rowSegCells[s][rowSegCells[s].size() / 2];\n            if (!isCandidate[mid]) {\n                isCandidate[mid] = 1;\n                candidateCells.push_back(mid);\n            }\n        }\n    }\n    for (int s = 0; s < (int)colSegCells.size(); ++s) {\n        if (!hasInterCol[s]) {\n            int mid = colSegCells[s][colSegCells[s].size() / 2];\n            if (!isCandidate[mid]) {\n                isCandidate[mid] = 1;\n                candidateCells.push_back(mid);\n            }\n        }\n    }\n\n    // Ensure start cell is a candidate\n    if (!isCandidate[startId]) {\n        isCandidate[startId] = 1;\n        candidateCells.push_back(startId);\n    }\n\n    // Coverage of candidates\n    int C = (int)candidateCells.size();\n    vector<vector<int>> candCover;\n    candCover.reserve(C);\n    vector<char> cellCovered(r, 0);\n    for (int idx = 0; idx < C; ++idx) {\n        int cell = candidateCells[idx];\n        candCover.push_back(coverageAll[cell]);\n        for (int x : candCover[idx]) cellCovered[x] = 1;\n    }\n\n    // Patch: if some cell is not covered by any candidate, add it as candidate\n    for (int id = 0; id < r; ++id) {\n        if (!cellCovered[id]) {\n            isCandidate[id] = 1;\n            candidateCells.push_back(id);\n            candCover.push_back(coverageAll[id]);\n            for (int x : coverageAll[id]) cellCovered[x] = 1;\n        }\n    }\n    C = (int)candidateCells.size();\n\n    // -------- Greedy set cover on candidates --------\n    vector<int> vantageCells;        // chosen vantage cell ids\n    vantageCells.reserve(C);\n\n    vector<char> coveredCells(r, 0);\n    int coveredCount = 0;\n    vector<char> candSelected(C, 0);\n\n    auto selectCandidate = [&](int idx) {\n        if (candSelected[idx]) return;\n        candSelected[idx] = 1;\n        int cell = candidateCells[idx];\n        vantageCells.push_back(cell);\n        for (int x : candCover[idx]) {\n            if (!coveredCells[x]) {\n                coveredCells[x] = 1;\n                ++coveredCount;\n            }\n        }\n    };\n\n    int startCandIdx = -1;\n    for (int idx = 0; idx < C; ++idx) {\n        if (candidateCells[idx] == startId) {\n            startCandIdx = idx;\n            break;\n        }\n    }\n    if (startCandIdx == -1) {\n        // Should not happen, but safeguard: add start as standalone vantage\n        vantageCells.push_back(startId);\n        for (int x : coverageAll[startId]) {\n            if (!coveredCells[x]) {\n                coveredCells[x] = 1;\n                ++coveredCount;\n            }\n        }\n    } else {\n        selectCandidate(startCandIdx);\n    }\n\n    while (coveredCount < r) {\n        int bestIdx = -1;\n        int bestGain = -1;\n        for (int idx = 0; idx < C; ++idx) {\n            if (candSelected[idx]) continue;\n            int gain = 0;\n            for (int x : candCover[idx]) {\n                if (!coveredCells[x]) ++gain;\n            }\n            if (gain > bestGain) {\n                bestGain = gain;\n                bestIdx = idx;\n            } else if (gain == bestGain && gain > 0 && bestIdx != -1) {\n                // Tie-break: closer (Manhattan) to start\n                int cellNew = candidateCells[idx];\n                int cellBest = candidateCells[bestIdx];\n                auto [ni, nj] = pos[cellNew];\n                auto [bi, bj] = pos[cellBest];\n                int manNew = abs(ni - si) + abs(nj - sj);\n                int manBest = abs(bi - si) + abs(bj - sj);\n                if (manNew < manBest) bestIdx = idx;\n            }\n        }\n\n        if (bestIdx == -1 || bestGain <= 0) {\n            // Safeguard: pick some uncovered cell itself as vantage\n            int uncoveredId = -1;\n            for (int id = 0; id < r; ++id) {\n                if (!coveredCells[id]) {\n                    uncoveredId = id;\n                    break;\n                }\n            }\n            if (uncoveredId == -1) break; // should not\n            vantageCells.push_back(uncoveredId);\n            for (int x : coverageAll[uncoveredId]) {\n                if (!coveredCells[x]) {\n                    coveredCells[x] = 1;\n                    ++coveredCount;\n                }\n            }\n        } else {\n            selectCandidate(bestIdx);\n        }\n    }\n\n    // Remove possible duplicates in vantageCells (shouldn't normally exist)\n    sort(vantageCells.begin(), vantageCells.end());\n    vantageCells.erase(unique(vantageCells.begin(), vantageCells.end()), vantageCells.end());\n\n    // -------- Build main route visiting all vantages (nearest-neighbor via Dijkstra) --------\n    vector<char> isTarget(r, 0);\n    for (int id : vantageCells) isTarget[id] = 1;\n\n    vector<char> visitedTarget(r, 0);\n    int remainingTargets = 0;\n    for (int id : vantageCells) {\n        if (id == startId) {\n            visitedTarget[id] = 1;\n        } else {\n            ++remainingTargets;\n        }\n    }\n\n    vector<int> routeMain;\n    routeMain.reserve(2 * r + 5);\n    routeMain.push_back(startId);\n\n    vector<int> dist(r), prev(r);\n\n    auto dijkstraNearestTarget = [&](int src) -> int {\n        fill(dist.begin(), dist.end(), INF);\n        fill(prev.begin(), prev.end(), -1);\n        priority_queue<pair<int,int>, vector<pair<int,int>>, greater<pair<int,int>>> pq;\n        dist[src] = 0;\n        pq.push({0, src});\n        int target = -1;\n        while (!pq.empty()) {\n            auto [d, u] = pq.top();\n            pq.pop();\n            if (d != dist[u]) continue;\n            if (isTarget[u] && !visitedTarget[u]) {\n                target = u;\n                break;\n            }\n            for (auto &e : G[u]) {\n                int v = e.to;\n                int nd = d + e.w;\n                if (nd < dist[v]) {\n                    dist[v] = nd;\n                    prev[v] = u;\n                    pq.push({nd, v});\n                }\n            }\n        }\n        return target;\n    };\n\n    auto dijkstraToDest = [&](int src, int dest) {\n        fill(dist.begin(), dist.end(), INF);\n        fill(prev.begin(), prev.end(), -1);\n        priority_queue<pair<int,int>, vector<pair<int,int>>, greater<pair<int,int>>> pq;\n        dist[src] = 0;\n        pq.push({0, src});\n        while (!pq.empty()) {\n            auto [d, u] = pq.top();\n            pq.pop();\n            if (d != dist[u]) continue;\n            if (u == dest) break;\n            for (auto &e : G[u]) {\n                int v = e.to;\n                int nd = d + e.w;\n                if (nd < dist[v]) {\n                    dist[v] = nd;\n                    prev[v] = u;\n                    pq.push({nd, v});\n                }\n            }\n        }\n    };\n\n    int curr = startId;\n    while (remainingTargets > 0) {\n        int target = dijkstraNearestTarget(curr);\n        if (target == -1) {\n            break; // should not happen if graph is connected\n        }\n        // reconstruct path from curr to target (excluding curr)\n        vector<int> tmp;\n        int x = target;\n        while (x != curr && x != -1) {\n            tmp.push_back(x);\n            x = prev[x];\n        }\n        for (int i = (int)tmp.size() - 1; i >= 0; --i) {\n            int node = tmp[i];\n            routeMain.push_back(node);\n            if (isTarget[node] && !visitedTarget[node]) {\n                visitedTarget[node] = 1;\n                --remainingTargets;\n            }\n        }\n        curr = target;\n    }\n\n    // Return to start\n    if (curr != startId) {\n        dijkstraToDest(curr, startId);\n        vector<int> tmp;\n        int x = startId;\n        while (x != curr && x != -1) {\n            tmp.push_back(x);\n            x = prev[x];\n        }\n        for (int i = (int)tmp.size() - 1; i >= 0; --i) {\n            routeMain.push_back(tmp[i]);\n        }\n    }\n\n    long long mainTime = computeTravelTime(routeMain);\n\n    // Choose better route (shorter travel time)\n    vector<int> bestRoute;\n    long long bestTime;\n    if (mainTime < fallbackTime) {\n        bestRoute = std::move(routeMain);\n        bestTime = mainTime;\n    } else {\n        bestRoute = std::move(fallbackRoute);\n        bestTime = fallbackTime;\n    }\n\n    // If route has no movement (length 1), add a tiny loop to avoid t=0\n    if ((int)bestRoute.size() == 1) {\n        int u = startId;\n        int v = -1;\n        for (auto &e : G[u]) {\n            v = e.to;\n            break;\n        }\n        if (v != -1) {\n            bestRoute.push_back(v);\n            bestRoute.push_back(u);\n        }\n    }\n\n    // Convert node sequence to direction string\n    string ans;\n    ans.reserve(bestRoute.size());\n    for (int i = 1; i < (int)bestRoute.size(); ++i) {\n        auto [i1, j1] = pos[bestRoute[i-1]];\n        auto [i2, j2] = pos[bestRoute[i]];\n        if (i2 == i1 - 1 && j2 == j1) ans.push_back('U');\n        else if (i2 == i1 + 1 && j2 == j1) ans.push_back('D');\n        else if (j2 == j1 - 1 && i2 == i1) ans.push_back('L');\n        else if (j2 == j1 + 1 && i2 == i1) ans.push_back('R');\n        else {\n            // Should not happen; if it does, output empty (WA rather than UB)\n            // but this should never occur with correct Dijkstra paths.\n        }\n    }\n\n    cout << ans << '\\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    if (!(cin >> N >> M >> K >> R)) {\n        return 0;\n    }\n\n    // Task requirements d[i][k]\n    vector<vector<int>> d(N, vector<int>(K));\n    for (int i = 0; i < N; ++i) {\n        for (int k = 0; k < K; ++k) {\n            cin >> d[i][k];\n        }\n    }\n\n    // Dependencies: u -> v (v depends on u)\n    vector<vector<int>> out(N);\n    vector<int> indeg(N, 0);\n    for (int e = 0; e < R; ++e) {\n        int u, v;\n        cin >> u >> v;\n        --u; --v;\n        out[u].push_back(v);\n        indeg[v]++;\n    }\n\n    // Precompute depth-from-end (longest path length to any sink)\n    vector<int> depth(N, 0);\n    for (int i = N - 1; i >= 0; --i) {\n        int best = 0;\n        for (int v : out[i]) {\n            best = max(best, depth[v] + 1);\n        }\n        depth[i] = best;\n    }\n\n    // Task states\n    const int NOT_STARTED = 0;\n    const int IN_PROGRESS = 1;\n    const int DONE = 2;\n    vector<int> state(N, NOT_STARTED);\n    vector<int> degRem = indeg;\n    int tasksDone = 0;\n\n    // Worker states\n    vector<int> curTask(M, -1);       // current task index or -1\n    vector<int> startDay(M, -1);      // start day of current task\n\n    // Per-worker linear model coefficients a[j][k]\n    vector<vector<double>> a(M, vector<double>(K, 0.5)); // initial slope ~0.5\n    const double GAMMA = 5e-4;\n\n    int day = 0;\n    const int MAX_CAND = 200;\n\n    while (true) {\n        day++;\n\n        // Compute available tasks (not started and all prerequisites done)\n        vector<int> available;\n        if (tasksDone < N) {\n            available.reserve(N);\n            for (int i = 0; i < N; ++i) {\n                if (state[i] == NOT_STARTED && degRem[i] == 0) {\n                    available.push_back(i);\n                }\n            }\n        }\n\n        // Collect free workers\n        vector<int> freeWorkers;\n        freeWorkers.reserve(M);\n        for (int j = 0; j < M; ++j) {\n            if (curTask[j] == -1) {\n                freeWorkers.push_back(j);\n            }\n        }\n\n        // Decide assignments\n        vector<pair<int,int>> assigns; // (worker, task)\n        if (!freeWorkers.empty() && !available.empty()) {\n            // Restrict to top MAX_CAND tasks by depth\n            auto cmpTask = [&](int x, int y) {\n                if (depth[x] != depth[y]) return depth[x] > depth[y];\n                return x < y;\n            };\n\n            int sz = (int)available.size();\n            if (sz > MAX_CAND) {\n                int limit = MAX_CAND;\n                // partial_sort first 'limit' elements\n                partial_sort(available.begin(), available.begin() + limit,\n                             available.end(), cmpTask);\n                available.resize(limit);\n                sz = limit;\n            } else {\n                sort(available.begin(), available.end(), cmpTask);\n            }\n\n            // Build all (worker, task) options with predicted cost\n            struct Option {\n                double cost;\n                int w;\n                int task;\n            };\n            vector<Option> options;\n            options.reserve(freeWorkers.size() * sz);\n\n            for (int widx = 0; widx < (int)freeWorkers.size(); ++widx) {\n                int j = freeWorkers[widx];\n                const auto &aj = a[j];\n                for (int tidx = 0; tidx < sz; ++tidx) {\n                    int ti = available[tidx];\n                    const auto &dv = d[ti];\n                    double w_pred = 0.0;\n                    for (int k = 0; k < K; ++k) {\n                        w_pred += aj[k] * (double)dv[k];\n                    }\n                    if (w_pred < 0.0) w_pred = 0.0;\n                    double t_pred = w_pred;\n                    if (t_pred < 1.0) t_pred = 1.0; // at least 1 day\n                    double cost = t_pred;           // simple cost\n\n                    options.push_back(Option{cost, j, ti});\n                }\n            }\n\n            sort(options.begin(), options.end(),\n                 [](const Option &lhs, const Option &rhs) {\n                     if (lhs.cost != rhs.cost) return lhs.cost < rhs.cost;\n                     if (lhs.w != rhs.w) return lhs.w < rhs.w;\n                     return lhs.task < rhs.task;\n                 });\n\n            vector<char> workerUsed(M, 0);\n            vector<char> taskUsed(N, 0);\n            assigns.reserve(freeWorkers.size());\n\n            for (const auto &opt : options) {\n                if ((int)assigns.size() == (int)freeWorkers.size()) break;\n                int j = opt.w;\n                int ti = opt.task;\n                if (workerUsed[j] || taskUsed[ti]) continue;\n                workerUsed[j] = 1;\n                taskUsed[ti] = 1;\n                assigns.emplace_back(j, ti);\n            }\n        }\n\n        // Output assignments and update worker/task states\n        int m = (int)assigns.size();\n        cout << m;\n        for (auto &p : assigns) {\n            int j = p.first;\n            int ti = p.second;\n            cout << ' ' << (j + 1) << ' ' << (ti + 1);\n            curTask[j] = ti;\n            startDay[j] = day;\n            state[ti] = IN_PROGRESS;\n        }\n        cout << '\\n' << flush;\n\n        // Read completion info\n        int n;\n        if (!(cin >> n)) {\n            return 0;  // input ended unexpectedly\n        }\n        if (n == -1) {\n            break;  // judge signals end\n        }\n\n        vector<int> finishedWorkers;\n        finishedWorkers.reserve(n);\n        for (int i = 0; i < n; ++i) {\n            int f;\n            cin >> f;\n            finishedWorkers.push_back(f - 1); // zero-based\n        }\n\n        // Process completions: update models & DAG\n        for (int idx = 0; idx < n; ++idx) {\n            int j = finishedWorkers[idx];\n            int ti = (j >= 0 && j < M) ? curTask[j] : -1;\n            if (ti < 0) continue;  // should not happen, but just be safe\n\n            int st = startDay[j];\n            if (st < 1) st = day; // safety\n            int t_obs = day - st + 1;\n            if (t_obs < 1) t_obs = 1;\n            int w_obs_int = t_obs - 1;\n            if (w_obs_int < 0) w_obs_int = 0;\n            double w_obs = (double)w_obs_int;\n\n            // Model update: SGD on worker j\n            auto &aj = a[j];\n            const auto &dv = d[ti];\n            double w_pred = 0.0;\n            for (int k = 0; k < K; ++k) {\n                w_pred += aj[k] * (double)dv[k];\n            }\n            double e = w_pred - w_obs;\n\n            // Update always; learning rate is small\n            for (int k = 0; k < K; ++k) {\n                double grad = e * (double)dv[k];\n                aj[k] -= GAMMA * grad;\n                if (aj[k] < 0.0) aj[k] = 0.0;\n                if (aj[k] > 1.0) aj[k] = 1.0;\n            }\n\n            // Mark task completion\n            state[ti] = DONE;\n            tasksDone++;\n            curTask[j] = -1;\n            startDay[j] = -1;\n\n            // Update indegrees of children\n            for (int v : out[ti]) {\n                degRem[v]--;\n            }\n        }\n    }\n\n    return 0;\n}","ahc006":"#include <bits/stdc++.h>\nusing namespace std;\n\n// ---------------------------------------------------------------\n// Types and globals\n// ---------------------------------------------------------------\n\nstruct TourResult {\n    vector<int> tour; // sequence of node indices, starts and ends with 0 (office)\n    int cost;\n};\n\nstatic int distMat[52][52];   // for TSP up to 51 nodes (0..50)\nstatic int nodeX[52], nodeY[52];\n\nconst int OFFICE_X = 400;\nconst int OFFICE_Y = 400;\n\n// RNG: simple xorshift\nstruct XorShift {\n    uint64_t x;\n    XorShift(uint64_t seed = 88172645463393265ULL) { x = seed; }\n    uint64_t next_u64() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return x;\n    }\n    uint32_t next_u32() { return (uint32_t)next_u64(); }\n    uint32_t next_uint(uint32_t mod) { return (uint32_t)(next_u64() % mod); }\n    double next_double() {\n        return (next_u64() >> 11) * (1.0 / (1ULL << 53));\n    }\n};\n\n// Manhattan distance\ninline int manhattan(int x1, int y1, int x2, int y2) {\n    return abs(x1 - x2) + abs(y1 - y2);\n}\n\n// ---------------------------------------------------------------\n// TSP solver: nearest neighbor + 2-opt\n// Points: X[i], Y[i] for i=0..m-1 correspond to nodes 1..m.\n// Node 0 is the office at (400,400).\n// ---------------------------------------------------------------\nTourResult solve_tsp_points(const vector<int>& X, const vector<int>& Y) {\n    int m = (int)X.size();       // number of non-office nodes (<=50)\n    int nNodes = m + 1;          // nodes 0..m\n\n    // Build node coordinates (0: office)\n    nodeX[0] = OFFICE_X;\n    nodeY[0] = OFFICE_Y;\n    for (int i = 1; i <= m; ++i) {\n        nodeX[i] = X[i - 1];\n        nodeY[i] = Y[i - 1];\n    }\n\n    // Distance matrix\n    for (int i = 0; i <= m; ++i) {\n        for (int j = 0; j <= m; ++j) {\n            distMat[i][j] = manhattan(nodeX[i], nodeY[i], nodeX[j], nodeY[j]);\n        }\n    }\n\n    // Nearest neighbor construction, start at office (0)\n    vector<int> tour;\n    tour.reserve(nNodes + 1);\n    vector<char> used(nNodes, 0);\n    int cur = 0;\n    used[0] = 1;\n    tour.push_back(0);\n    for (int step = 0; step < m; ++step) {\n        int best = -1;\n        int bestDist = INT_MAX;\n        for (int v = 1; v <= m; ++v) {\n            if (!used[v]) {\n                int d = distMat[cur][v];\n                if (d < bestDist) {\n                    bestDist = d;\n                    best = v;\n                }\n            }\n        }\n        used[best] = 1;\n        tour.push_back(best);\n        cur = best;\n    }\n    tour.push_back(0); // return to office\n\n    // 2-opt improvement with fixed endpoints\n    int M = (int)tour.size(); // should be m+2\n    bool improved = true;\n    while (improved) {\n        improved = false;\n        for (int i = 1; i <= M - 3; ++i) {\n            int a = tour[i - 1];\n            int b = tour[i];\n            for (int k = i + 1; k <= M - 2; ++k) {\n                int c = tour[k];\n                int d = tour[k + 1];\n                int delta = distMat[a][c] + distMat[b][d]\n                          - distMat[a][b] - distMat[c][d];\n                if (delta < 0) {\n                    reverse(tour.begin() + i, tour.begin() + k + 1);\n                    improved = true;\n                    goto next_iteration;\n                }\n            }\n        }\n        next_iteration:;\n    }\n\n    int cost = 0;\n    for (int i = 0; i < M - 1; ++i) {\n        cost += distMat[tour[i]][tour[i + 1]];\n    }\n\n    TourResult res;\n    res.tour = move(tour);\n    res.cost = cost;\n    return res;\n}\n\n// ---------------------------------------------------------------\n// Evaluate a selection of orders:\n//   selection: vector of indices (0-based) of orders.\n//   Returns total cost, and stores the restaurant and destination tours.\n// ---------------------------------------------------------------\nint evaluate_selection(\n    const vector<int>& selection,\n    const vector<int>& a, const vector<int>& b,\n    const vector<int>& c, const vector<int>& d,\n    vector<int>& outRtour,\n    vector<int>& outDtour\n) {\n    int m = (int)selection.size(); // 50\n    vector<int> XR(m), YR(m), XD(m), YD(m);\n    for (int i = 0; i < m; ++i) {\n        int idx = selection[i];\n        XR[i] = a[idx];\n        YR[i] = b[idx];\n        XD[i] = c[idx];\n        YD[i] = d[idx];\n    }\n\n    TourResult rRes = solve_tsp_points(XR, YR);\n    TourResult dRes = solve_tsp_points(XD, YD);\n\n    outRtour = move(rRes.tour);\n    outDtour = move(dRes.tour);\n\n    return rRes.cost + dRes.cost;\n}\n\n// ---------------------------------------------------------------\n// Main\n// ---------------------------------------------------------------\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    const int N = 1000;\n    vector<int> a(N), b(N), c(N), d(N);\n    for (int i = 0; i < N; ++i) {\n        if (!(cin >> a[i] >> b[i] >> c[i] >> d[i])) {\n            return 0; // in case of incomplete input\n        }\n    }\n\n    // Precompute single-trip scores for initial selection\n    vector<int> single_trip(N);\n    for (int i = 0; i < N; ++i) {\n        int d0R = manhattan(OFFICE_X, OFFICE_Y, a[i], b[i]);\n        int dRD = manhattan(a[i], b[i], c[i], d[i]);\n        int dD0 = manhattan(c[i], d[i], OFFICE_X, OFFICE_Y);\n        single_trip[i] = d0R + dRD + dD0;\n    }\n\n    // Initial selection: 50 orders with smallest single-trip cost\n    vector<int> idx(N);\n    iota(idx.begin(), idx.end(), 0);\n    sort(idx.begin(), idx.end(), [&](int i, int j) {\n        return single_trip[i] < single_trip[j];\n    });\n\n    const int M = 50;\n    vector<int> currentSel(M);\n    for (int i = 0; i < M; ++i) currentSel[i] = idx[i];\n\n    vector<char> inCurrent(N, 0);\n    for (int i = 0; i < M; ++i) inCurrent[currentSel[i]] = 1;\n\n    // Evaluate initial selection\n    vector<int> bestRtour, bestDtour;\n    vector<int> tmpRtour, tmpDtour;\n    int currentCost = evaluate_selection(currentSel, a, b, c, d, tmpRtour, tmpDtour);\n\n    vector<int> bestSel = currentSel;\n    bestRtour = tmpRtour;\n    bestDtour = tmpDtour;\n    int bestCost = currentCost;\n\n    // Hill-climbing on selection\n    XorShift rng(\n        (uint64_t)chrono::high_resolution_clock::now()\n            .time_since_epoch().count()\n    );\n\n    auto startTime = chrono::steady_clock::now();\n    const double TIME_LIMIT = 1.85; // seconds\n\n    int iter = 0;\n    while (true) {\n        ++iter;\n        // Time check every iteration (TSP is relatively expensive anyway)\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - startTime).count();\n        if (elapsed > TIME_LIMIT) break;\n\n        // Pick a random order to remove\n        int posOut = rng.next_uint(M);\n        int outIdx = currentSel[posOut];\n\n        // Pick a random order to insert (not in currentSel)\n        int inIdx;\n        do {\n            inIdx = rng.next_uint(N);\n        } while (inCurrent[inIdx]);\n\n        vector<int> candidateSel = currentSel;\n        candidateSel[posOut] = inIdx;\n\n        int candCost = evaluate_selection(candidateSel, a, b, c, d, tmpRtour, tmpDtour);\n\n        // Greedy acceptance\n        if (candCost <= currentCost) {\n            // Update current selection\n            currentSel.swap(candidateSel);\n            currentCost = candCost;\n            inCurrent[outIdx] = 0;\n            inCurrent[inIdx] = 1;\n        }\n\n        // Track global best\n        if (candCost < bestCost) {\n            bestCost = candCost;\n            bestSel = candidateSel;\n            bestRtour = tmpRtour;\n            bestDtour = tmpDtour;\n        }\n    }\n\n    // Build final path coordinates from bestSel + best tours\n    // bestRtour / bestDtour: node indices 0..M, starting and ending at 0.\n    // Node 0: office, node k>0: order bestSel[k-1].\n    vector<pair<int,int>> path;\n    path.reserve(1 + (int)bestRtour.size() - 1 + (int)bestDtour.size() - 1);\n\n    // Start at office\n    path.emplace_back(OFFICE_X, OFFICE_Y);\n\n    // Restaurants phase\n    for (int i = 1; i < (int)bestRtour.size(); ++i) {\n        int node = bestRtour[i];\n        if (node == 0) {\n            path.emplace_back(OFFICE_X, OFFICE_Y);\n        } else {\n            int orderIdx = bestSel[node - 1];\n            path.emplace_back(a[orderIdx], b[orderIdx]);\n        }\n    }\n\n    // Destinations phase\n    for (int i = 1; i < (int)bestDtour.size(); ++i) {\n        int node = bestDtour[i];\n        if (node == 0) {\n            path.emplace_back(OFFICE_X, OFFICE_Y);\n        } else {\n            int orderIdx = bestSel[node - 1];\n            path.emplace_back(c[orderIdx], d[orderIdx]);\n        }\n    }\n\n    // Output\n    // First line: m and chosen order indices (1-based)\n    cout << M;\n    for (int i = 0; i < M; ++i) {\n        cout << ' ' << (bestSel[i] + 1);\n    }\n    cout << '\\n';\n\n    // Second line: n and route coordinates\n    int n = (int)path.size();\n    cout << n;\n    for (int i = 0; i < n; ++i) {\n        cout << ' ' << path[i].first << ' ' << path[i].second;\n    }\n    cout << '\\n';\n\n    return 0;\n}","ahc007":"#include <bits/stdc++.h>\nusing namespace std;\n\n// ---------- DSU (Union-Find) ----------\nstruct DSU {\n    int n;\n    vector<int> p, r;\n    DSU() {}\n    DSU(int n_) { init(n_); }\n    void init(int n_) {\n        n = n_;\n        p.resize(n);\n        r.assign(n, 0);\n        iota(p.begin(), p.end(), 0);\n    }\n    int find(int x) {\n        if (p[x] == x) return x;\n        return p[x] = find(p[x]);\n    }\n    bool same(int a, int b) {\n        return find(a) == find(b);\n    }\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\n// ---------- XorShift RNG (deterministic) ----------\nstruct XorShift {\n    uint32_t x = 123456789u;\n    uint32_t y = 362436069u;\n    uint32_t z = 521288629u;\n    uint32_t w = 88675123u;\n    uint32_t next() {\n        uint32_t t = x ^ (x << 11);\n        x = y; y = z; z = w;\n        w = w ^ (w >> 19) ^ (t ^ (t >> 8));\n        return w;\n    }\n    uint32_t nextUInt(uint32_t bound) {\n        return next() % bound;\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    const int N = 400;\n    const int M = 1995;\n\n    // ----- Read coordinates -----\n    vector<int> x(N), y(N);\n    for (int i = 0; i < N; i++) {\n        if (!(cin >> x[i] >> y[i])) return 0;  // safety\n    }\n\n    // ----- Read edges (endpoints) -----\n    vector<int> u(M), v(M);\n    for (int i = 0; i < M; i++) {\n        cin >> u[i] >> v[i];\n    }\n\n    // ----- Precompute geometric distances d_i -----\n    vector<int> d(M);\n    for (int i = 0; i < M; i++) {\n        int dx = x[u[i]] - x[v[i]];\n        int dy = y[u[i]] - y[v[i]];\n        double dist = sqrt((double)dx * dx + (double)dy * dy);\n        d[i] = (int)llround(dist);  // round to nearest integer\n    }\n\n    // ----- Compute geometric MST T (on d_i) -----\n    vector<int> idx(M);\n    iota(idx.begin(), idx.end(), 0);\n    sort(idx.begin(), idx.end(), [&](int a, int b) {\n        if (d[a] != d[b]) return d[a] < d[b];\n        return a < b;\n    });\n\n    vector<char> inTree(M, false);\n    DSU dsu0(N);\n    int used = 0;\n    for (int id : idx) {\n        if (!dsu0.same(u[id], v[id])) {\n            dsu0.unite(u[id], v[id]);\n            inTree[id] = true;\n            used++;\n            if (used == N - 1) break;\n        }\n    }\n\n    // ----- Build adjacency of MST T for LCA / max-on-path -----\n    vector<vector<pair<int,int>>> adj(N);\n    adj.assign(N, {});\n    for (int i = 0; i < M; i++) {\n        if (!inTree[i]) continue;\n        adj[u[i]].push_back({v[i], d[i]});\n        adj[v[i]].push_back({u[i], d[i]});\n    }\n\n    // ----- Precompute LCA tables for max edge on path -----\n    const int LOG = 9; // 2^9 = 512 > 400\n    vector<int> depth(N, 0);\n    vector<vector<int>> par(LOG, vector<int>(N));\n    vector<vector<int>> mx(LOG, vector<int>(N));\n\n    // BFS (tree is connected)\n    {\n        queue<int> q;\n        vector<char> vis(N, false);\n        int root = 0;\n        vis[root] = true;\n        depth[root] = 0;\n        par[0][root] = root;\n        mx[0][root] = 0;\n        q.push(root);\n        while (!q.empty()) {\n            int cur = q.front(); q.pop();\n            for (auto [to, w] : adj[cur]) {\n                if (!vis[to]) {\n                    vis[to] = true;\n                    depth[to] = depth[cur] + 1;\n                    par[0][to] = cur;\n                    mx[0][to] = w;\n                    q.push(to);\n                }\n            }\n        }\n        // Fill ancestors\n        for (int k = 1; k < LOG; k++) {\n            for (int vtx = 0; vtx < N; vtx++) {\n                int p = par[k-1][vtx];\n                par[k][vtx] = par[k-1][p];\n                mx[k][vtx] = max(mx[k-1][vtx], mx[k-1][p]);\n            }\n        }\n    }\n\n    auto getMaxOnPath = [&](int a, int b) -> int {\n        if (a == b) return 0;\n        int res = 0;\n        if (depth[a] < depth[b]) swap(a, b);\n        int diff = depth[a] - depth[b];\n        for (int k = 0; k < LOG; k++) {\n            if (diff & (1 << k)) {\n                res = max(res, mx[k][a]);\n                a = par[k][a];\n            }\n        }\n        if (a == b) return res;\n        for (int k = LOG - 1; k >= 0; k--) {\n            if (par[k][a] != par[k][b]) {\n                res = max(res, mx[k][a]);\n                res = max(res, mx[k][b]);\n                a = par[k][a];\n                b = par[k][b];\n            }\n        }\n        // last step to LCA\n        res = max(res, mx[0][a]);\n        res = max(res, mx[0][b]);\n        return res;\n    };\n\n    // ----- Compute H[i] = max d on path in T between u[i], v[i] (for non-tree edges) -----\n    vector<int> H(M, 0);\n    for (int i = 0; i < M; i++) {\n        if (inTree[i]) continue;\n        H[i] = getMaxOnPath(u[i], v[i]); // >0 because u,v are distinct\n        if (H[i] == 0) H[i] = d[i];      // very unlikely, but safety\n    }\n\n    // ----- Compute importance via repeated MSTs with noisy weights -----\n    const int R = 40;  // number of runs\n    vector<int> importance(M, 0);\n    XorShift rng;\n    vector<long long> w(M);\n    vector<int> perm(M);\n    for (int run = 0; run < R; run++) {\n        for (int i = 0; i < M; i++) {\n            // small random noise to break ties in d\n            w[i] = (long long)d[i] * 1000 + (long long)rng.nextUInt(1000);\n            perm[i] = i;\n        }\n        sort(perm.begin(), perm.end(), [&](int a, int b) {\n            if (w[a] != w[b]) return w[a] < w[b];\n            return a < b;\n        });\n        DSU dsu(N);\n        int cnt = 0;\n        for (int id : perm) {\n            if (!dsu.same(u[id], v[id])) {\n                dsu.unite(u[id], v[id]);\n                importance[id]++;\n                cnt++;\n                if (cnt == N - 1) break;\n            }\n        }\n    }\n\n    // ----- Precompute alpha[i] thresholds for non-tree edges -----\n    vector<double> alpha(M, 0.0);\n    const double impFactor = 0.15;  // importance bonus amplitude\n    for (int i = 0; i < M; i++) {\n        if (inTree[i]) continue;  // not used; tree edges accepted unconditionally when needed\n        int Hi = H[i];\n        if (Hi <= 0) Hi = d[i];\n        double ratio = (double)d[i] / (double)Hi; // >=1\n        double baseAlpha;\n        if (ratio >= 3.0) {\n            baseAlpha = 1.0;      // almost never accept\n        } else if (ratio >= 2.5) {\n            baseAlpha = 1.20;\n        } else if (ratio >= 2.0) {\n            baseAlpha = 1.35;\n        } else if (ratio >= 1.5) {\n            baseAlpha = 1.60;\n        } else {\n            baseAlpha = 1.90;\n        }\n        double bonus = impFactor * (double)importance[i] / (double)R;\n        double a = baseAlpha + bonus;\n        if (a > 3.0) a = 3.0;\n        if (a < 1.0) a = 1.0;\n        alpha[i] = a;\n    }\n\n    // ----- Online phase -----\n    DSU dsuCur(N);\n\n    for (int i = 0; i < M; i++) {\n        long long l;\n        if (!(cin >> l)) return 0; // safety\n\n        bool take = false;\n        if (!dsuCur.same(u[i], v[i])) {\n            if (inTree[i]) {\n                // Tree edge: always accept when it connects different components\n                take = true;\n            } else {\n                // Non-tree edge: thresholded acceptance\n                double a = alpha[i];\n                if (a <= 0.0) a = 1.0; // fallback\n                double thr = a * (double)d[i];\n                double maxPossible = 3.0 * (double)d[i];\n                if (thr > maxPossible) thr = maxPossible;\n                if ((double)l <= thr + 1e-9) {\n                    take = true;\n                }\n            }\n        } else {\n            take = false; // would form a cycle; never accept\n        }\n\n        if (take) {\n            dsuCur.unite(u[i], v[i]);\n        }\n\n        cout << (take ? 1 : 0) << '\\n';\n        cout.flush();\n    }\n\n    return 0;\n}","ahc008":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Pet {\n    int x, y, t;\n};\n\nstruct Human {\n    int x, y;\n};\n\nstatic const int H = 30;\nstatic const int W = 30;\n\nbool inside(int x, int y) {\n    return 1 <= x && x <= H && 1 <= y && y <= W;\n}\n\n// Check whether we are allowed to place a wall at (x,y)\nbool canWallCell(int x, int y,\n                 const vector<Pet> &pets,\n                 const vector<Human> &humans) {\n    if (!inside(x, y)) return false;\n    // Cannot place on a human\n    for (const auto &h : humans) {\n        if (h.x == x && h.y == y) return false;\n    }\n    // Cannot place on or adjacent (4-neighbor) to a pet\n    for (const auto &p : pets) {\n        int dx = abs(p.x - x);\n        int dy = abs(p.y - y);\n        if (dx + dy == 0) return false; // same cell\n        if (dx + dy == 1) return false; // 4-neighbor\n    }\n    return true;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    if (!(cin >> N)) {\n        return 0;\n    }\n    vector<Pet> pets(N);\n    for (int i = 0; i < N; i++) {\n        cin >> pets[i].x >> pets[i].y >> pets[i].t;\n    }\n    int M;\n    cin >> M;\n    vector<Human> humans(M);\n    for (int i = 0; i < M; i++) {\n        cin >> humans[i].x >> humans[i].y;\n    }\n\n    // Grid of walls: true means impassable\n    static bool wall[H + 1][W + 1];\n    for (int i = 1; i <= H; i++) {\n        for (int j = 1; j <= W; j++) wall[i][j] = false;\n    }\n\n    // We will build a vertical wall at column WALL_COL\n    const int WALL_COL = 16; // 1-indexed\n    const int WALK_COL = 17; // walkway column for the builder (to the right of the wall)\n    const int builder = 0;   // index of the builder human\n\n    // Row completion tracking for the wall\n    vector<bool> rowWalled(H + 1, false);\n    int walledCount = 0;\n\n    const int T_PRE = 50; // preparation phase duration\n\n    for (int turn = 0; turn < 300; turn++) {\n        string actions(M, '.');\n\n        // Decide actions for humans\n        if (M > 0) {\n            Human &hb = humans[builder];\n            int hx = hb.x;\n            int hy = hb.y;\n\n            char act = '.';\n\n            if (turn < T_PRE) {\n                // Preparation: move builder horizontally to walkway column\n                if (hy < WALK_COL) act = 'R';\n                else if (hy > WALK_COL) act = 'L';\n                else act = '.';\n            } else {\n                // Building phase\n                if (hy != WALK_COL) {\n                    // Ensure builder is on walkway column\n                    if (hy < WALK_COL) act = 'R';\n                    else if (hy > WALK_COL) act = 'L';\n                } else {\n                    // On walkway column; move up/down and place walls\n                    if (walledCount >= H) {\n                        act = '.';\n                    } else {\n                        // Determine if we can wall at current row\n                        bool thisRowUnwalled = !rowWalled[hx];\n\n                        bool canWallHere = false;\n                        if (thisRowUnwalled && !wall[hx][WALL_COL]) {\n                            if (canWallCell(hx, WALL_COL, pets, humans)) {\n                                canWallHere = true;\n                            }\n                        }\n                        if (thisRowUnwalled && canWallHere) {\n                            // Place wall to the left from (hx, WALK_COL) to (hx, WALL_COL)\n                            act = (WALK_COL > WALL_COL ? 'l' : 'r');\n                            wall[hx][WALL_COL] = true;\n                            rowWalled[hx] = true;\n                            walledCount++;\n                        } else {\n                            // Move to nearest other row that still needs a wall\n                            int bestRow = -1;\n                            int bestDist = INT_MAX;\n                            for (int r = 1; r <= H; r++) {\n                                if (!rowWalled[r] && r != hx) {\n                                    int d = abs(r - hx);\n                                    if (d < bestDist) {\n                                        bestDist = d;\n                                        bestRow = r;\n                                    }\n                                }\n                            }\n                            if (bestRow != -1) {\n                                if (bestRow > hx) act = 'D';\n                                else act = 'U';\n                            } else {\n                                // This row is the only remaining one; wait until it becomes safe\n                                act = '.';\n                            }\n                        }\n                    }\n                }\n            }\n            actions[builder] = act;\n        }\n\n        // Other humans\n        for (int i = 0; i < M; i++) {\n            if (i == builder) continue;\n            Human &h = humans[i];\n            char act = '.';\n            if (turn < T_PRE) {\n                // Move off the wall column if initially on it\n                if (h.y == WALL_COL) {\n                    // Simple: move left (safe, because WALL_COL=16, so >=2)\n                    act = 'L';\n                }\n            } else {\n                act = '.';\n            }\n            actions[i] = act;\n        }\n\n        // Output actions and flush\n        cout << actions << '\\n' << flush;\n\n        // Apply wall placements\n        for (int i = 0; i < M; i++) {\n            char c = actions[i];\n            if (c == 'u' || c == 'd' || c == 'l' || c == 'r') {\n                int x = humans[i].x;\n                int y = humans[i].y;\n                int nx = x, ny = y;\n                if (c == 'u') nx = x - 1;\n                else if (c == 'd') nx = x + 1;\n                else if (c == 'l') ny = y - 1;\n                else if (c == 'r') ny = y + 1;\n                if (inside(nx, ny)) {\n                    wall[nx][ny] = true;\n                }\n            }\n        }\n\n        // Apply human moves\n        for (int i = 0; i < M; i++) {\n            char c = actions[i];\n            if (c == 'U' || c == 'D' || c == 'L' || c == 'R') {\n                int x = humans[i].x;\n                int y = humans[i].y;\n                int nx = x, ny = y;\n                if (c == 'U') nx = x - 1;\n                else if (c == 'D') nx = x + 1;\n                else if (c == 'L') ny = y - 1;\n                else if (c == 'R') ny = y + 1;\n                if (inside(nx, ny) && !wall[nx][ny]) {\n                    humans[i].x = nx;\n                    humans[i].y = ny;\n                }\n            }\n        }\n\n        // Read pets' moves\n        vector<string> pmoves(N);\n        for (int i = 0; i < N; i++) {\n            cin >> pmoves[i];\n        }\n\n        // Apply pets' moves\n        for (int i = 0; i < N; i++) {\n            for (char c : pmoves[i]) {\n                int x = pets[i].x;\n                int y = pets[i].y;\n                int nx = x, ny = y;\n                if (c == 'U') nx = x - 1;\n                else if (c == 'D') nx = x + 1;\n                else if (c == 'L') ny = y - 1;\n                else if (c == 'R') ny = y + 1;\n                if (inside(nx, ny) && !wall[nx][ny]) {\n                    pets[i].x = nx;\n                    pets[i].y = ny;\n                } else {\n                    // According to rules, pets won't try to move into walls,\n                    // but we keep this check for safety.\n                }\n            }\n        }\n    }\n\n    return 0;\n}","ahc009":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const int H = 20;\nstatic const int W = 20;\nstatic const int N = H * W;\nstatic const int MAXL = 200;\n\n// DP arrays: indexed by time t (0..L) and cell id (0..N-1)\nstatic double alpha_dp[MAXL + 1][N];\nstatic double beta_dp[MAXL + 1][N];\nstatic double prefix_score[MAXL + 1];\n\n// Direction mapping\nint dirIdx[256];\nchar dirChar[4] = {'U', 'D', 'L', 'R'};\n\n// Precomputed next cell for each dir and cell (ignoring absorbing goal)\nint nextCell[4][N];\n\n// Globals for convenience\nint start_id, goal_id;\nint L = MAXL;\ndouble forget_p;\n\n// BFS to get an initial shortest path from start to goal\nvector<char> bfs_shortest_path(const vector<string> &h, const vector<string> &v) {\n    // Build adjacency list\n    vector<vector<int>> g(N);\n    auto cell_id = [](int r, int c) { return r * W + c; };\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            int id = cell_id(i, j);\n            if (j + 1 < W && h[i][j] == '0') {\n                int nid = cell_id(i, j + 1);\n                g[id].push_back(nid);\n                g[nid].push_back(id);\n            }\n            if (i + 1 < H && v[i][j] == '0') {\n                int nid = cell_id(i + 1, j);\n                g[id].push_back(nid);\n                g[nid].push_back(id);\n            }\n        }\n    }\n\n    vector<int> prev(N, -1);\n    vector<char> prevMove(N, '?');\n    queue<int> q;\n    q.push(start_id);\n    prev[start_id] = start_id;\n\n    auto decode_dir = [](int from, int to) {\n        int r1 = from / W, c1 = from % W;\n        int r2 = to   / W, c2 = to   % W;\n        if (r2 == r1 && c2 == c1 + 1) return 'R';\n        if (r2 == r1 && c2 == c1 - 1) return 'L';\n        if (r2 == r1 + 1 && c2 == c1) return 'D';\n        if (r2 == r1 - 1 && c2 == c1) return 'U';\n        return 'U'; // should not happen\n    };\n\n    while (!q.empty()) {\n        int vtx = q.front(); q.pop();\n        if (vtx == goal_id) break;\n        for (int to : g[vtx]) {\n            if (prev[to] == -1) {\n                prev[to] = vtx;\n                prevMove[to] = decode_dir(vtx, to);\n                q.push(to);\n            }\n        }\n    }\n\n    // Reconstruct path\n    vector<char> path;\n    int cur = goal_id;\n    while (cur != start_id) {\n        int p = prev[cur];\n        if (p == -1) {\n            // Should not happen given problem guarantees connectivity\n            break;\n        }\n        path.push_back(prevMove[cur]);\n        cur = p;\n    }\n    reverse(path.begin(), path.end());\n    if (path.empty()) {\n        // In extremely unlikely case start==goal (not in constraints),\n        // just return dummy single move.\n        path.push_back('R');\n    }\n    return path;\n}\n\n// Recompute alpha, beta, prefix for a given route s[1..L]; return E[S]\ndouble evaluate_route(const vector<char> &s) {\n    const double p = forget_p;\n    const double q = 1.0 - p;\n\n    // Forward DP (alpha + prefix_score)\n    memset(alpha_dp, 0, sizeof(alpha_dp));\n    alpha_dp[0][start_id] = 1.0;\n    prefix_score[0] = 0.0;\n\n    for (int t = 1; t <= L; ++t) {\n        memset(alpha_dp[t], 0, sizeof(alpha_dp[t]));\n        prefix_score[t] = prefix_score[t - 1];\n        int d = dirIdx[(unsigned char)s[t]];\n        double reward_weight = 401.0 - t;\n        for (int id = 0; id < N; ++id) {\n            double px = alpha_dp[t - 1][id];\n            if (px == 0.0) continue;\n\n            if (id == goal_id) {\n                // Already at goal: stay there\n                alpha_dp[t][id] += px;\n                continue;\n            }\n\n            int dest = nextCell[d][id];\n\n            if (dest == id) {\n                // Wall or blocked; stay with prob 1\n                alpha_dp[t][id] += px;\n            } else if (dest == goal_id) {\n                // Can reach goal\n                double moved = px * q;\n                prefix_score[t] += moved * reward_weight;\n                alpha_dp[t][goal_id] += moved;\n                alpha_dp[t][id] += px * p; // stayed due to forgetting\n            } else {\n                // Normal move\n                double moved = px * q;\n                alpha_dp[t][dest] += moved;\n                alpha_dp[t][id]   += px * p;\n            }\n        }\n    }\n\n    double total_score = prefix_score[L];\n\n    // Backward DP (beta)\n    // beta_dp[L][*] = 0 already by memset\n    memset(beta_dp, 0, sizeof(beta_dp));\n    // We only need row L initialized to 0; others will be overwritten\n    for (int id = 0; id < N; ++id) beta_dp[L][id] = 0.0;\n\n    for (int t = L - 1; t >= 0; --t) {\n        int d = dirIdx[(unsigned char)s[t + 1]];\n        double reward_weight = 401.0 - (t + 1);\n        for (int id = 0; id < N; ++id) {\n            if (id == goal_id) {\n                beta_dp[t][id] = 0.0;\n                continue;\n            }\n            int dest = nextCell[d][id];\n            double immediate = 0.0;\n            double future = 0.0;\n            if (dest == id) {\n                // Wall: always stay\n                future = beta_dp[t + 1][id];\n            } else if (dest == goal_id) {\n                // May reach goal\n                immediate = q * reward_weight;\n                future = p * beta_dp[t + 1][id]; // stay due to forgetting\n            } else {\n                future = q * beta_dp[t + 1][dest] + p * beta_dp[t + 1][id];\n            }\n            beta_dp[t][id] = immediate + future;\n        }\n    }\n\n    // As a sanity check, beta_dp[0][start_id] should be ~= total_score.\n    // We don't assert due to floating point noise, but they should match.\n    return total_score;\n}\n\n// Compute E[S] if only step k is changed to newDir, everything else fixed\ndouble score_if_change_step(const vector<char> &s, int k, char newDir) {\n    const double p = forget_p;\n    const double q = 1.0 - p;\n\n    double res = prefix_score[k - 1];\n    int d = dirIdx[(unsigned char)newDir];\n\n    for (int id = 0; id < N; ++id) {\n        double px = alpha_dp[k - 1][id];\n        if (px == 0.0) continue;\n        if (id == goal_id) {\n            // Already at goal, no further reward\n            continue;\n        }\n        int dest = nextCell[d][id];\n        if (dest == id) {\n            // Wall: stay, no immediate reward\n            res += px * beta_dp[k][id];\n        } else if (dest == goal_id) {\n            // Can reach goal\n            res += px * q * (401.0 - k);     // immediate\n            res += px * p * beta_dp[k][id];  // stayed due to forgetting\n        } else {\n            // Normal move\n            res += px * (q * beta_dp[k][dest] + p * beta_dp[k][id]);\n        }\n    }\n    return res;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int si, sj, ti, tj;\n    if (!(cin >> si >> sj >> ti >> tj >> forget_p)) {\n        return 0;\n    }\n    vector<string> h(H), v(H - 1);\n    for (int i = 0; i < H; ++i) cin >> h[i];\n    for (int i = 0; i < H - 1; ++i) cin >> v[i];\n\n    start_id = si * W + sj;\n    goal_id  = ti * W + tj;\n\n    // Direction indices\n    dirIdx['U'] = 0;\n    dirIdx['D'] = 1;\n    dirIdx['L'] = 2;\n    dirIdx['R'] = 3;\n\n    // Precompute nextCell for each dir and cell (static, ignoring absorbing)\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            int id = i * W + j;\n            // Up\n            if (i == 0 || v[i - 1][j] == '1') nextCell[0][id] = id;\n            else                              nextCell[0][id] = (i - 1) * W + j;\n            // Down\n            if (i == H - 1 || v[i][j] == '1') nextCell[1][id] = id;\n            else                               nextCell[1][id] = (i + 1) * W + j;\n            // Left\n            if (j == 0 || h[i][j - 1] == '1') nextCell[2][id] = id;\n            else                              nextCell[2][id] = i * W + (j - 1);\n            // Right\n            if (j == W - 1 || h[i][j] == '1') nextCell[3][id] = id;\n            else                              nextCell[3][id] = i * W + (j + 1);\n        }\n    }\n\n    // Initial route: repeat shortest BFS path\n    vector<char> base_path = bfs_shortest_path(h, v);\n    int D = (int)base_path.size();\n    if (D <= 0) {\n        base_path.push_back('R');\n        D = 1;\n    }\n\n    vector<char> route(L + 1); // 1-based\n    for (int t = 1; t <= L; ++t) {\n        route[t] = base_path[(t - 1) % D];\n    }\n\n    // Evaluate initial route\n    double bestScore = evaluate_route(route);\n\n    // Hill-climbing\n    const int MAX_ITER = 5;\n    const double EPS = 1e-9;\n    for (int iter = 0; iter < MAX_ITER; ++iter) {\n        bool improved_any = false;\n        for (int k = 1; k <= L; ++k) {\n            char orig = route[k];\n            char bestDir = orig;\n            double currScore = bestScore;\n\n            // Try all alternative directions\n            for (int di = 0; di < 4; ++di) {\n                char c = dirChar[di];\n                if (c == orig) continue;\n                double newScore = score_if_change_step(route, k, c);\n                if (newScore > currScore + EPS) {\n                    currScore = newScore;\n                    bestDir = c;\n                }\n            }\n\n            if (bestDir != orig) {\n                route[k] = bestDir;\n                bestScore = evaluate_route(route); // recompute DP arrays + score\n                improved_any = true;\n            }\n        }\n        if (!improved_any) break;\n    }\n\n    // Output final route as a string\n    string out;\n    out.reserve(L);\n    for (int t = 1; t <= L; ++t) out.push_back(route[t]);\n    cout << out << '\\n';\n\n    return 0;\n}","ahc010":"#include <bits/stdc++.h>\nusing namespace std;\n\nconstexpr int N = 30;\nconstexpr int M = 30;\nconstexpr int TOT_STATES = N * M * 4;\n\n// Global tables\nint baseTile[N][M];\nint curTile[N][M];\nint curRot[N][M];\nint bestLocalRot[N][M];\n\nint rotTable[8][4];      // rotTable[t][r] = tile type after rotating t r times CCW\nint toTbl[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};\nbool useSide[8][4];\n\nbool visitedState[TOT_STATES];\nint  pathId[TOT_STATES];\nint  pathStep[TOT_STATES];\n\nint di[4] = {0, -1, 0, 1};  // left, up, right, down\nint dj[4] = {-1, 0, 1, 0};\n\nmt19937_64 rng(20240131);\n\n// Encode (i, j, d) into index\ninline int encodeState(int i, int j, int d) {\n    return ((i * M) + j) * 4 + d;\n}\n\n// Compute localScore for current curTile\nint computeLocalScore() {\n    int connected = 0;\n    int boundaryUsed = 0;\n\n    // Horizontal internal edges\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < M - 1; ++j) {\n            int t1 = curTile[i][j];\n            int t2 = curTile[i][j + 1];\n            if (useSide[t1][2] && useSide[t2][0]) connected++;\n        }\n    }\n    // Vertical internal edges\n    for (int i = 0; i < N - 1; ++i) {\n        for (int j = 0; j < M; ++j) {\n            int t1 = curTile[i][j];\n            int t2 = curTile[i + 1][j];\n            if (useSide[t1][3] && useSide[t2][1]) connected++;\n        }\n    }\n    // Boundary sides\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < M; ++j) {\n            int t = curTile[i][j];\n            if (i == 0     && useSide[t][1]) boundaryUsed++;\n            if (i == N - 1 && useSide[t][3]) boundaryUsed++;\n            if (j == 0     && useSide[t][0]) boundaryUsed++;\n            if (j == M - 1 && useSide[t][2]) boundaryUsed++;\n        }\n    }\n\n    return connected * 2 - boundaryUsed;\n}\n\n// Incremental change in localScore when (i, j) changes from oldT to newT\ninline int deltaLocalScoreTile(int i, int j, int oldT, int newT) {\n    int deltaConn = 0;\n    int deltaBound = 0;\n\n    // Up side\n    if (i > 0) {\n        int neighbor = curTile[i - 1][j];\n        bool neighborUsedDown = useSide[neighbor][3];\n        bool oldUsedUp = useSide[oldT][1];\n        bool newUsedUp = useSide[newT][1];\n        int before = (oldUsedUp && neighborUsedDown) ? 1 : 0;\n        int after  = (newUsedUp && neighborUsedDown) ? 1 : 0;\n        deltaConn += after - before;\n    } else {\n        bool oldUsedUp = useSide[oldT][1];\n        bool newUsedUp = useSide[newT][1];\n        deltaBound += (newUsedUp ? 1 : 0) - (oldUsedUp ? 1 : 0);\n    }\n\n    // Down side\n    if (i < N - 1) {\n        int neighbor = curTile[i + 1][j];\n        bool neighborUsedUp = useSide[neighbor][1];\n        bool oldUsedDown = useSide[oldT][3];\n        bool newUsedDown = useSide[newT][3];\n        int before = (oldUsedDown && neighborUsedUp) ? 1 : 0;\n        int after  = (newUsedDown && neighborUsedUp) ? 1 : 0;\n        deltaConn += after - before;\n    } else {\n        bool oldUsedDown = useSide[oldT][3];\n        bool newUsedDown = useSide[newT][3];\n        deltaBound += (newUsedDown ? 1 : 0) - (oldUsedDown ? 1 : 0);\n    }\n\n    // Left side\n    if (j > 0) {\n        int neighbor = curTile[i][j - 1];\n        bool neighborUsedRight = useSide[neighbor][2];\n        bool oldUsedLeft = useSide[oldT][0];\n        bool newUsedLeft = useSide[newT][0];\n        int before = (oldUsedLeft && neighborUsedRight) ? 1 : 0;\n        int after  = (newUsedLeft && neighborUsedRight) ? 1 : 0;\n        deltaConn += after - before;\n    } else {\n        bool oldUsedLeft = useSide[oldT][0];\n        bool newUsedLeft = useSide[newT][0];\n        deltaBound += (newUsedLeft ? 1 : 0) - (oldUsedLeft ? 1 : 0);\n    }\n\n    // Right side\n    if (j < M - 1) {\n        int neighbor = curTile[i][j + 1];\n        bool neighborUsedLeft = useSide[neighbor][0];\n        bool oldUsedRight = useSide[oldT][2];\n        bool newUsedRight = useSide[newT][2];\n        int before = (oldUsedRight && neighborUsedLeft) ? 1 : 0;\n        int after  = (newUsedRight && neighborUsedLeft) ? 1 : 0;\n        deltaConn += after - before;\n    } else {\n        bool oldUsedRight = useSide[oldT][2];\n        bool newUsedRight = useSide[newT][2];\n        deltaBound += (newUsedRight ? 1 : 0) - (oldUsedRight ? 1 : 0);\n    }\n\n    return deltaConn * 2 - deltaBound;\n}\n\n// Compute true score: product of lengths of two longest loops\nint computeTrueScore() {\n    fill(visitedState, visitedState + TOT_STATES, false);\n    fill(pathId, pathId + TOT_STATES, 0);\n    // pathStep doesn't need initialization; we only read it where pathId is current\n\n    int best1 = 0, best2 = 0;\n    int curPathId = 1;\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < M; ++j) {\n            int t = curTile[i][j];\n            for (int d = 0; d < 4; ++d) {\n                int idx0 = encodeState(i, j, d);\n                if (visitedState[idx0]) continue;\n                if (toTbl[t][d] == -1) {\n                    visitedState[idx0] = true;\n                    continue;\n                }\n\n                int x = i, y = j, dir = d;\n                int pathLen = 0;\n                ++curPathId;\n\n                while (true) {\n                    int idx = encodeState(x, y, dir);\n                    visitedState[idx] = true;\n                    pathId[idx] = curPathId;\n                    pathStep[idx] = pathLen;\n\n                    int tt = curTile[x][y];\n                    int d2 = toTbl[tt][dir];\n                    if (d2 == -1) break;\n\n                    int nx = x + di[d2];\n                    int ny = y + dj[d2];\n                    if (nx < 0 || nx >= N || ny < 0 || ny >= M) break;\n\n                    int nd = (d2 + 2) & 3;\n                    ++pathLen;\n                    int idxNext = encodeState(nx, ny, nd);\n\n                    if (pathId[idxNext] == curPathId) {\n                        // Found a cycle\n                        int len = pathLen - pathStep[idxNext];\n                        if (len >= best1) {\n                            best2 = best1;\n                            best1 = len;\n                        } else if (len > best2) {\n                            best2 = len;\n                        }\n                        break;\n                    }\n                    if (visitedState[idxNext]) {\n                        // Merges into previously explored path\n                        break;\n                    }\n\n                    x = nx;\n                    y = ny;\n                    dir = nd;\n                }\n            }\n        }\n    }\n\n    if (best2 == 0) return 0;\n    return best1 * best2;\n}\n\n// Random double in [0, 1)\ninline double randDouble() {\n    // Use 53 bits of randomness\n    return (double)(rng() >> 11) * (1.0 / (1ULL << 53));\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // Precompute rotTable and useSide\n    int rotMap[8] = {1, 2, 3, 0, 5, 4, 7, 6};\n    for (int t = 0; t < 8; ++t) {\n        rotTable[t][0] = t;\n        for (int r = 1; r < 4; ++r) {\n            rotTable[t][r] = rotMap[ rotTable[t][r - 1] ];\n        }\n    }\n    for (int t = 0; t < 8; ++t) {\n        for (int d = 0; d < 4; ++d) {\n            useSide[t][d] = (toTbl[t][d] != -1);\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 < M; ++j) {\n            baseTile[i][j] = s[j] - '0';\n        }\n    }\n\n    auto timeStart = chrono::steady_clock::now();\n    const double GLOBAL_TIME_LIMIT = 1.9;  // seconds\n\n    // Stage 1: multi-start greedy local search on local score\n    const int MAX_RUNS = 5;\n    const int MAX_PASS = 10;\n\n    vector<int> order(N * M);\n    iota(order.begin(), order.end(), 0);\n\n    int bestLocalScore = numeric_limits<int>::min();\n\n    for (int run = 0; run < MAX_RUNS; ++run) {\n        // Random initial rotations\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < M; ++j) {\n                int r = (int)(rng() & 3ULL);  // 0..3\n                curRot[i][j] = r;\n                curTile[i][j] = rotTable[ baseTile[i][j] ][r];\n            }\n        }\n\n        int curLocalScore = computeLocalScore();\n\n        for (int pass = 0; pass < MAX_PASS; ++pass) {\n            bool changed = false;\n            shuffle(order.begin(), order.end(), rng);\n\n            for (int idx : order) {\n                int i = idx / M;\n                int j = idx % M;\n\n                int oldRot = curRot[i][j];\n                int oldT = curTile[i][j];\n\n                int bestDelta = 0;\n                int bestR = oldRot;\n                int bestT = oldT;\n\n                // Try all 4 rotations\n                for (int r = 0; r < 4; ++r) {\n                    if (r == oldRot) continue;\n                    int newT = rotTable[ baseTile[i][j] ][r];\n                    int delta = deltaLocalScoreTile(i, j, oldT, newT);\n                    if (delta > bestDelta) {\n                        bestDelta = delta;\n                        bestR = r;\n                        bestT = newT;\n                    }\n                }\n\n                if (bestDelta > 0) {\n                    curRot[i][j] = bestR;\n                    curTile[i][j] = bestT;\n                    curLocalScore += bestDelta;\n                    changed = true;\n                }\n            }\n\n            if (!changed) break;\n        }\n\n        if (curLocalScore > bestLocalScore) {\n            bestLocalScore = curLocalScore;\n            for (int i = 0; i < N; ++i)\n                for (int j = 0; j < M; ++j)\n                    bestLocalRot[i][j] = curRot[i][j];\n        }\n\n        double elapsed = chrono::duration<double>(chrono::steady_clock::now() - timeStart).count();\n        if (elapsed > GLOBAL_TIME_LIMIT * 0.6) {\n            // Leave enough time for Stage 2\n            break;\n        }\n    }\n\n    // Start Stage 2 from best local configuration\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < M; ++j) {\n            curRot[i][j] = bestLocalRot[i][j];\n            curTile[i][j] = rotTable[ baseTile[i][j] ][curRot[i][j]];\n        }\n    }\n\n    // Collect 4/5 tiles for Stage 2\n    vector<pair<int,int>> crossCells;\n    crossCells.reserve(N * M / 2);\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < M; ++j) {\n            int t0 = baseTile[i][j];\n            if (t0 == 4 || t0 == 5) {\n                crossCells.emplace_back(i, j);\n            }\n        }\n    }\n\n    // Stage 2: SA on true score, only rotate tiles 4/5 (toggle parity)\n    int finalRot[N][M];\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < M; ++j)\n            finalRot[i][j] = curRot[i][j];\n\n    if (!crossCells.empty()) {\n        double elapsed = chrono::duration<double>(chrono::steady_clock::now() - timeStart).count();\n        double timeRemain = GLOBAL_TIME_LIMIT - elapsed;\n        if (timeRemain > 0.05) {  // leave some margin\n            int curScore = computeTrueScore();\n            int bestScore = curScore;\n            for (int i = 0; i < N; ++i)\n                for (int j = 0; j < M; ++j)\n                    finalRot[i][j] = curRot[i][j];\n\n            const int MAX_SA_ITERS = 2000;\n            double T0 = 500.0;\n            double T1 = 5.0;\n\n            auto saStart = chrono::steady_clock::now();\n            for (int iter = 0; iter < MAX_SA_ITERS; ++iter) {\n                double nowTime = chrono::duration<double>(chrono::steady_clock::now() - timeStart).count();\n                if (nowTime > GLOBAL_TIME_LIMIT) break;\n                double saElapsed = chrono::duration<double>(chrono::steady_clock::now() - saStart).count();\n                double progress = min(1.0, saElapsed / max(1e-9, timeRemain));\n                double T = T0 + (T1 - T0) * progress;\n\n                auto [ci, cj] = crossCells[ rng() % crossCells.size() ];\n\n                int oldRot = curRot[ci][cj];\n                int newRot = oldRot ^ 1;  // toggle parity: switch between type 4 and 5\n\n                int oldT = curTile[ci][cj];\n                int newT = rotTable[ baseTile[ci][cj] ][newRot];\n\n                curRot[ci][cj] = newRot;\n                curTile[ci][cj] = newT;\n\n                int newScore = computeTrueScore();\n                int diff = newScore - curScore;\n\n                bool accept = false;\n                if (diff >= 0) {\n                    accept = true;\n                } else {\n                    double prob = exp((double)diff / T);\n                    if (randDouble() < prob) accept = true;\n                }\n\n                if (accept) {\n                    curScore = newScore;\n                    if (newScore > bestScore) {\n                        bestScore = newScore;\n                        for (int i = 0; i < N; ++i)\n                            for (int j = 0; j < M; ++j)\n                                finalRot[i][j] = curRot[i][j];\n                    }\n                } else {\n                    // revert\n                    curRot[ci][cj] = oldRot;\n                    curTile[ci][cj] = oldT;\n                }\n            }\n        }\n    }\n\n    // Output final rotations\n    string out;\n    out.reserve(N * M);\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < M; ++j) {\n            int r = finalRot[i][j] & 3;\n            out.push_back(char('0' + r));\n        }\n    }\n    cout << out << '\\n';\n\n    return 0;\n}","ahc011":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const int MAXN = 10;\n\n// Board representation\nstruct Board {\n    unsigned char a[MAXN][MAXN];\n};\n\nint N, T;\n\n// Directions for graph connectivity (Up, Right, Down, Left)\nconst int DX[4]   = {-1, 0, 1, 0};\nconst int DY[4]   = { 0, 1, 0,-1};\n// Bit masks corresponding to U,R,D,L in that order\nconst int MASK[4] = {2, 4, 8, 1};\n// Opposite directions\nconst int OPP[4]  = {2, 3, 0, 1};\n\nstruct EvalRes {\n    int bestTree;   // largest tree component size\n    int bestConn;   // largest connected component size\n};\n\n// Evaluate the board: largest tree and largest connected component\nEvalRes evaluate(const Board &B) {\n    static bool vis[MAXN][MAXN];\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            vis[i][j] = false;\n\n    int bestTree = 0;\n    int bestConn = 0;\n\n    int qx[MAXN * MAXN];\n    int qy[MAXN * MAXN];\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (B.a[i][j] == 0 || vis[i][j]) continue;\n\n            int v = 0; // vertices in this component\n            int e = 0; // edges in this component\n\n            int head = 0, tail = 0;\n            vis[i][j] = true;\n            qx[tail] = i;\n            qy[tail] = j;\n            ++tail;\n\n            while (head < tail) {\n                int x = qx[head];\n                int y = qy[head];\n                ++head;\n\n                ++v;\n                unsigned char tile = B.a[x][y];\n\n                for (int dir = 0; dir < 4; ++dir) {\n                    if (!(tile & MASK[dir])) continue;\n                    int nx = x + DX[dir];\n                    int ny = y + DY[dir];\n                    if (nx < 0 || nx >= N || ny < 0 || ny >= N) continue;\n                    unsigned char nt = B.a[nx][ny];\n                    if (nt == 0) continue;\n                    if (!(nt & MASK[OPP[dir]])) continue;\n\n                    if (!vis[nx][ny]) {\n                        vis[nx][ny] = true;\n                        qx[tail] = nx;\n                        qy[tail] = ny;\n                        ++tail;\n                    }\n                    // Count each undirected edge once\n                    if (x < nx || (x == nx && y < ny)) {\n                        ++e;\n                    }\n                }\n            }\n\n            bestConn = max(bestConn, v);\n            if (e == v - 1) {\n                bestTree = max(bestTree, v);\n            }\n        }\n    }\n\n    return {bestTree, bestConn};\n}\n\n// Sliding puzzle move legality\ninline bool legalMove(int r, int c, char mv) {\n    if (mv == 'U') return r > 0;\n    if (mv == 'D') return r + 1 < N;\n    if (mv == 'L') return c > 0;\n    if (mv == 'R') return c + 1 < N;\n    return false;\n}\n\n// Apply move to board and blank position\ninline void applyMove(Board &B, int &r, int &c, char mv) {\n    if (mv == 'U') {\n        swap(B.a[r][c], B.a[r-1][c]);\n        --r;\n    } else if (mv == 'D') {\n        swap(B.a[r][c], B.a[r+1][c]);\n        ++r;\n    } else if (mv == 'L') {\n        swap(B.a[r][c], B.a[r][c-1]);\n        --c;\n    } else if (mv == 'R') {\n        swap(B.a[r][c], B.a[r][c+1]);\n        ++c;\n    }\n}\n\n// Opposite sliding move\ninline char oppositeMove(char mv) {\n    if (mv == 'U') return 'D';\n    if (mv == 'D') return 'U';\n    if (mv == 'L') return 'R';\n    if (mv == 'R') return 'L';\n    return '?';\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    if (!(cin >> N >> T)) {\n        return 0;\n    }\n\n    Board board;\n    int blankR = -1, blankC = -1;\n\n    for (int i = 0; i < N; ++i) {\n        string row;\n        cin >> row;\n        for (int j = 0; j < N; ++j) {\n            char ch = row[j];\n            int val;\n            if ('0' <= ch && ch <= '9') val = ch - '0';\n            else val = ch - 'a' + 10;\n            board.a[i][j] = static_cast<unsigned char>(val);\n            if (val == 0) {\n                blankR = i;\n                blankC = j;\n            }\n        }\n    }\n\n    // RNG for tie-breaking\n    std::mt19937_64 rng(\n        (uint64_t)chrono::high_resolution_clock::now().time_since_epoch().count()\n    );\n\n    EvalRes initialEval = evaluate(board);\n    int bestTreeGlobal = initialEval.bestTree;\n    int bestConnGlobal = initialEval.bestConn;\n    int bestStep = 0;  // prefix length giving best board\n\n    const int totalTiles = N * N - 1;\n\n    // If already perfect, output empty sequence\n    if (bestTreeGlobal == totalTiles) {\n        cout << \"\\n\";\n        return 0;\n    }\n\n    string ops;\n    ops.reserve(T);\n    char lastMove = '?';\n\n    const char allMoves[4] = {'U', 'D', 'L', 'R'};\n\n    for (int step = 0; step < T; ++step) {\n        // Build candidate first moves, avoiding immediate reverse if possible\n        char cand1[4];\n        int cand1cnt = 0;\n        for (int k = 0; k < 4; ++k) {\n            char mv = allMoves[k];\n            if (!legalMove(blankR, blankC, mv)) continue;\n            if (step > 0 && mv == oppositeMove(lastMove)) continue;\n            cand1[cand1cnt++] = mv;\n        }\n        if (cand1cnt == 0) {\n            // All legal moves are reverse of last; allow them\n            for (int k = 0; k < 4; ++k) {\n                char mv = allMoves[k];\n                if (legalMove(blankR, blankC, mv)) {\n                    cand1[cand1cnt++] = mv;\n                }\n            }\n            if (cand1cnt == 0) {\n                // Should not happen, but just in case\n                break;\n            }\n        }\n\n        long long bestScoreForStep = LLONG_MIN;\n        char chosenMove = cand1[0];\n        int tieCount = 0;\n\n        for (int idx = 0; idx < cand1cnt; ++idx) {\n            char d1 = cand1[idx];\n\n            // Simulate first move\n            Board b1 = board;\n            int br1 = blankR, bc1 = blankC;\n            applyMove(b1, br1, bc1, d1);\n\n            EvalRes e1 = evaluate(b1);\n            long long score1 = (long long)e1.bestTree * 1000 + e1.bestConn;\n            long long bestLocalScore = score1;\n\n            // Candidate second moves (depth-2 lookahead)\n            char cand2[4];\n            int cand2cnt = 0;\n            for (int k = 0; k < 4; ++k) {\n                char mv2 = allMoves[k];\n                if (!legalMove(br1, bc1, mv2)) continue;\n                if (mv2 == oppositeMove(d1)) continue;\n                cand2[cand2cnt++] = mv2;\n            }\n\n            for (int j = 0; j < cand2cnt; ++j) {\n                char d2 = cand2[j];\n                Board b2 = b1;\n                int br2 = br1, bc2 = bc1;\n                applyMove(b2, br2, bc2, d2);\n                EvalRes e2 = evaluate(b2);\n                long long score2 = (long long)e2.bestTree * 1000 + e2.bestConn;\n                if (score2 > bestLocalScore) {\n                    bestLocalScore = score2;\n                }\n            }\n\n            // Choose d1 based on bestLocalScore\n            if (bestLocalScore > bestScoreForStep) {\n                bestScoreForStep = bestLocalScore;\n                chosenMove = d1;\n                tieCount = 1;\n            } else if (bestLocalScore == bestScoreForStep) {\n                ++tieCount;\n                if (rng() % tieCount == 0) {\n                    chosenMove = d1;\n                }\n            }\n        }\n\n        // Commit chosen move\n        applyMove(board, blankR, blankC, chosenMove);\n        ops.push_back(chosenMove);\n        lastMove = chosenMove;\n\n        // Evaluate current board and update global best prefix\n        EvalRes cur = evaluate(board);\n        if (cur.bestTree > bestTreeGlobal ||\n            (cur.bestTree == bestTreeGlobal && cur.bestConn > bestConnGlobal)) {\n            bestTreeGlobal = cur.bestTree;\n            bestConnGlobal = cur.bestConn;\n            bestStep = step + 1;\n            // If we reach full tree, we can stop: shorter is better\n            if (bestTreeGlobal == totalTiles) {\n                break;\n            }\n        }\n    }\n\n    // Output best prefix\n    if (bestStep < (int)ops.size()) {\n        ops.resize(bestStep);\n    }\n    cout << ops << '\\n';\n\n    return 0;\n}","ahc012":"#include <bits/stdc++.h>\nusing namespace std;\n\n// Constants\nstatic const int RADIUS = 10000;   // radius of the cake\nstatic const int BIG = 100000;     // endpoints far enough to cross the cake\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, K;\n    if (!(cin >> N >> K)) {\n        return 0;\n    }\n    vector<int> a(11);\n    long long sumA = 0;\n    for (int d = 1; d <= 10; ++d) {\n        cin >> a[d];\n        sumA += a[d];\n    }\n    vector<pair<int,int>> pts(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> pts[i].first >> pts[i].second;\n    }\n\n    // If somehow no attendees (should not happen with constraints), output 0 cuts.\n    if (sumA == 0 || K == 0) {\n        cout << 0 << '\\n';\n        return 0;\n    }\n\n    // Average desired piece size: N / sumA (clamped to [2, 8])\n    double avgD = (double)N / (double)sumA;\n    double lambdaTarget = avgD;\n    lambdaTarget = max(2.0, min(8.0, lambdaTarget));\n\n    // Target number of cells\n    int cellsTarget = (int)std::llround((double)N / lambdaTarget);\n    if (cellsTarget < 1) cellsTarget = 1;\n\n    // Maximum cells achievable with at most K lines: maximize (Nx+1)*(Ny+1) with Nx+Ny <= K\n    long long maxCellsPossible = 0;\n    for (int Nx = 0; Nx <= K; ++Nx) {\n        int Ny = K - Nx;\n        long long cells = 1LL * (Nx + 1) * (Ny + 1);\n        if (cells > maxCellsPossible) maxCellsPossible = cells;\n    }\n    if (cellsTarget > (int)maxCellsPossible) cellsTarget = (int)maxCellsPossible;\n\n    // Choose Nx, Ny to make (Nx+1)*(Ny+1) close to cellsTarget, tie-breaking by squareness\n    int bestNx = 0, bestNy = 0;\n    long long bestErr = (1LL << 60);\n    int bestSquarePenalty = (1 << 30);\n    for (int Nx = 0; Nx <= K; ++Nx) {\n        for (int Ny = 0; Ny <= K - Nx; ++Ny) {\n            long long cells = 1LL * (Nx + 1) * (Ny + 1);\n            long long err = llabs(cells - (long long)cellsTarget);\n            int squarePenalty = abs(Nx - Ny);\n            if (err < bestErr ||\n                (err == bestErr && squarePenalty < bestSquarePenalty)) {\n                bestErr = err;\n                bestSquarePenalty = squarePenalty;\n                bestNx = Nx;\n                bestNy = Ny;\n            }\n        }\n    }\n\n    int Nx = bestNx;\n    int Ny = bestNy;\n\n    // Generate x-coordinates for vertical cuts\n    vector<int> xCuts;\n    xCuts.reserve(Nx);\n    if (Nx > 0) {\n        for (int i = 1; i <= Nx; ++i) {\n            long long num = 2LL * RADIUS * i;\n            int c = -RADIUS + (int)(num / (Nx + 1)); // floor\n            xCuts.push_back(c);\n        }\n    }\n\n    // Generate y-coordinates for horizontal cuts\n    vector<int> yCuts;\n    yCuts.reserve(Ny);\n    if (Ny > 0) {\n        for (int j = 1; j <= Ny; ++j) {\n            long long num = 2LL * RADIUS * j;\n            int c = -RADIUS + (int)(num / (Ny + 1)); // floor\n            yCuts.push_back(c);\n        }\n    }\n\n    int totalCuts = (int)xCuts.size() + (int)yCuts.size();\n    if (totalCuts > K) {\n        // Should not happen due to construction, but safeguard\n        totalCuts = K;\n    }\n\n    cout << totalCuts << '\\n';\n    // Output vertical cuts\n    for (int c : xCuts) {\n        if (--totalCuts < 0) break;\n        int px = c, py = -BIG;\n        int qx = c, qy = BIG;\n        cout << px << ' ' << py << ' ' << qx << ' ' << qy << '\\n';\n    }\n    // Output horizontal cuts\n    for (int c : yCuts) {\n        if (totalCuts <= 0) break;\n        int px = -BIG, py = c;\n        int qx = BIG,  qy = c;\n        cout << px << ' ' << py << ' ' << qx << ' ' << qy << '\\n';\n        --totalCuts;\n    }\n\n    return 0;\n}","ahc014":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int MAXN = 65;  // N <= 61\n\nint N, M;\n\n// Board state\nstatic bool hasDot[MAXN][MAXN];      // [x][y]\nstatic bool horUsed[MAXN][MAXN];     // [y][x] edge from (x,y) to (x+1,y)\nstatic bool verUsed[MAXN][MAXN];     // [x][y] edge from (x,y) to (x,y+1)\nstatic int rowPrefix[MAXN][MAXN+1];  // [y][i]: dots with x < i\nstatic int colPrefix[MAXN][MAXN+1];  // [x][i]: dots with y < i\nstatic int cellWeight[MAXN][MAXN];   // w(x,y)\n\n// Candidate rectangle for adding a dot\nstruct Candidate {\n    int weight;          // weight of new dot\n    uint8_t px, py;      // new dot position\n    uint8_t xL, yB;      // bounding box: left, bottom\n    uint8_t xR, yT;      // right, top\n};\n\nbool operator<(const Candidate &a, const Candidate &b) {\n    // priority_queue is max-heap by default; larger weight first\n    return a.weight < b.weight;\n}\n\npriority_queue<Candidate> pq;\n\n// Add a dot at (x,y): update hasDot and 1D prefix sums\ninline void addDot(int x, int y) {\n    if (hasDot[x][y]) return;\n    hasDot[x][y] = true;\n    for (int i = x + 1; i <= N; ++i) rowPrefix[y][i] += 1;\n    for (int i = y + 1; i <= N; ++i) colPrefix[x][i] += 1;\n}\n\n// For a newly added dot at (x,y), generate all rectangles where it is a vertex\n// and exactly three corners have dots (so the fourth is a candidate new dot).\ninline void updateRectanglesForNewDot(int x, int y) {\n    for (int x2 = 0; x2 < N; ++x2) {\n        if (x2 == x) continue;\n        int xL = (x2 < x) ? x2 : x;\n        int xR = (x2 < x) ? x : x2;\n        for (int y2 = 0; y2 < N; ++y2) {\n            if (y2 == y) continue;\n            int yB = (y2 < y) ? y2 : y;\n            int yT = (y2 < y) ? y : y2;\n\n            bool BL = hasDot[xL][yB];\n            bool BR = hasDot[xR][yB];\n            bool TR = hasDot[xR][yT];\n            bool TL = hasDot[xL][yT];\n            int cnt = BL + BR + TR + TL;\n            if (cnt != 3) continue;\n\n            int px, py;\n            if (!BL) { px = xL; py = yB; }\n            else if (!BR) { px = xR; py = yB; }\n            else if (!TR) { px = xR; py = yT; }\n            else { px = xL; py = yT; }\n\n            // px,py is currently empty by construction (cnt == 3)\n            Candidate c;\n            c.weight = cellWeight[px][py];\n            c.px = (uint8_t)px;\n            c.py = (uint8_t)py;\n            c.xL = (uint8_t)xL;\n            c.yB = (uint8_t)yB;\n            c.xR = (uint8_t)xR;\n            c.yT = (uint8_t)yT;\n            pq.push(c);\n        }\n    }\n}\n\n// Check if a candidate rectangle is still valid given current board state\ninline bool validateCandidate(const Candidate &c) {\n    int xL = c.xL, xR = c.xR;\n    int yB = c.yB, yT = c.yT;\n    int px = c.px, py = c.py;\n\n    // New point must be empty\n    if (hasDot[px][py]) return false;\n\n    // New point must be a corner of the rectangle\n    bool isCorner =\n        (px == xL && py == yB) ||\n        (px == xR && py == yB) ||\n        (px == xR && py == yT) ||\n        (px == xL && py == yT);\n    if (!isCorner) return false;\n\n    // Other three corners must currently be dots\n    if (!(px == xL && py == yB) && !hasDot[xL][yB]) return false;\n    if (!(px == xR && py == yB) && !hasDot[xR][yB]) return false;\n    if (!(px == xR && py == yT) && !hasDot[xR][yT]) return false;\n    if (!(px == xL && py == yT) && !hasDot[xL][yT]) return false;\n\n    // No extra dots on perimeter interior\n    if (xR - xL > 1) {\n        int sumBottom = rowPrefix[yB][xR] - rowPrefix[yB][xL + 1];\n        if (sumBottom > 0) return false;\n        int sumTop = rowPrefix[yT][xR] - rowPrefix[yT][xL + 1];\n        if (sumTop > 0) return false;\n    }\n    if (yT - yB > 1) {\n        int sumLeft  = colPrefix[xL][yT] - colPrefix[xL][yB + 1];\n        if (sumLeft > 0) return false;\n        int sumRight = colPrefix[xR][yT] - colPrefix[xR][yB + 1];\n        if (sumRight > 0) return false;\n    }\n\n    // No edges already used (no shared segments)\n    for (int x = xL; x < xR; ++x) {\n        if (horUsed[yB][x]) return false;\n        if (horUsed[yT][x]) return false;\n    }\n    for (int y = yB; y < yT; ++y) {\n        if (verUsed[xL][y]) return false;\n        if (verUsed[xR][y]) return false;\n    }\n\n    return true;\n}\n\n// Mark edges of the rectangle as used\ninline void markEdges(const Candidate &c) {\n    int xL = c.xL, xR = c.xR;\n    int yB = c.yB, yT = c.yT;\n    for (int x = xL; x < xR; ++x) {\n        horUsed[yB][x] = true;\n        horUsed[yT][x] = true;\n    }\n    for (int y = yB; y < yT; ++y) {\n        verUsed[xL][y] = true;\n        verUsed[xR][y] = true;\n    }\n}\n\n// Move record\nstruct Move {\n    int x1, y1, x2, y2, x3, y3, x4, y4;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> M;\n    vector<pair<int,int>> initial(M);\n    for (int i = 0; i < M; ++i) {\n        int x, y;\n        cin >> x >> y;\n        initial[i] = {x, y};\n    }\n\n    // Precompute weights\n    int c = (N - 1) / 2;\n    for (int x = 0; x < N; ++x) {\n        for (int y = 0; y < N; ++y) {\n            int dx = x - c;\n            int dy = y - c;\n            cellWeight[x][y] = dx * dx + dy * dy + 1;\n        }\n    }\n\n    // Sequentially add initial dots and generate initial candidates\n    for (int i = 0; i < M; ++i) {\n        int x = initial[i].first;\n        int y = initial[i].second;\n        addDot(x, y);\n        updateRectanglesForNewDot(x, y);\n    }\n\n    vector<Move> moves;\n    auto start_time = chrono::steady_clock::now();\n    const double TIME_LIMIT = 4.8; // safety margin\n\n    int iter = 0;\n    while (!pq.empty()) {\n        if ((iter & 0xFF) == 0) {\n            auto now = chrono::steady_clock::now();\n            double elapsed = chrono::duration<double>(now - start_time).count();\n            if (elapsed > TIME_LIMIT) break;\n        }\n        ++iter;\n\n        Candidate cand = pq.top();\n        pq.pop();\n\n        if (!validateCandidate(cand)) continue;\n\n        // Commit this rectangle\n        markEdges(cand);\n\n        int px = cand.px;\n        int py = cand.py;\n        addDot(px, py);\n        updateRectanglesForNewDot(px, py);\n\n        int xL = cand.xL, xR = cand.xR;\n        int yB = cand.yB, yT = cand.yT;\n\n        int ax = xL, ay = yB;\n        int bx = xR, by = yB;\n        int cx = xR, cy = yT;\n        int dx = xL, dy = yT;\n\n        Move m;\n        if (px == ax && py == ay) {\n            m = {ax, ay, bx, by, cx, cy, dx, dy};\n        } else if (px == bx && py == by) {\n            m = {bx, by, cx, cy, dx, dy, ax, ay};\n        } else if (px == cx && py == cy) {\n            m = {cx, cy, dx, dy, ax, ay, bx, by};\n        } else { // (px == dx && py == dy)\n            m = {dx, dy, ax, ay, bx, by, cx, cy};\n        }\n        moves.push_back(m);\n    }\n\n    // Output\n    cout << moves.size() << '\\n';\n    for (const auto &m : moves) {\n        cout << m.x1 << ' ' << m.y1 << ' '\n             << m.x2 << ' ' << m.y2 << ' '\n             << m.x3 << ' ' << m.y3 << ' '\n             << m.x4 << ' ' << m.y4 << '\\n';\n    }\n\n    return 0;\n}","ahc015":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const int N = 10;\n\n// Board representation\nstruct Board {\n    int a[N][N];\n    Board() { memset(a, 0, sizeof(a)); }\n\n    void add(int r, int c, int col) {\n        a[r][c] = col;\n    }\n\n    // dir: 0 = F, 1 = B, 2 = L, 3 = R\n    void tilt(int dir) {\n        if (dir == 0) { // F: move toward row 0\n            for (int c = 0; c < N; c++) {\n                int pos = 0;\n                for (int r = 0; r < N; r++) {\n                    if (a[r][c]) {\n                        if (pos != r) a[pos][c] = a[r][c];\n                        pos++;\n                    }\n                }\n                for (int r = pos; r < N; r++) a[r][c] = 0;\n            }\n        } else if (dir == 1) { // B: move toward row 9\n            for (int c = 0; c < N; c++) {\n                int pos = N - 1;\n                for (int r = N - 1; r >= 0; r--) {\n                    if (a[r][c]) {\n                        if (pos != r) a[pos][c] = a[r][c];\n                        pos--;\n                    }\n                }\n                for (int r = pos; r >= 0; r--) a[r][c] = 0;\n            }\n        } else if (dir == 2) { // L: move toward col 0\n            for (int r = 0; r < N; r++) {\n                int pos = 0;\n                for (int c = 0; c < N; c++) {\n                    if (a[r][c]) {\n                        if (pos != c) a[r][pos] = a[r][c];\n                        pos++;\n                    }\n                }\n                for (int c = pos; c < N; c++) a[r][c] = 0;\n            }\n        } else { // R: move toward col 9\n            for (int r = 0; r < N; r++) {\n                int pos = N - 1;\n                for (int c = N - 1; c >= 0; c--) {\n                    if (a[r][c]) {\n                        if (pos != c) a[r][pos] = a[r][c];\n                        pos--;\n                    }\n                }\n                for (int c = pos; c >= 0; c--) a[r][c] = 0;\n            }\n        }\n    }\n};\n\n// Evaluate sum of squares of connected component sizes (same-color, 4-neighbor)\nlong long evaluate(const Board &b) {\n    bool vis[N][N] = {};\n    const int dr[4] = {1, -1, 0, 0};\n    const int dc[4] = {0, 0, 1, -1};\n    long long score = 0;\n\n    for (int r = 0; r < N; r++) {\n        for (int c = 0; c < N; c++) {\n            if (b.a[r][c] != 0 && !vis[r][c]) {\n                int color = b.a[r][c];\n                int cnt = 0;\n                queue<pair<int,int>> q;\n                vis[r][c] = true;\n                q.push({r, c});\n                while (!q.empty()) {\n                    auto [x, y] = q.front();\n                    q.pop();\n                    cnt++;\n                    for (int k = 0; k < 4; k++) {\n                        int nx = x + dr[k];\n                        int ny = y + dc[k];\n                        if (0 <= nx && nx < N && 0 <= ny && ny < N &&\n                            !vis[nx][ny] && b.a[nx][ny] == color) {\n                            vis[nx][ny] = true;\n                            q.push({nx, ny});\n                        }\n                    }\n                }\n                score += 1LL * cnt * cnt;\n            }\n        }\n    }\n    return score;\n}\n\n// Map p (1-based) to (r, c) in current board: front-to-back, left-to-right\npair<int,int> findPos(const Board &b, int p) {\n    int cnt = 0;\n    for (int r = 0; r < N; r++) {\n        for (int c = 0; c < N; c++) {\n            if (b.a[r][c] == 0) {\n                cnt++;\n                if (cnt == p) return {r, c};\n            }\n        }\n    }\n    // Should never happen\n    return {-1, -1};\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // Read flavors\n    vector<int> f(100);\n    for (int i = 0; i < 100; i++) {\n        if (!(cin >> f[i])) return 0;\n    }\n\n    Board cur;\n    const char DIR_CH[4] = {'F', 'B', 'L', 'R'};\n\n    for (int t = 0; t < 100; t++) {\n        int p;\n        if (!(cin >> p)) return 0;\n\n        // Place the new candy\n        auto [r, c] = findPos(cur, p);\n        if (r == -1) return 0; // safety\n        cur.add(r, c, f[t]);\n\n        // Try all 4 directions and pick the best\n        long long bestScore = -1;\n        int bestDir = 0;\n        Board bestBoard;\n\n        for (int dir = 0; dir < 4; dir++) {\n            Board tmp = cur;\n            tmp.tilt(dir);\n            long long sc = evaluate(tmp);\n            if (sc > bestScore) {\n                bestScore = sc;\n                bestDir = dir;\n                bestBoard = tmp;\n            }\n        }\n\n        // Update current board to chosen tilt result\n        cur = bestBoard;\n\n        // Output chosen direction and flush\n        cout << DIR_CH[bestDir] << '\\n' << flush;\n    }\n\n    return 0;\n}","ahc016":"#include <bits/stdc++.h>\nusing namespace std;\n\n// Fast xorshift RNG (deterministic)\nstatic uint64_t rng_state = 88172645463325252ULL;\ninline uint64_t rng64() {\n    rng_state ^= rng_state << 7;\n    rng_state ^= rng_state >> 9;\n    return rng_state;\n}\ninline int rand_int(int n) {\n    return (int)(rng64() % n); // 0..n-1\n}\n\nstruct Graph {\n    int N;\n    int mEdges; // number of edges\n    vector<vector<uint8_t>> adj; // NxN adjacency (0/1)\n    vector<int> deg;\n    vector<int> feat2;\n    vector<int> feat3;\n    vector<int> sortedIdx;\n\n    Graph() {}\n    Graph(int n) { init(n); }\n\n    void init(int n) {\n        N = n;\n        adj.assign(N, vector<uint8_t>(N, 0));\n        deg.assign(N, 0);\n        feat2.assign(N, 0);\n        feat3.assign(N, 0);\n        sortedIdx.resize(N);\n    }\n\n    void compute_features() {\n        // degrees\n        mEdges = 0;\n        for (int i = 0; i < N; ++i) {\n            int d = 0;\n            for (int j = 0; j < N; ++j) {\n                if (adj[i][j]) ++d;\n            }\n            deg[i] = d;\n            mEdges += d;\n        }\n        mEdges /= 2;\n        // neighbor-degree based features\n        for (int i = 0; i < N; ++i) {\n            int s2 = 0;\n            int s3 = 0;\n            for (int j = 0; j < N; ++j) {\n                if (adj[i][j]) {\n                    int d = deg[j];\n                    s2 += d;\n                    s3 += d * d;\n                }\n            }\n            feat2[i] = s2;\n            feat3[i] = s3;\n        }\n        // sorted indices by (deg, feat2, feat3, index)\n        iota(sortedIdx.begin(), sortedIdx.end(), 0);\n        sort(sortedIdx.begin(), sortedIdx.end(),\n             [&](int a, int b) {\n                 if (deg[a] != deg[b]) return deg[a] < deg[b];\n                 if (feat2[a] != feat2[b]) return feat2[a] < feat2[b];\n                 if (feat3[a] != feat3[b]) return feat3[a] < feat3[b];\n                 return a < b;\n             });\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int M;\n    double eps;\n    if (!(cin >> M >> eps)) {\n        return 0;\n    }\n\n    // Choose N based on M and eps\n    int N = 4;\n    double baseFactor = 10.0 + 80.0 * eps; // between 10 and 42 for eps in [0,0.4]\n    double targetL = baseFactor * (double)M;\n    while (N < 100) {\n        double L = 1.0 * N * (N - 1) / 2.0;\n        if (L >= targetL) break;\n        ++N;\n    }\n    if (N < 4) N = 4;\n    int L = N * (N - 1) / 2;\n\n    // Prepare graphs G_0..G_{M-1}\n    vector<Graph> G(M, Graph(N));\n\n    // Assign edge counts spread evenly over [1, L-1]\n    vector<int> targetEdges(M);\n    for (int k = 0; k < M; ++k) {\n        // floor((k+1)*L/(M+1))\n        long long num = 1LL * (k + 1) * L;\n        int mk = (int)(num / (M + 1));\n        if (mk <= 0) mk = 1;\n        if (mk >= L) mk = L - 1;\n        targetEdges[k] = mk;\n    }\n\n    // Generate each G_k\n    for (int k = 0; k < M; ++k) {\n        Graph &g = G[k];\n        int mk = targetEdges[k];\n\n        // Initialize adjacency\n        if (mk * 2 <= L) {\n            // start from empty graph, add mk edges\n            for (int i = 0; i < N; ++i)\n                fill(g.adj[i].begin(), g.adj[i].end(), 0);\n            int edges = 0;\n            while (edges < mk) {\n                int i = rand_int(N);\n                int j = rand_int(N - 1);\n                if (j >= i) ++j;\n                if (!g.adj[i][j]) {\n                    g.adj[i][j] = 1;\n                    g.adj[j][i] = 1;\n                    ++edges;\n                }\n            }\n        } else {\n            // start from complete graph, remove L - mk edges\n            for (int i = 0; i < N; ++i) {\n                for (int j = 0; j < N; ++j) {\n                    g.adj[i][j] = (i != j) ? 1 : 0;\n                }\n            }\n            int rem = L - mk;\n            while (rem > 0) {\n                int i = rand_int(N);\n                int j = rand_int(N - 1);\n                if (j >= i) ++j;\n                if (g.adj[i][j]) {\n                    g.adj[i][j] = 0;\n                    g.adj[j][i] = 0;\n                    --rem;\n                }\n            }\n        }\n\n        g.compute_features();\n        // We could assert g.mEdges == mk, but it's guaranteed by construction.\n    }\n\n    // Output N and graphs in required string format\n    cout << N << '\\n';\n    for (int k = 0; k < M; ++k) {\n        Graph &g = G[k];\n        // Output edges in lex order of (i,j) with i<j\n        string s;\n        s.reserve(L);\n        for (int i = 0; i < N; ++i) {\n            for (int j = i + 1; j < N; ++j) {\n                s.push_back(g.adj[i][j] ? '1' : '0');\n            }\n        }\n        cout << s << '\\n';\n    }\n    cout.flush();\n\n    // Prepare buffers for queries\n    vector<vector<uint8_t>> Hadj(N, vector<uint8_t>(N, 0));\n    vector<int> deg_H(N), feat2_H(N), feat3_H(N), sortedIdx_H(N);\n    vector<int> mapGH(N);\n\n    // Process 100 queries\n    for (int q = 0; q < 100; ++q) {\n        string Hstr;\n        if (!(cin >> Hstr)) return 0;\n        // Build Hadj from Hstr\n        int pos = 0;\n        for (int i = 0; i < N; ++i) {\n            Hadj[i][i] = 0;\n            for (int j = i + 1; j < N; ++j) {\n                char c = Hstr[pos++];\n                uint8_t v = (c == '1') ? 1 : 0;\n                Hadj[i][j] = v;\n                Hadj[j][i] = v;\n            }\n        }\n\n        // Compute degrees for H\n        for (int i = 0; i < N; ++i) {\n            int d = 0;\n            const auto &row = Hadj[i];\n            for (int j = 0; j < N; ++j) {\n                if (row[j]) ++d;\n            }\n            deg_H[i] = d;\n        }\n\n        // Compute neighbor-degree features for H\n        for (int i = 0; i < N; ++i) {\n            int s2 = 0;\n            int s3 = 0;\n            const auto &row = Hadj[i];\n            for (int j = 0; j < N; ++j) {\n                if (row[j]) {\n                    int d = deg_H[j];\n                    s2 += d;\n                    s3 += d * d;\n                }\n            }\n            feat2_H[i] = s2;\n            feat3_H[i] = s3;\n        }\n\n        // Sorted indices for H\n        iota(sortedIdx_H.begin(), sortedIdx_H.end(), 0);\n        sort(sortedIdx_H.begin(), sortedIdx_H.end(),\n             [&](int a, int b) {\n                 if (deg_H[a] != deg_H[b]) return deg_H[a] < deg_H[b];\n                 if (feat2_H[a] != feat2_H[b]) return feat2_H[a] < feat2_H[b];\n                 if (feat3_H[a] != feat3_H[b]) return feat3_H[a] < feat3_H[b];\n                 return a < b;\n             });\n\n        int bestK = 0;\n        int bestCost = INT_MAX;\n\n        // For each candidate graph\n        for (int k = 0; k < M; ++k) {\n            Graph &g = G[k];\n\n            // Build mapping G -> H via sorted feature ranks\n            for (int r = 0; r < N; ++r) {\n                int gv = g.sortedIdx[r];\n                int hv = sortedIdx_H[r];\n                mapGH[gv] = hv;\n            }\n\n            int cost = 0;\n            // Compare adjacency matrices under the mapping\n            for (int i = 0; i < N; ++i) {\n                int hi = mapGH[i];\n                const auto &rowG = g.adj[i];\n                const auto &rowH = Hadj[hi];\n                for (int j = i + 1; j < N; ++j) {\n                    int hj = mapGH[j];\n                    if (rowG[j] != rowH[hj]) {\n                        ++cost;\n                        if (cost >= bestCost) {\n                            goto next_candidate;\n                        }\n                    }\n                }\n            }\n\n            if (cost < bestCost) {\n                bestCost = cost;\n                bestK = k;\n            }\n\n        next_candidate:\n            continue;\n        }\n\n        cout << bestK << '\\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 id;\n    int w;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, D, K;\n    if (!(cin >> N >> M >> D >> K)) return 0;\n\n    vector<int> U(M), V(M), W(M);\n    for (int i = 0; i < M; i++) {\n        cin >> U[i] >> V[i] >> W[i];\n        --U[i];\n        --V[i];\n    }\n\n    // Read coordinates but ignore them\n    for (int i = 0; i < N; i++) {\n        int x, y;\n        cin >> x >> y;\n    }\n\n    // Build adjacency list\n    vector<vector<AdjEdge>> g(N);\n    g.assign(N, {});\n    for (int i = 0; i < M; i++) {\n        int u = U[i], v = V[i], w = W[i];\n        g[u].push_back({v, i, w});\n        g[v].push_back({u, i, w});\n    }\n\n    // -------- Edge importance via sampled shortest-path trees --------\n    int S = min(N, 80); // number of sampled sources\n    vector<int> sources;\n    sources.reserve(S);\n    for (int i = 0; i < S; i++) {\n        int s = (long long)i * N / S;\n        sources.push_back(s);\n    }\n\n    vector<double> central(M, 0.0);\n    const long long INFLL = (1LL << 60);\n    vector<long long> dist(N);\n    vector<int> parent_v(N), parent_e(N);\n    vector<int> order;\n    order.reserve(N);\n\n    using PQItem = pair<long long, int>;\n\n    for (int s : sources) {\n        // Dijkstra from s\n        fill(dist.begin(), dist.end(), INFLL);\n        fill(parent_v.begin(), parent_v.end(), -1);\n        fill(parent_e.begin(), parent_e.end(), -1);\n        order.clear();\n\n        priority_queue<PQItem, vector<PQItem>, greater<PQItem>> pq;\n        dist[s] = 0;\n        pq.emplace(0, s);\n\n        while (!pq.empty()) {\n            auto [d, v] = pq.top();\n            pq.pop();\n            if (d != dist[v]) continue;\n            order.push_back(v);\n            for (const auto &e : g[v]) {\n                int to = e.to;\n                long long nd = d + e.w;\n                if (nd < dist[to]) {\n                    dist[to] = nd;\n                    parent_v[to] = v;\n                    parent_e[to] = e.id;\n                    pq.emplace(nd, to);\n                }\n            }\n        }\n\n        // Tree DP: compute subtree sizes and accumulate centrality on edges\n        vector<int> sz(N, 1);\n        for (int i = (int)order.size() - 1; i >= 0; --i) {\n            int v = order[i];\n            int pv = parent_v[v];\n            if (pv == -1) continue;\n            int eid = parent_e[v];\n            central[eid] += sz[v];\n            sz[pv] += sz[v];\n        }\n    }\n\n    // Compute importance and scaled weights\n    vector<double> imp(M);\n    double max_imp = 0.0;\n    for (int i = 0; i < M; i++) {\n        imp[i] = (central[i] + 1.0) * (double)W[i];  // +1 to avoid 0\n        if (imp[i] > max_imp) max_imp = imp[i];\n    }\n    double scale = (max_imp > 0.0 ? max_imp / 1000.0 : 1.0);\n    vector<double> weight(M);\n    for (int i = 0; i < M; i++) {\n        weight[i] = imp[i] / scale;\n    }\n\n    // -------- Initial greedy assignment --------\n    vector<int> cap(D);\n    int base = M / D;\n    int rem = M % D;\n    for (int d = 0; d < D; d++) {\n        cap[d] = base + (d < rem ? 1 : 0);\n        // cap[d] <= ceil(M/D) <= K, so always valid\n    }\n\n    vector<int> day_cnt(D, 0);\n    vector<double> day_sum(D, 0.0);  // sum of weights per day\n\n    // vertex-day counts: how many edges at vertex v repaired on day d\n    vector<vector<uint16_t>> vdc(N, vector<uint16_t>(D, 0));\n\n    vector<int> r(M, -1);  // day assignment for each edge (0..D-1)\n\n    // Edges sorted by descending importance\n    vector<int> ids(M);\n    iota(ids.begin(), ids.end(), 0);\n    sort(ids.begin(), ids.end(),\n         [&](int a, int b) { return weight[a] > weight[b]; });\n\n    for (int idx = 0; idx < M; idx++) {\n        int e = ids[idx];\n        int u = U[e], v = V[e];\n\n        int bestD = -1;\n        int bestC0 = INT_MAX;\n        double bestC1 = 0.0;\n\n        for (int d = 0; d < D; d++) {\n            if (day_cnt[d] >= cap[d]) continue;\n            int c0 = (int)vdc[u][d] + (int)vdc[v][d];\n            double c1 = day_sum[d];\n\n            if (c0 < bestC0 || (c0 == bestC0 && c1 < bestC1)) {\n                bestC0 = c0;\n                bestC1 = c1;\n                bestD = d;\n            }\n        }\n\n        if (bestD == -1) {\n            // Fallback (should not happen): choose any day with remaining cap\n            for (int d = 0; d < D; d++) {\n                if (day_cnt[d] < cap[d]) {\n                    bestD = d;\n                    break;\n                }\n            }\n        }\n\n        r[e] = bestD;\n        day_cnt[bestD]++;\n        day_sum[bestD] += weight[e];\n        vdc[u][bestD]++;\n        vdc[v][bestD]++;\n    }\n\n    // -------- Local search (hill climbing) --------\n    mt19937_64 rng(123456789);\n    uniform_int_distribution<int> distEdge(0, M - 1);\n\n    auto deltaPenalty = [&](int e1, int d1, int e2, int d2) -> long long {\n        // Compute change in concurrency penalty if days of e1 and e2 are swapped.\n        int u1 = U[e1], v1 = V[e1];\n        int u2 = U[e2], v2 = V[e2];\n\n        int vs[8];\n        int dsA[8];\n        int dc[8];\n        int cnt = 0;\n\n        auto addChange = [&](int v, int d, int delta) {\n            for (int i = 0; i < cnt; i++) {\n                if (vs[i] == v && dsA[i] == d) {\n                    dc[i] += delta;\n                    return;\n                }\n            }\n            vs[cnt] = v;\n            dsA[cnt] = d;\n            dc[cnt] = delta;\n            cnt++;\n        };\n\n        // e1: from d1 to d2\n        addChange(u1, d1, -1);\n        addChange(u1, d2, +1);\n        addChange(v1, d1, -1);\n        addChange(v1, d2, +1);\n\n        // e2: from d2 to d1\n        addChange(u2, d2, -1);\n        addChange(u2, d1, +1);\n        addChange(v2, d2, -1);\n        addChange(v2, d1, +1);\n\n        long long deltaP = 0;\n        for (int i = 0; i < cnt; i++) {\n            int v = vs[i];\n            int d = dsA[i];\n            int oldc = (int)vdc[v][d];\n            int newc = oldc + dc[i];\n            if (newc < 0) {\n                // Should not happen, treat as very bad\n                return (long long)4e18;\n            }\n            long long oldPairs = (long long)oldc * (oldc - 1) / 2;\n            long long newPairs = (long long)newc * (newc - 1) / 2;\n            deltaP += newPairs - oldPairs;\n        }\n        return deltaP;\n    };\n\n    // Stage 1: concurrency-only improvement\n    int ITER1 = min(200000, 50 * M);\n    for (int it = 0; it < ITER1; ++it) {\n        int e1 = distEdge(rng);\n        int e2 = distEdge(rng);\n        if (e1 == e2) continue;\n        int d1 = r[e1], d2 = r[e2];\n        if (d1 == d2) continue;\n\n        long long dP = deltaPenalty(e1, d1, e2, d2);\n        if (dP < 0) {\n            // Accept swap: update assignments and data\n            double w1 = weight[e1], w2 = weight[e2];\n\n            day_sum[d1] += w2 - w1;\n            day_sum[d2] += w1 - w2;\n\n            int u1 = U[e1], v1 = V[e1];\n            int u2 = U[e2], v2 = V[e2];\n\n            vdc[u1][d1]--; vdc[u1][d2]++;\n            vdc[v1][d1]--; vdc[v1][d2]++;\n            vdc[u2][d2]--; vdc[u2][d1]++;\n            vdc[v2][d2]--; vdc[v2][d1]++;\n\n            swap(r[e1], r[e2]);\n        }\n    }\n\n    // Stage 2: balance day sums with concurrency non-increase\n    int ITER2 = min(800000, 200 * M);\n    for (int it = 0; it < ITER2; ++it) {\n        int e1 = distEdge(rng);\n        int e2 = distEdge(rng);\n        if (e1 == e2) continue;\n        int d1 = r[e1], d2 = r[e2];\n        if (d1 == d2) continue;\n\n        long long dP = deltaPenalty(e1, d1, e2, d2);\n        if (dP > 0) continue;  // do not allow increasing concurrency\n\n        double w1 = weight[e1], w2 = weight[e2];\n        double S1 = day_sum[d1], S2 = day_sum[d2];\n\n        double nS1 = S1 - w1 + w2;\n        double nS2 = S2 - w2 + w1;\n\n        double oldS2 = S1 * S1 + S2 * S2;\n        double newS2 = nS1 * nS1 + nS2 * nS2;\n        double deltaS2 = newS2 - oldS2;\n\n        if (deltaS2 < -1e-9) {\n            // Accept swap\n            day_sum[d1] = nS1;\n            day_sum[d2] = nS2;\n\n            int u1 = U[e1], v1 = V[e1];\n            int u2 = U[e2], v2 = V[e2];\n\n            vdc[u1][d1]--; vdc[u1][d2]++;\n            vdc[v1][d1]--; vdc[v1][d2]++;\n            vdc[u2][d2]--; vdc[u2][d1]++;\n            vdc[v2][d2]--; vdc[v2][d1]++;\n\n            swap(r[e1], r[e2]);\n        }\n    }\n\n    // -------- Output --------\n    for (int i = 0; i < M; i++) {\n        cout << (r[i] + 1) << (i + 1 == M ? '\\n' : ' ');\n    }\n\n    return 0;\n}","ahc019":"#include <bits/stdc++.h>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int D;\n    if (!(cin >> D)) return 0;\n\n    // Read silhouettes: f[i][z][x], r[i][z][y]\n    vector<string> f[2], r[2];\n    for (int t = 0; t < 2; t++) {\n        f[t].resize(D);\n        r[t].resize(D);\n        for (int z = 0; z < D; z++) cin >> f[t][z];\n        for (int z = 0; z < D; z++) cin >> r[t][z];\n    }\n\n    // 3D arrays of block indices for two puzzles\n    vector<vector<vector<int>>> b1(D, vector<vector<int>>(D, vector<int>(D, 0)));\n    vector<vector<vector<int>>> b2(D, vector<vector<int>>(D, vector<int>(D, 0)));\n\n    // Occupied cells for each puzzle as (x,y,z)\n    vector<tuple<int,int,int>> cells[2];\n\n    // Build minimal-volume objects for each puzzle separately\n    for (int t = 0; t < 2; t++) {\n        for (int z = 0; z < D; z++) {\n            vector<int> rows, cols;\n            rows.reserve(D);\n            cols.reserve(D);\n            for (int x = 0; x < D; x++) if (f[t][z][x] == '1') rows.push_back(x);\n            for (int y = 0; y < D; y++) if (r[t][z][y] == '1') cols.push_back(y);\n\n            int R = (int)rows.size();\n            int C = (int)cols.size();\n            if (R == 0 || C == 0) continue; // Should not happen due to constraints\n\n            if (R <= C) {\n                // Use C cubes, one per column, rows repeated cyclically\n                for (int j = 0; j < C; j++) {\n                    int x = rows[j % R];\n                    int y = cols[j];\n                    cells[t].emplace_back(x, y, z);\n                }\n            } else {\n                // Use R cubes, one per row, columns repeated cyclically\n                for (int i = 0; i < R; i++) {\n                    int x = rows[i];\n                    int y = cols[i % C];\n                    cells[t].emplace_back(x, y, z);\n                }\n            }\n        }\n    }\n\n    int V1 = (int)cells[0].size();\n    int V2 = (int)cells[1].size();\n    int nBlocks = max(V1, V2);\n\n    // Assign block IDs, reusing as many unit cubes as possible\n    if (V1 <= V2) {\n        // First V1 blocks shared\n        for (int k = 0; k < V1; k++) {\n            auto [x1, y1, z1] = cells[0][k];\n            auto [x2, y2, z2] = cells[1][k];\n            int id = k + 1;\n            b1[x1][y1][z1] = id;\n            b2[x2][y2][z2] = id;\n        }\n        // Remaining blocks used only in puzzle 2\n        for (int k = V1; k < V2; k++) {\n            auto [x2, y2, z2] = cells[1][k];\n            int id = k + 1;\n            b2[x2][y2][z2] = id;\n        }\n    } else {\n        // V2 < V1: symmetric\n        for (int k = 0; k < V2; k++) {\n            auto [x1, y1, z1] = cells[0][k];\n            auto [x2, y2, z2] = cells[1][k];\n            int id = k + 1;\n            b1[x1][y1][z1] = id;\n            b2[x2][y2][z2] = id;\n        }\n        for (int k = V2; k < V1; k++) {\n            auto [x1, y1, z1] = cells[0][k];\n            int id = k + 1;\n            b1[x1][y1][z1] = id;\n        }\n    }\n\n    // Output\n    cout << nBlocks << '\\n';\n\n    // Flattened b1: order (x,y,z) with x outermost, then y, then z\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                if (!first) cout << ' ';\n                first = false;\n                cout << b1[x][y][z];\n            }\n        }\n    }\n    cout << '\\n';\n\n    // Flattened b2\n    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                if (!first) cout << ' ';\n                first = false;\n                cout << b2[x][y][z];\n            }\n        }\n    }\n    cout << '\\n';\n\n    return 0;\n}","ahc020":"#include <bits/stdc++.h>\nusing namespace std;\nusing ll = long long;\n\nstruct Edge {\n    int u, v;\n    ll w;\n};\n\nstruct DSU {\n    vector<int> p, r;\n    DSU(int n = 0) { init(n); }\n    void init(int n) {\n        p.resize(n + 1);\n        r.assign(n + 1, 0);\n        for (int i = 0; i <= n; ++i) p[i] = i;\n    }\n    int find(int x) {\n        if (p[x] == x) return x;\n        return p[x] = find(p[x]);\n    }\n    bool unite(int a, int b) {\n        a = find(a); 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\nint N, M, K;\nvector<ll> vx, vy;\nvector<Edge> edges;\nvector<vector<pair<int,int>>> mstAdj;   // [1..N]: (to, edgeIndex 0..M-1)\nvector<int> MSTedges;                   // indices into edges[]\nvector<char> MSTmask;                   // edge in MST?\n\nvector<vector<pair<ll,int>>> residentCand; // per resident: (dist2, vertex)\n\n// Working buffers for evaluation\nvector<ll> maxd2_arr;\nvector<char> used_arr;\nvector<char> req_arr;\nvector<int> degree_arr;\nvector<char> alive_arr;\n\n// Evaluate solution for given \"open\" set of centers.\n// open[i] = 1 if station i can be chosen as a broadcast center.\n// Returns true if all residents can be assigned within radius <=5000.\n// Fills P_out[1..N], B_out[0..M-1], and cost_out.\nbool evaluate_solution(const vector<char>& open,\n                       ll &cost_out,\n                       vector<int>& P_out,\n                       vector<int>& B_out)\n{\n    const ll R2max = 5000LL * 5000LL;\n    int n = N;\n    int m = M;\n\n    // Assignment: residents -> nearest open station within 5000\n    maxd2_arr.assign(n + 1, 0);\n    used_arr.assign(n + 1, 0);\n\n    for (int k = 0; k < K; ++k) {\n        bool assigned = false;\n        const auto &cand = residentCand[k];\n        for (const auto &pr : cand) {\n            ll d2 = pr.first;\n            if (d2 > R2max) break;  // further candidates are even farther\n            int v = pr.second;\n            if (open[v]) {\n                assigned = true;\n                used_arr[v] = 1;\n                if (maxd2_arr[v] < d2) maxd2_arr[v] = d2;\n                break;\n            }\n        }\n        if (!assigned) {\n            // Some resident has no open station within radius 5000\n            return false;\n        }\n    }\n\n    // Compute P_i (broadcast radii) and broadcast cost\n    P_out.assign(n + 1, 0);\n    ll broadcastCost = 0;\n    for (int i = 1; i <= n; ++i) {\n        if (maxd2_arr[i] > 0) {\n            ll r2 = maxd2_arr[i];\n            long double sr = sqrt((long double)r2);\n            ll r = (ll)sr;\n            if (r * r < r2) ++r;   // ceil sqrt\n            if (r > 5000) r = 5000; // safety (should not happen by constraints)\n            P_out[i] = (int)r;\n            broadcastCost += r * r;\n        }\n    }\n\n    // Steiner tree on MST: connect used stations and vertex 1\n    req_arr.assign(n + 1, 0);\n    for (int i = 1; i <= n; ++i) {\n        req_arr[i] = used_arr[i];\n    }\n    req_arr[1] = 1; // root must be connected\n\n    degree_arr.assign(n + 1, 0);\n    for (int i = 1; i <= n; ++i) {\n        degree_arr[i] = (int)mstAdj[i].size();\n    }\n    alive_arr.assign(m, 0);\n    for (int eid : MSTedges) alive_arr[eid] = 1;\n\n    queue<int> q;\n    for (int i = 1; i <= n; ++i) {\n        if (!req_arr[i] && degree_arr[i] == 1) q.push(i);\n    }\n\n    while (!q.empty()) {\n        int v = q.front(); q.pop();\n        if (req_arr[v]) continue;       // should not prune required\n        if (degree_arr[v] != 1) continue;\n        // find the single alive incident edge\n        for (auto &pr : mstAdj[v]) {\n            int to = pr.first;\n            int eid = pr.second;\n            if (alive_arr[eid]) {\n                alive_arr[eid] = 0;\n                --degree_arr[v];\n                --degree_arr[to];\n                if (!req_arr[to] && degree_arr[to] == 1) {\n                    q.push(to);\n                }\n                break;\n            }\n        }\n    }\n\n    ll edgeCost = 0;\n    for (int eid : MSTedges) {\n        if (alive_arr[eid]) edgeCost += edges[eid].w;\n    }\n    cost_out = broadcastCost + edgeCost;\n\n    // Build B_out\n    B_out.assign(m, 0);\n    for (int eid : MSTedges) {\n        if (alive_arr[eid]) B_out[eid] = 1;\n    }\n\n    return true;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> M >> K;\n    vx.assign(N + 1, 0);\n    vy.assign(N + 1, 0);\n    for (int i = 1; i <= N; ++i) {\n        cin >> vx[i] >> vy[i];\n    }\n\n    edges.resize(M);\n    for (int j = 0; j < M; ++j) {\n        cin >> edges[j].u >> edges[j].v >> edges[j].w;\n    }\n\n    vector<ll> ax(K), ay(K);\n    for (int k = 0; k < K; ++k) {\n        cin >> ax[k] >> ay[k];\n    }\n\n    // Build MST with Kruskal\n    mstAdj.assign(N + 1, {});\n    MSTmask.assign(M, 0);\n    MSTedges.clear();\n    MSTedges.reserve(N - 1);\n\n    vector<int> ord(M);\n    iota(ord.begin(), ord.end(), 0);\n    sort(ord.begin(), ord.end(), [&](int a, int b){\n        return edges[a].w < edges[b].w;\n    });\n\n    DSU dsu(N);\n    for (int id : ord) {\n        int u = edges[id].u;\n        int v = edges[id].v;\n        if (dsu.unite(u, v)) {\n            MSTmask[id] = 1;\n            MSTedges.push_back(id);\n            mstAdj[u].push_back({v, id});\n            mstAdj[v].push_back({u, id});\n        }\n    }\n\n    // Compute MST distance from root 1 to each vertex\n    vector<ll> distMST(N + 1, 0);\n    {\n        vector<int> st;\n        st.reserve(N);\n        vector<int> parent(N + 1, 0);\n        st.push_back(1);\n        parent[1] = -1;\n        while (!st.empty()) {\n            int u = st.back(); st.pop_back();\n            for (auto &pr : mstAdj[u]) {\n                int v = pr.first;\n                int eid = pr.second;\n                if (v == parent[u]) continue;\n                parent[v] = u;\n                distMST[v] = distMST[u] + edges[eid].w;\n                st.push_back(v);\n            }\n        }\n    }\n\n    // Precompute candidate lists for residents\n    residentCand.resize(K);\n    for (int k = 0; k < K; ++k) {\n        vector<pair<ll,int>> cand;\n        cand.reserve(N);\n        for (int v = 1; v <= N; ++v) {\n            ll dx = vx[v] - ax[k];\n            ll dy = vy[v] - ay[k];\n            ll d2 = dx * dx + dy * dy;\n            cand.emplace_back(d2, v);\n        }\n        sort(cand.begin(), cand.end(),\n             [](const pair<ll,int>& a, const pair<ll,int>& b){\n                 return a.first < b.first;\n             });\n        residentCand[k] = move(cand);\n    }\n\n    // Initialize working buffers for evaluation\n    maxd2_arr.assign(N + 1, 0);\n    used_arr.assign(N + 1, 0);\n    req_arr.assign(N + 1, 0);\n    degree_arr.assign(N + 1, 0);\n    alive_arr.assign(M, 0);\n\n    // Initial open set: all stations open\n    vector<char> open(N + 1, 1);\n\n    vector<int> P_temp(N + 1), B_temp(M);\n    vector<int> P_best(N + 1), B_best(M);\n    ll bestCost = 0;\n\n    bool ok = evaluate_solution(open, bestCost, P_temp, B_temp);\n    if (!ok) {\n        // As a fallback (should never happen), open all and trust it\n        fill(open.begin(), open.end(), 1);\n        evaluate_solution(open, bestCost, P_temp, B_temp);\n    }\n    P_best = P_temp;\n    B_best = B_temp;\n\n    // Order vertices by decreasing MST distance from root (skip 1)\n    vector<int> order;\n    order.reserve(N - 1);\n    for (int i = 2; i <= N; ++i) order.push_back(i);\n    sort(order.begin(), order.end(), [&](int a, int b){\n        return distMST[a] > distMST[b];\n    });\n\n    // Greedy removal of centers\n    for (int v : order) {\n        if (!open[v]) continue;  // already closed\n        open[v] = 0;\n        ll cost2;\n        if (evaluate_solution(open, cost2, P_temp, B_temp)) {\n            if (cost2 < bestCost) {\n                bestCost = cost2;\n                P_best = P_temp;\n                B_best = B_temp;\n                // keep v closed\n            } else {\n                open[v] = 1; // revert\n            }\n        } else {\n            open[v] = 1; // cannot cover all residents without this station\n        }\n    }\n\n    // Output final solution\n    // Line 1: P_1 ... P_N\n    cout << P_best[1];\n    for (int i = 2; i <= N; ++i) {\n        cout << ' ' << P_best[i];\n    }\n    cout << '\\n';\n\n    // Line 2: B_1 ... B_M (edges in input order)\n    if (M > 0) {\n        cout << B_best[0];\n        for (int j = 1; j < M; ++j) {\n            cout << ' ' << B_best[j];\n        }\n    }\n    cout << '\\n';\n\n    return 0;\n}","ahc021":"#include <bits/stdc++.h>\nusing namespace std;\n\n// ----- Structures -----\nstruct Edge {\n    int u, v; // indices of nodes\n};\n\nstruct Op {\n    short x1, y1, x2, y2; // coordinates of swapped cells\n};\n\n// ----- Simple RNG (xorshift) -----\nstruct XorShift {\n    uint64_t x;\n    XorShift(uint64_t seed = 123456789) : x(seed) {}\n    uint64_t operator()() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return x;\n    }\n    int next_int(int n) { // 0..n-1\n        return (int)(operator()() % (uint64_t)n);\n    }\n};\n\n// ----- Compute total number of violations E -----\nint computeE(const vector<int> &a, const vector<Edge> &dEdges) {\n    int E = 0;\n    for (const auto &e : dEdges) {\n        if (a[e.u] > a[e.v]) ++E;\n    }\n    return E;\n}\n\n// ----- Delta E for swapping two neighboring nodes u, v -----\nint deltaE_for_swap(const vector<int> &a, int u, int v,\n                    const vector<Edge> &dEdges,\n                    const vector<vector<int>> &nodeEdgeIds) {\n    int valU = a[u];\n    int valV = a[v];\n\n    int edges[8];\n    int cnt = 0;\n\n    // collect incident edges of u\n    for (int id : nodeEdgeIds[u]) {\n        edges[cnt++] = id;\n    }\n    // add incident edges of v, avoiding duplicates\n    for (int id : nodeEdgeIds[v]) {\n        bool dup = false;\n        for (int i = 0; i < cnt; ++i) {\n            if (edges[i] == id) {\n                dup = true;\n                break;\n            }\n        }\n        if (!dup) edges[cnt++] = id;\n    }\n\n    int delta = 0;\n    for (int i = 0; i < cnt; ++i) {\n        const Edge &e = dEdges[edges[i]];\n        int aIdx = e.u;\n        int bIdx = e.v;\n\n        int beforeA = a[aIdx];\n        int beforeB = a[bIdx];\n        bool before = (beforeA > beforeB);\n\n        int afterA = (aIdx == u ? valV : (aIdx == v ? valU : beforeA));\n        int afterB = (bIdx == u ? valV : (bIdx == v ? valU : beforeB));\n        bool after = (afterA > afterB);\n\n        delta += (int)after - (int)before;\n    }\n    return delta;\n}\n\n// ----- One run of the heuristic (returns ops + final E) -----\nvoid run_single(const vector<int> &initial,\n                const vector<Edge> &dEdges,\n                const vector<Edge> &adjEdges,\n                const vector<vector<int>> &nodeEdgeIds,\n                const vector<int> &posX,\n                const vector<int> &posY,\n                XorShift &rng,\n                vector<Op> &opsOut,\n                int &EOut) {\n    const int maxK = 10000;\n    vector<int> a = initial;\n\n    vector<Op> ops;\n    ops.reserve(maxK);\n\n    int K = 0;\n    int E = computeE(a, dEdges);\n\n    // Stage 1: bubble along parent-child edges (heapify-like)\n    const int limitStage1 = maxK * 8 / 10; // up to 8000 swaps\n    const int E_threshold = 30;            // stop Stage1 early if already low\n    const int recalc_interval = 256;\n\n    if (E > 0) {\n        int dM = (int)dEdges.size();\n        bool done = false;\n        while (K < limitStage1 && !done) {\n            bool swappedPass = false;\n            int start = rng.next_int(dM); // random starting position\n\n            for (int t = 0; t < dM && K < limitStage1; ++t) {\n                const Edge &ed = dEdges[(start + t) % dM];\n                int u = ed.u;\n                int v = ed.v;\n                if (a[u] > a[v]) {\n                    swap(a[u], a[v]);\n                    ops.push_back(Op{(short)posX[u], (short)posY[u],\n                                     (short)posX[v], (short)posY[v]});\n                    ++K;\n                    swappedPass = true;\n\n                    if ((K % recalc_interval == 0) || K >= limitStage1) {\n                        E = computeE(a, dEdges);\n                        if (E == 0 || E <= E_threshold || K >= limitStage1) {\n                            done = true;\n                            break;\n                        }\n                    }\n                }\n            }\n            if (!swappedPass) {\n                // No violating parent-child edge => E = 0\n                E = 0;\n                done = true;\n                break;\n            }\n        }\n    }\n\n    // Stage 2: greedy local search on all adjacent swaps\n    if (E != 0) {\n        E = computeE(a, dEdges); // ensure E is up-to-date\n        int M = (int)adjEdges.size();\n\n        while (K < maxK && E > 0) {\n            bool improved = false;\n            int start = rng.next_int(M);\n\n            for (int t = 0; t < M; ++t) {\n                const Edge &edge = adjEdges[(start + t) % M];\n                int u = edge.u;\n                int v = edge.v;\n\n                int delta = deltaE_for_swap(a, u, v, dEdges, nodeEdgeIds);\n                if (delta < 0) {\n                    swap(a[u], a[v]);\n                    ops.push_back(Op{(short)posX[u], (short)posY[u],\n                                     (short)posX[v], (short)posY[v]});\n                    ++K;\n                    E += delta;\n                    improved = true;\n                    break;\n                }\n            }\n            if (!improved) break; // local minimum w.r.t. single swap\n        }\n    }\n\n    opsOut.swap(ops);\n    EOut = E;\n}\n\n// ----- Main -----\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    const int N = 30;\n    const int numNodes = N * (N + 1) / 2;\n\n    // Read input and build id / coordinate mapping\n    vector<int> a0(numNodes);\n    vector<int> posX(numNodes), posY(numNodes);\n    vector<vector<int>> id(N);\n    int cur = 0;\n    for (int x = 0; x < N; ++x) {\n        id[x].resize(x + 1);\n        for (int y = 0; y <= x; ++y) {\n            id[x][y] = cur;\n            posX[cur] = x;\n            posY[cur] = y;\n            int v;\n            cin >> v;\n            a0[cur] = v;\n            ++cur;\n        }\n    }\n\n    // Build DAG edges (parent -> child)\n    vector<Edge> dEdges;\n    dEdges.reserve(2 * (N - 1) * N / 2);\n    for (int x = 0; x < N - 1; ++x) {\n        for (int y = 0; y <= x; ++y) {\n            int p = id[x][y];\n            int c1 = id[x + 1][y];\n            int c2 = id[x + 1][y + 1];\n            dEdges.push_back(Edge{p, c1});\n            dEdges.push_back(Edge{p, c2});\n        }\n    }\n\n    // For each node, list incident DAG edges (indices into dEdges)\n    vector<vector<int>> nodeEdgeIds(numNodes);\n    for (int ei = 0; ei < (int)dEdges.size(); ++ei) {\n        int u = dEdges[ei].u;\n        int v = dEdges[ei].v;\n        nodeEdgeIds[u].push_back(ei);\n        nodeEdgeIds[v].push_back(ei);\n    }\n\n    // Build adjacency edges of triangular grid\n    const int dx[6] = {-1, -1, 0, 0, 1, 1};\n    const int dy[6] = {-1, 0, -1, 1, 0, 1};\n    vector<Edge> adjEdges;\n    adjEdges.reserve(3 * numNodes); // rough upper bound\n\n    for (int x = 0; x < N; ++x) {\n        for (int y = 0; y <= x; ++y) {\n            int u = id[x][y];\n            for (int dir = 0; dir < 6; ++dir) {\n                int nx = x + dx[dir];\n                int ny = y + dy[dir];\n                if (nx < 0 || nx >= N) continue;\n                if (ny < 0 || ny > nx) continue;\n                int v = id[nx][ny];\n                if (v > u) { // avoid duplicates\n                    adjEdges.push_back(Edge{u, v});\n                }\n            }\n        }\n    }\n\n    XorShift rng(123456789);\n\n    // Multiple restarts; keep the best result\n    const int MAX_RESTARTS = 5;\n    vector<Op> bestOps;\n    int bestE = INT_MAX;\n    int bestK = INT_MAX;\n\n    for (int iter = 0; iter < MAX_RESTARTS; ++iter) {\n        vector<Op> curOps;\n        int curE;\n        run_single(a0, dEdges, adjEdges, nodeEdgeIds, posX, posY,\n                   rng, curOps, curE);\n        int curK = (int)curOps.size();\n\n        if (curE < bestE || (curE == bestE && curK < bestK)) {\n            bestE = curE;\n            bestK = curK;\n            bestOps = curOps;\n        }\n    }\n\n    // Output\n    cout << bestOps.size() << '\\n';\n    for (const auto &op : bestOps) {\n        cout << op.x1 << ' ' << op.y1 << ' '\n             << op.x2 << ' ' << op.y2 << '\\n';\n    }\n\n    return 0;\n}","toyota2023summer-final":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Cell {\n    int r, c, dist;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int D, N;\n    if (!(cin >> D >> N)) return 0;\n\n    const int er = 0;\n    const int ec = (D - 1) / 2;\n\n    vector<vector<bool>> isObstacle(D, vector<bool>(D, false));\n    for (int k = 0; k < N; ++k) {\n        int r, c;\n        cin >> r >> c;\n        isObstacle[r][c] = true;\n    }\n\n    // 1. Static BFS distances from entrance (obstacles only)\n    vector<vector<int>> dist(D, vector<int>(D, -1));\n    {\n        queue<pair<int,int>> q;\n        dist[er][ec] = 0;\n        q.push({er, ec});\n        const int dr[4] = {1, -1, 0, 0};\n        const int dc[4] = {0, 0, 1, -1};\n        while (!q.empty()) {\n            auto [r, c] = q.front(); q.pop();\n            for (int d = 0; d < 4; ++d) {\n                int nr = r + dr[d], nc = c + dc[d];\n                if (nr < 0 || nr >= D || nc < 0 || nc >= D) continue;\n                if (isObstacle[nr][nc]) continue;\n                if (dist[nr][nc] != -1) continue;\n                dist[nr][nc] = dist[r][c] + 1;\n                q.push({nr, nc});\n            }\n        }\n    }\n\n    // 2. Collect storeable cells (non-entrance, non-obstacle) with distances\n    vector<Cell> cells;\n    cells.reserve(D * D);\n    for (int r = 0; r < D; ++r) {\n        for (int c = 0; c < D; ++c) {\n            if (r == er && c == ec) continue;\n            if (isObstacle[r][c]) continue;\n            cells.push_back({r, c, dist[r][c]});\n        }\n    }\n    int M = (int)cells.size(); // = D^2 - 1 - N\n\n    // 3. Sort cells by distance, then row, then column\n    sort(cells.begin(), cells.end(), [](const Cell &a, const Cell &b) {\n        if (a.dist != b.dist) return a.dist < b.dist;\n        if (a.r != b.r) return a.r < b.r;\n        return a.c < b.c;\n    });\n\n    // 4. Rank mapping from (r,c) to index in cells[]\n    vector<vector<int>> rankIdx(D, vector<int>(D, -1));\n    for (int i = 0; i < M; ++i) {\n        rankIdx[cells[i].r][cells[i].c] = i;\n    }\n\n    // Occupancy and labels\n    vector<vector<bool>> hasContainer(D, vector<bool>(D, false));\n    vector<vector<int>> labelGrid(D, vector<int>(D, -1));\n    vector<bool> usedRank(M, false);\n\n    auto bfs_count_reachable_empty = [&](void) -> int {\n        // BFS over empty cells (no obstacles, no containers)\n        vector<vector<char>> vis(D, vector<char>(D, 0));\n        queue<pair<int,int>> q;\n        vis[er][ec] = 1;\n        q.push({er, ec});\n        const int dr[4] = {1, -1, 0, 0};\n        const int dc[4] = {0, 0, 1, -1};\n        while (!q.empty()) {\n            auto [r, c] = q.front(); q.pop();\n            for (int d = 0; d < 4; ++d) {\n                int nr = r + dr[d], nc = c + dc[d];\n                if (nr < 0 || nr >= D || nc < 0 || nc >= D) continue;\n                if (vis[nr][nc]) continue;\n                if (isObstacle[nr][nc]) continue;\n                if (hasContainer[nr][nc]) continue;\n                vis[nr][nc] = 1;\n                q.push({nr, nc});\n            }\n        }\n        int cnt = 0;\n        for (int r = 0; r < D; ++r) {\n            for (int c = 0; c < D; ++c) {\n                if (r == er && c == ec) continue;\n                if (isObstacle[r][c]) continue;\n                if (hasContainer[r][c]) continue;\n                if (vis[r][c]) ++cnt;\n            }\n        }\n        return cnt;\n    };\n\n    auto is_safe_index = [&](int idx, int placed) -> bool {\n        const Cell &cell = cells[idx];\n        int r = cell.r, c = cell.c;\n        // temporarily place container\n        hasContainer[r][c] = true;\n        int reachableEmpty = bfs_count_reachable_empty();\n        hasContainer[r][c] = false;\n\n        int emptiesAfter = M - (placed + 1);\n        return reachableEmpty == emptiesAfter;\n    };\n\n    // 5. Storage phase\n    for (int step = 0; step < M; ++step) {\n        int t;\n        cin >> t;\n        int targetIdx = t; // ideal position index\n\n        int chosenIdx = -1;\n\n        // Try ideal index first if unused\n        if (0 <= targetIdx && targetIdx < M && !usedRank[targetIdx]) {\n            if (is_safe_index(targetIdx, step)) {\n                chosenIdx = targetIdx;\n            }\n        }\n\n        if (chosenIdx == -1) {\n            int bestCost = INT_MAX;\n            // Scan all unused cells and pick safe one closest to targetIdx\n            for (int i = 0; i < M; ++i) {\n                if (usedRank[i]) continue;\n                if (!is_safe_index(i, step)) continue;\n                int cost = (0 <= targetIdx && targetIdx < M) ? abs(i - targetIdx) : 0;\n                if (cost < bestCost) {\n                    bestCost = cost;\n                    chosenIdx = i;\n                }\n            }\n            // In theory chosenIdx should always be set; fallback just in case.\n            if (chosenIdx == -1) {\n                for (int i = 0; i < M; ++i) {\n                    if (!usedRank[i]) {\n                        chosenIdx = i;\n                        break;\n                    }\n                }\n            }\n        }\n\n        usedRank[chosenIdx] = true;\n        int r = cells[chosenIdx].r;\n        int c = cells[chosenIdx].c;\n        hasContainer[r][c] = true;\n        labelGrid[r][c] = t;\n\n        cout << r << ' ' << c << '\\n' << flush;\n    }\n\n    // 6. Retrieval phase\n\n    auto bfs_reachable_empty = [&](vector<vector<char>> &vis) {\n        vis.assign(D, vector<char>(D, 0));\n        queue<pair<int,int>> q;\n        vis[er][ec] = 1;\n        q.push({er, ec});\n        const int dr[4] = {1, -1, 0, 0};\n        const int dc[4] = {0, 0, 1, -1};\n        while (!q.empty()) {\n            auto [r, c] = q.front(); q.pop();\n            for (int d = 0; d < 4; ++d) {\n                int nr = r + dr[d], nc = c + dc[d];\n                if (nr < 0 || nr >= D || nc < 0 || nc >= D) continue;\n                if (vis[nr][nc]) continue;\n                if (isObstacle[nr][nc]) continue;\n                if (hasContainer[nr][nc]) continue;\n                vis[nr][nc] = 1;\n                q.push({nr, nc});\n            }\n        }\n    };\n\n    const int dr[4] = {1, -1, 0, 0};\n    const int dc[4] = {0, 0, 1, -1};\n\n    vector<vector<char>> vis;\n    for (int step = 0; step < M; ++step) {\n        bfs_reachable_empty(vis);\n\n        int bestLabel = INT_MAX;\n        int bestR = -1, bestC = -1;\n\n        for (int r = 0; r < D; ++r) {\n            for (int c = 0; c < D; ++c) {\n                if (!hasContainer[r][c]) continue;\n                bool accessible = false;\n                for (int d = 0; d < 4; ++d) {\n                    int nr = r + dr[d], nc = c + dc[d];\n                    if (nr < 0 || nr >= D || nc < 0 || nc >= D) continue;\n                    if (isObstacle[nr][nc]) continue;\n                    if (hasContainer[nr][nc]) continue; // neighbor must be empty\n                    if (vis[nr][nc]) {\n                        accessible = true;\n                        break;\n                    }\n                }\n                if (!accessible) continue;\n                int lbl = labelGrid[r][c];\n                if (lbl < bestLabel) {\n                    bestLabel = lbl;\n                    bestR = r;\n                    bestC = c;\n                }\n            }\n        }\n\n        // Fallback (should not happen if storage kept empties connected)\n        if (bestR == -1) {\n            for (int r = 0; r < D && bestR == -1; ++r)\n                for (int c = 0; c < D && bestR == -1; ++c)\n                    if (hasContainer[r][c]) {\n                        bestR = r;\n                        bestC = c;\n                    }\n        }\n\n        cout << bestR << ' ' << bestC << '\\n';\n        hasContainer[bestR][bestC] = false;\n        labelGrid[bestR][bestC] = -1;\n    }\n\n    cout.flush();\n    return 0;\n}","ahc024":"#include <bits/stdc++.h>\nusing namespace std;\n\n// Global parameters (read from input)\nint n, m;\n\n// Original and current grids\nvector<vector<int>> orig_grid;\nvector<vector<int>> cur_grid;\n\n// Original adjacency matrix, and a temporary one for checks\n// adj[c][d] = true iff colors c and d are adjacent somewhere (0..m)\nbool adj_orig[101][101];\nbool adj_tmp[101][101];\n\n// Which colors may be adjacent to 0 (i.e., touched the boundary originally)\nbool allowedZeroAdj[101];\n\n// Directions for 4-neighbor moves\nconst int DX[4] = {1, -1, 0, 0};\nconst int DY[4] = {0, 0, 1, -1};\n\n// Compute adjacency matrix for a given grid\nvoid computeAdj(const vector<vector<int>> &g, bool adj[101][101]) {\n    for (int i = 0; i <= m; i++) {\n        for (int j = 0; j <= m; j++) {\n            adj[i][j] = false;\n        }\n    }\n\n    // Internal adjacency\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            int a = g[i][j];\n            if (i + 1 < n) {\n                int b = g[i + 1][j];\n                if (a != b) {\n                    adj[a][b] = adj[b][a] = true;\n                }\n            }\n            if (j + 1 < n) {\n                int b = g[i][j + 1];\n                if (a != b) {\n                    adj[a][b] = adj[b][a] = true;\n                }\n            }\n        }\n    }\n\n    // Adjacency with outside (color 0) via boundary cells\n    for (int i = 0; i < n; i++) {\n        int c1 = g[i][0];\n        if (c1 != 0) adj[0][c1] = adj[c1][0] = true;\n        int c2 = g[i][n - 1];\n        if (c2 != 0) adj[0][c2] = adj[c2][0] = true;\n    }\n    for (int j = 1; j < n - 1; j++) {\n        int c1 = g[0][j];\n        if (c1 != 0) adj[0][c1] = adj[c1][0] = true;\n        int c2 = g[n - 1][j];\n        if (c2 != 0) adj[0][c2] = adj[c2][0] = true;\n    }\n}\n\n// BFS to check connectivity of a given color in the grid\nbool isConnectedColor(int color, const vector<vector<int>> &g) {\n    int N = n * n;\n    static vector<char> vis;\n    if ((int)vis.size() != N) vis.assign(N, 0);\n    else fill(vis.begin(), vis.end(), 0);\n\n    int start = -1;\n    for (int i = 0; i < n && start == -1; i++) {\n        for (int j = 0; j < n; j++) {\n            if (g[i][j] == color) {\n                start = i * n + j;\n                break;\n            }\n        }\n    }\n    if (start == -1) {\n        // Should not happen because we ensure countColor[color] >= 1 when calling\n        return false;\n    }\n\n    queue<int> q;\n    vis[start] = 1;\n    q.push(start);\n\n    while (!q.empty()) {\n        int v = q.front(); q.pop();\n        int x = v / n;\n        int y = v % n;\n        for (int dir = 0; dir < 4; dir++) {\n            int nx = x + DX[dir];\n            int ny = y + DY[dir];\n            if (nx < 0 || nx >= n || ny < 0 || ny >= n) continue;\n            if (g[nx][ny] == color) {\n                int idx = nx * n + ny;\n                if (!vis[idx]) {\n                    vis[idx] = 1;\n                    q.push(idx);\n                }\n            }\n        }\n    }\n\n    // Verify all cells of this color were visited\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            if (g[i][j] == color && !vis[i * n + j]) {\n                return false;\n            }\n        }\n    }\n    return true;\n}\n\n// Compare current adjacency with original\nbool sameAdj() {\n    for (int c = 0; c <= m; c++) {\n        for (int d = c + 1; d <= m; d++) {\n            if (adj_orig[c][d] != adj_tmp[c][d]) return false;\n        }\n    }\n    return true;\n}\n\n// Try to change cell (x, y) to color 0\nbool tryChange(int x, int y, vector<vector<int>> &cur, vector<int> &countColor) {\n    int col = cur[x][y];\n    if (col == 0) return false;\n    if (countColor[col] <= 1) return false; // keep at least one cell per color\n\n    // Ensure this cell is on boundary or adjacent to an existing 0 (for 0-connectivity)\n    bool boundaryCell = (x == 0 || x == n - 1 || y == 0 || y == n - 1);\n    bool adjacentZero = false;\n    for (int dir = 0; dir < 4; dir++) {\n        int nx = x + DX[dir];\n        int ny = y + DY[dir];\n        if (nx < 0 || nx >= n || ny < 0 || ny >= n) continue;\n        if (cur[nx][ny] == 0) {\n            adjacentZero = true;\n            break;\n        }\n    }\n    if (!boundaryCell && !adjacentZero) return false;\n\n    // Ensure we don't create new 0\u2013d adjacencies\n    for (int dir = 0; dir < 4; dir++) {\n        int nx = x + DX[dir];\n        int ny = y + DY[dir];\n        if (nx < 0 || nx >= n || ny < 0 || ny >= n) continue;\n        int neighborColor = cur[nx][ny];\n        if (!allowedZeroAdj[neighborColor]) {\n            return false;\n        }\n    }\n\n    // Degree of this cell in its color's component\n    int sameNei = 0;\n    for (int dir = 0; dir < 4; dir++) {\n        int nx = x + DX[dir];\n        int ny = y + DY[dir];\n        if (nx < 0 || nx >= n || ny < 0 || ny >= n) continue;\n        if (cur[nx][ny] == col) sameNei++;\n    }\n    bool needBFS = (sameNei >= 2);\n\n    // Apply tentative change\n    cur[x][y] = 0;\n    countColor[col]--;\n    countColor[0]++;\n\n    bool ok = true;\n\n    // Check connectivity of the original color if needed\n    if (needBFS) {\n        if (!isConnectedColor(col, cur)) ok = false;\n    }\n\n    // Check adjacency graph\n    if (ok) {\n        computeAdj(cur, adj_tmp);\n        if (!sameAdj()) ok = false;\n    }\n\n    // Revert if invalid\n    if (!ok) {\n        cur[x][y] = col;\n        countColor[col]++;\n        countColor[0]--;\n        return false;\n    }\n    return true;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> n >> m;\n    orig_grid.assign(n, vector<int>(n));\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            cin >> orig_grid[i][j];\n        }\n    }\n\n    // Compute original adjacency\n    computeAdj(orig_grid, adj_orig);\n\n    // Colors allowed to touch 0\n    for (int c = 0; c <= m; c++) {\n        allowedZeroAdj[c] = adj_orig[0][c];\n    }\n    allowedZeroAdj[0] = true; // 0 can touch itself\n\n    // Initialize current grid and color counts\n    cur_grid = orig_grid;\n    vector<int> countColor(m + 1, 0);\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            countColor[cur_grid[i][j]]++;\n        }\n    }\n    // countColor[0] is initially zero inside the grid\n\n    // Queue-based expansion from boundary\n    int N = n * n;\n    vector<char> inQueue(N, false);\n    deque<int> q;\n\n    // Initialize queue with all boundary cells\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            if (i == 0 || i == n - 1 || j == 0 || j == n - 1) {\n                int idx = i * n + j;\n                if (!inQueue[idx]) {\n                    inQueue[idx] = true;\n                    q.push_back(idx);\n                }\n            }\n        }\n    }\n\n    // Deterministic RNG to slightly randomize neighbor processing order\n    std::mt19937_64 rng(123456789);\n\n    while (!q.empty()) {\n        int idx = q.front();\n        q.pop_front();\n        inQueue[idx] = false;\n\n        int x = idx / n;\n        int y = idx % n;\n\n        if (cur_grid[x][y] == 0) continue; // already turned to 0\n\n        if (tryChange(x, y, cur_grid, countColor)) {\n            // If successful, its neighbors may now be removable\n            for (int dir = 0; dir < 4; dir++) {\n                int nx = x + DX[dir];\n                int ny = y + DY[dir];\n                if (nx < 0 || nx >= n || ny < 0 || ny >= n) continue;\n                if (cur_grid[nx][ny] == 0) continue; // no need to revisit zeros\n                int idx2 = nx * n + ny;\n                if (!inQueue[idx2]) {\n                    inQueue[idx2] = true;\n                    // Randomly push front or back to add some variation\n                    if (rng() & 1) q.push_back(idx2);\n                    else q.push_front(idx2);\n                }\n            }\n        }\n    }\n\n    // Output final grid\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            if (j) cout << ' ';\n            cout << cur_grid[i][j];\n        }\n        cout << '\\n';\n    }\n\n    return 0;\n}","ahc025":"#include <bits/stdc++.h>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, D, Q;\n    if (!(cin >> N >> D >> Q)) return 0;\n\n    // Store pairwise queries and results\n    vector<int> A(Q), B(Q);   // items in each query\n    vector<int> Y(Q);         // label: +1 if A[q] heavier, -1 if B[q] heavier, 0 if '='\n\n    vector<int> matchCount(N, 0);\n    static bool used[100][100];  // N <= 100, symmetric\n\n    mt19937 rng(712367821);\n\n    vector<int> order(N);\n    iota(order.begin(), order.end(), 0);\n\n    // ---- Query phase: perform exactly Q pairwise comparisons ----\n    for (int q = 0; q < Q; ++q) {\n        // Choose a pair (a, b) that keeps match counts balanced and avoids repeats\n        sort(order.begin(), order.end(), [&](int i, int j) {\n            if (matchCount[i] != matchCount[j]) return matchCount[i] < matchCount[j];\n            return i < j;\n        });\n\n        int a = -1, b = -1;\n        bool found = false;\n        int K = min(N, 10);\n\n        // Try to find a new pair among the K least-used items\n        for (int attempt = 0; attempt < K * 5 && !found; ++attempt) {\n            int ui = rng() % K;\n            int vi = rng() % K;\n            if (ui == vi) continue;\n            int i = order[ui];\n            int j = order[vi];\n            if (i > j) swap(i, j);\n            if (!used[i][j]) {\n                a = i;\n                b = j;\n                found = true;\n            }\n        }\n\n        // Fallback: random pairs avoiding used ones if possible\n        if (!found) {\n            for (int attempt = 0; attempt < N * N && !found; ++attempt) {\n                int i = rng() % N;\n                int j = rng() % N;\n                if (i == j) continue;\n                if (i > j) swap(i, j);\n                if (!used[i][j]) {\n                    a = i;\n                    b = j;\n                    found = true;\n                }\n            }\n        }\n\n        // If all pairs are used (very unlikely since Q < N(N-1)/2), just pick any pair\n        if (!found) {\n            do {\n                a = rng() % N;\n                b = rng() % N;\n            } while (a == b);\n            if (a > b) swap(a, b);\n        }\n\n        used[a][b] = used[b][a] = true;\n        matchCount[a]++;\n        matchCount[b]++;\n        A[q] = a;\n        B[q] = b;\n\n        // Output the query: 1 item on each side\n        cout << 1 << ' ' << 1 << ' ' << a << ' ' << b << '\\n';\n        cout.flush();\n\n        // Read the result\n        string res;\n        if (!(cin >> res)) return 0;\n        if (res[0] == '>') {\n            Y[q] = +1;  // A heavier than B\n        } else if (res[0] == '<') {\n            Y[q] = -1;  // B heavier than A\n        } else {\n            Y[q] = 0;   // '=' (very rare)\n        }\n    }\n\n    // ---- Offline rating (Bradley\u2013Terry style logistic regression) ----\n    vector<double> r(N, 0.0);  // ratings\n\n    const int ITER = 80;\n    const double base_eta = 0.5;\n\n    bool hasInfo = false;\n    for (int q = 0; q < Q; ++q) if (Y[q] != 0) { hasInfo = true; break; }\n\n    if (hasInfo) {\n        for (int iter = 0; iter < ITER; ++iter) {\n            double eta = base_eta / (1.0 + 0.1 * iter);\n            for (int q = 0; q < Q; ++q) {\n                int y = Y[q];\n                if (y == 0) continue;  // skip ties\n                int a = A[q], b = B[q];\n                double s = r[a] - r[b];\n                double z = (double) y * s;\n\n                // Avoid overflow; if z is large positive, gradient ~ 0\n                if (z > 40.0) continue;\n\n                double g;\n                if (z < -40.0) {\n                    g = (double) y;  // ~ y / (1 + 0) = y\n                } else {\n                    g = (double) y / (1.0 + std::exp(z));\n                }\n                double step = eta * g;\n                r[a] += step;\n                r[b] -= step;\n            }\n        }\n    }\n\n    // ---- Map ratings to approximate weights using exponential order statistics ----\n    vector<int> idx(N);\n    iota(idx.begin(), idx.end(), 0);\n    // Larger rating => heavier\n    sort(idx.begin(), idx.end(), [&](int i, int j) {\n        if (r[i] != r[j]) return r[i] > r[j];\n        return i < j;\n    });\n\n    vector<double> wAsc(N);  // expected Exp(lambda) order statistics, ascending\n    const double lambda = 1e-5;\n    double acc = 0.0;\n    for (int k = 1; k <= N; ++k) {\n        acc += 1.0 / (lambda * (N - k + 1));  // increment for kth smallest\n        wAsc[k - 1] = acc;\n    }\n    // Clamp to generation max (not strictly necessary, but harmless)\n    double wmax = 1e5 * (double) N / (double) D;\n    for (int i = 0; i < N; ++i) {\n        if (wAsc[i] > wmax) wAsc[i] = wmax;\n    }\n\n    vector<double> weight(N);\n    if (hasInfo) {\n        // Assign heaviest rating to largest expected weight\n        for (int pos = 0; pos < N; ++pos) {\n            int item = idx[pos];\n            double w_est = wAsc[N - 1 - pos];\n            weight[item] = w_est;\n        }\n    } else {\n        // Degenerate case: no information (almost impossible); use equal weights\n        for (int i = 0; i < N; ++i) weight[i] = 1.0;\n    }\n\n    // ---- Partitioning: greedy + local search ----\n\n    // Greedy initialization (largest weight first)\n    vector<int> assign(N, -1);\n    vector<double> binSum(D, 0.0);\n\n    vector<int> ord(N);\n    iota(ord.begin(), ord.end(), 0);\n    sort(ord.begin(), ord.end(), [&](int i, int j) {\n        if (weight[i] != weight[j]) return weight[i] > weight[j];\n        return i < j;\n    });\n\n    for (int id : ord) {\n        int bestBin = 0;\n        double bestSum = binSum[0];\n        for (int k = 1; k < D; ++k) {\n            if (binSum[k] < bestSum) {\n                bestSum = binSum[k];\n                bestBin = k;\n            }\n        }\n        assign[id] = bestBin;\n        binSum[bestBin] += weight[id];\n    }\n\n    // Local search (moves + swaps) on approximate objective\n    double totalW = 0.0;\n    for (double x : weight) totalW += x;\n    double target = totalW / D;\n    const double EPS = 1e-9;\n    const int MAX_ITERS_LS = 10000;\n\n    int guard = 0;\n    while (true) {\n        bool improved = false;\n\n        // Single-item moves\n        for (int i = 0; i < N && !improved; ++i) {\n            int ai = assign[i];\n            double wi = weight[i];\n            double sa = binSum[ai];\n            double oldA = (sa - target) * (sa - target);\n            for (int k = 0; k < D; ++k) {\n                if (k == ai) continue;\n                double sb = binSum[k];\n                double oldB = (sb - target) * (sb - target);\n                double newSa = sa - wi;\n                double newSb = sb + wi;\n                double newCost = (newSa - target) * (newSa - target)\n                               + (newSb - target) * (newSb - target);\n                double oldCost = oldA + oldB;\n                if (newCost + EPS < oldCost) {\n                    // Apply move\n                    binSum[ai] -= wi;\n                    binSum[k] += wi;\n                    assign[i] = k;\n                    improved = true;\n                    break;\n                }\n            }\n        }\n\n        // Pair swaps\n        if (!improved) {\n            for (int i = 0; i < N && !improved; ++i) {\n                for (int j = i + 1; j < N; ++j) {\n                    int ai = assign[i];\n                    int aj = assign[j];\n                    if (ai == aj) continue;\n                    double wi = weight[i];\n                    double wj = weight[j];\n                    double sa = binSum[ai];\n                    double sb = binSum[aj];\n                    double oldCost = (sa - target) * (sa - target)\n                                   + (sb - target) * (sb - target);\n                    double newSa = sa - wi + wj;\n                    double newSb = sb - wj + wi;\n                    double newCost = (newSa - target) * (newSa - target)\n                                   + (newSb - target) * (newSb - target);\n                    if (newCost + EPS < oldCost) {\n                        binSum[ai] = newSa;\n                        binSum[aj] = newSb;\n                        swap(assign[i], assign[j]);\n                        improved = true;\n                        break;\n                    }\n                }\n            }\n        }\n\n        if (!improved) break;\n        if (++guard > MAX_ITERS_LS) break;\n    }\n\n    // ---- Final output: assignments d_0 ... d_{N-1} ----\n    for (int i = 0; i < N; ++i) {\n        if (i) cout << ' ';\n        cout << assign[i];\n    }\n    cout << '\\n';\n    cout.flush();\n\n    return 0;\n}","ahc026":"#include <bits/stdc++.h>\nusing namespace std;\n\n// Simple xorshift RNG\nstruct XorShift {\n    unsigned long long x;\n    XorShift(unsigned long long seed = 88172645463325252ULL) : x(seed) {}\n    unsigned long long next() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return x;\n    }\n};\n\nstruct Params {\n    int wSmall; // weight for number of \"small\" elements below the group\n    int wSize;  // weight for stack size\n    int wMin;   // weight for minimum element in the stack (reward for large min)\n    int wRand;  // max random noise added to score (0 => no noise)\n};\n\n// Move suffix starting at index startIdx in stack src to top of stack dest\nstatic void moveSuffix(vector<vector<int>>& stacks,\n                       vector<int>& stackOf,\n                       vector<int>& posInStack,\n                       int src, int startIdx, int dest) {\n    if (src == dest) return;\n    auto &S = stacks[src];\n    auto &D = stacks[dest];\n    int oldSizeS = (int)S.size();\n    for (int i = startIdx; i < oldSizeS; i++) {\n        int box = S[i];\n        stackOf[box] = dest;\n        posInStack[box] = (int)D.size();\n        D.push_back(box);\n    }\n    S.resize(startIdx);\n}\n\n// Choose destination stack for the suffix above v\nstatic int chooseDestStack(const vector<vector<int>>& stacks,\n                           int src, int startIdx,\n                           const Params& P,\n                           XorShift& rng) {\n    int m = (int)stacks.size();\n\n    // Prefer an empty stack if available\n    for (int t = 0; t < m; t++) {\n        if (t == src) continue;\n        if (stacks[t].empty()) return t;\n    }\n\n    const auto& S = stacks[src];\n    int gmax = 0;\n    for (int i = startIdx; i < (int)S.size(); i++) {\n        if (S[i] > gmax) gmax = S[i];\n    }\n\n    int best = -1;\n    long long bestScore = (1LL << 60);\n    int bestZero = -1;       // best stack with cntSmall==0\n    int bestZeroSize = INT_MAX;\n\n    for (int t = 0; t < m; t++) {\n        if (t == src) continue;\n        const auto& T = stacks[t];\n        int cntSmall = 0;\n        int minT = INT_MAX;\n        for (int u : T) {\n            if (u < gmax) cntSmall++;\n            if (u < minT) minT = u;\n        }\n\n        if (cntSmall == 0) {\n            if ((int)T.size() < bestZeroSize) {\n                bestZeroSize = (int)T.size();\n                bestZero = t;\n            }\n        }\n\n        long long score = 0;\n        score += (long long)P.wSmall * cntSmall;\n        score += (long long)P.wSize * (int)T.size();\n        if (minT != INT_MAX) score -= (long long)P.wMin * minT;\n        if (P.wRand) score += (long long)(rng.next() % P.wRand);\n\n        if (score < bestScore) {\n            bestScore = score;\n            best = t;\n        }\n    }\n\n    if (bestZero != -1) return bestZero;\n    return best;\n}\n\n// Run one full simulation with given parameters, return (energy, operations)\nstatic pair<long long, vector<pair<int,int>>>\nrunOnce(const vector<vector<int>>& initStacks,\n        const vector<int>& initStackOf,\n        const vector<int>& initPosInStack,\n        int n, int m,\n        const Params& P,\n        XorShift& rng) {\n    vector<vector<int>> stacks = initStacks;\n    vector<int> stackOf = initStackOf;\n    vector<int> posInStack = initPosInStack;\n\n    vector<pair<int,int>> ops;\n    ops.reserve(2 * n);\n\n    long long energy = 0;\n\n    for (int v = 1; v <= n; v++) {\n        int s = stackOf[v];\n        int idx = posInStack[v];\n\n        // If v is not at the top, move the suffix above it\n        if (idx != (int)stacks[s].size() - 1) {\n            int startIdx = idx + 1; // suffix starts at the box above v\n            int dest = chooseDestStack(stacks, s, startIdx, P, rng);\n            int pivot = stacks[s][startIdx];\n            // Operation 1: move suffix starting at 'pivot' to stack 'dest'\n            ops.emplace_back(pivot, dest + 1); // stacks are 1-based in output\n            int moved = (int)stacks[s].size() - startIdx;\n            energy += moved + 1;\n            moveSuffix(stacks, stackOf, posInStack, s, startIdx, dest);\n        }\n\n        // Now v should be at the top of its stack\n        s = stackOf[v];\n        auto &S = stacks[s];\n        // Operation 2: remove v\n        ops.emplace_back(v, 0);\n        S.pop_back();\n        stackOf[v] = -1;\n        posInStack[v] = -1;\n    }\n\n    return {energy, ops};\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int n, m;\n    if (!(cin >> n >> m)) return 0;\n\n    vector<vector<int>> initStacks(m);\n    vector<int> initStackOf(n + 1);\n    vector<int> initPosInStack(n + 1);\n\n    int perStack = n / m;\n    for (int i = 0; i < m; i++) {\n        initStacks[i].resize(perStack);\n        for (int j = 0; j < perStack; j++) {\n            int x;\n            cin >> x;\n            initStacks[i][j] = x;\n            initStackOf[x] = i;\n            initPosInStack[x] = j;\n        }\n    }\n\n    XorShift rng((unsigned long long)chrono::steady_clock::now()\n                     .time_since_epoch().count());\n\n    // Baseline deterministic parameters\n    Params base;\n    base.wSmall = 1000;\n    base.wSize  = 1;\n    base.wMin   = 1;\n    base.wRand  = 0;\n\n    vector<pair<int,int>> bestOps;\n    long long bestEnergy;\n\n    auto res0 = runOnce(initStacks, initStackOf, initPosInStack,\n                        n, m, base, rng);\n    bestEnergy = res0.first;\n    bestOps = move(res0.second);\n\n    // Additional randomized runs\n    const int totalRuns = 30; // 1 baseline + 29 random\n\n    for (int iter = 1; iter < totalRuns; iter++) {\n        Params P;\n        P.wSmall = 500 + (int)(rng.next() % 501); // 500..1000\n        P.wSize  = (int)(rng.next() % 5);         // 0..4\n        P.wMin   = (int)(rng.next() % 5);         // 0..4\n        P.wRand  = (int)(rng.next() % 1000);      // 0..999\n\n        auto res = runOnce(initStacks, initStackOf, initPosInStack,\n                           n, m, P, rng);\n        if (res.first < bestEnergy) {\n            bestEnergy = res.first;\n            bestOps = move(res.second);\n        }\n    }\n\n    // Output best sequence of operations\n    for (auto &op : bestOps) {\n        cout << op.first << ' ' << op.second << '\\n';\n    }\n\n    return 0;\n}","ahc027":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Edge {\n    int to;\n    char dir; // direction from current node to 'to'\n};\n\nstatic uint64_t rng_state = 123456789ULL;\n\nstatic inline uint64_t xorshift64() {\n    uint64_t x = rng_state;\n    x ^= x << 7;\n    x ^= x >> 9;\n    rng_state = x;\n    return x;\n}\n\n// Uniform double in [0,1)\nstatic inline double rand_double() {\n    return (xorshift64() & ((1ULL << 53) - 1)) * (1.0 / (1ULL << 53));\n}\n\nchar revdir(char c) {\n    if (c == 'U') return 'D';\n    if (c == 'D') return 'U';\n    if (c == 'L') return 'R';\n    return 'L'; // c == 'R'\n}\n\nint N;\nvector<string> hgrid; // vertical walls between (i,j) and (i+1,j), size (N-1) x N\nvector<string> vgrid; // horizontal walls between (i,j) and (i,j+1), size N x (N-1)\nvector<int> dflat;    // flattened d[i][j] of size N*N\nvector<vector<Edge>> adj; // adjacency list for all cells\n\nvector<int> dist_bfs;\nvector<int> parent_bfs;\nvector<char> pdir_bfs;     // direction from parent to node (in BFS tree)\nvector<vector<int>> children; // children in BFS tree used for DFS cover\n\nstring route;\n\n// DFS over BFS tree to build covering tour (edge-doubling)\nvoid dfs_cover(int u) {\n    for (int v : children[u]) {\n        char dir = pdir_bfs[v];     // direction from u to v\n        route.push_back(dir);       // go to child\n        dfs_cover(v);\n        route.push_back(revdir(dir)); // come back to parent\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N;\n    hgrid.resize(N - 1);\n    for (int i = 0; i < N - 1; i++) {\n        cin >> hgrid[i];\n    }\n    vgrid.resize(N);\n    for (int i = 0; i < N; i++) {\n        cin >> vgrid[i];\n    }\n\n    dflat.assign(N * N, 0);\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            int x;\n            cin >> x;\n            dflat[i * N + j] = x;\n        }\n    }\n\n    int V = N * N;\n    adj.assign(V, {});\n\n    // Build adjacency graph\n    auto in_bounds = [&](int i, int j) {\n        return 0 <= i && i < N && 0 <= j && j < N;\n    };\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            int id = i * N + j;\n            // Up: (i-1,j)\n            if (i > 0 && hgrid[i - 1][j] == '0') {\n                int to = (i - 1) * N + j;\n                adj[id].push_back({to, 'U'});\n            }\n            // Down: (i+1,j)\n            if (i < N - 1 && hgrid[i][j] == '0') {\n                int to = (i + 1) * N + j;\n                adj[id].push_back({to, 'D'});\n            }\n            // Left: (i,j-1)\n            if (j > 0 && vgrid[i][j - 1] == '0') {\n                int to = i * N + (j - 1);\n                adj[id].push_back({to, 'L'});\n            }\n            // Right: (i,j+1)\n            if (j < N - 1 && vgrid[i][j] == '0') {\n                int to = i * N + (j + 1);\n                adj[id].push_back({to, 'R'});\n            }\n        }\n    }\n\n    // Sort adjacency of each node so that neighbors with larger d are considered first\n    for (int u = 0; u < V; u++) {\n        sort(adj[u].begin(), adj[u].end(), [&](const Edge &a, const Edge &b) {\n            return dflat[a.to] > dflat[b.to];\n        });\n    }\n\n    // BFS from root (0,0) to:\n    //  - build a BFS tree (parent_bfs + pdir_bfs),\n    //  - compute distances (dist_bfs),\n    //  - get Dmax (max dist).\n    int root = 0;\n    dist_bfs.assign(V, -1);\n    parent_bfs.assign(V, -1);\n    pdir_bfs.assign(V, 0);\n    queue<int> q;\n    dist_bfs[root] = 0;\n    parent_bfs[root] = root;\n    q.push(root);\n\n    while (!q.empty()) {\n        int u = q.front();\n        q.pop();\n        for (const auto &e : adj[u]) {\n            int v = e.to;\n            if (dist_bfs[v] == -1) {\n                dist_bfs[v] = dist_bfs[u] + 1;\n                parent_bfs[v] = u;\n                pdir_bfs[v] = e.dir;  // direction parent -> v\n                q.push(v);\n            }\n        }\n    }\n\n    int Dmax = 0;\n    for (int i = 0; i < V; i++) {\n        if (dist_bfs[i] > Dmax) Dmax = dist_bfs[i];\n    }\n\n    // Build children list of BFS tree for DFS covering tour\n    children.assign(V, {});\n    for (int v = 0; v < V; v++) {\n        if (v == root) continue;\n        int p = parent_bfs[v];\n        if (p >= 0 && p < V) {\n            children[p].push_back(v);\n        }\n    }\n\n    // Covering tour via DFS on BFS tree\n    route.clear();\n    dfs_cover(root);\n    int L_cover = (int)route.size(); // length of covering segment\n\n    const int L_MAX = 100000;\n\n    // Precompute sqrt(d) weights for biased random walk\n    vector<double> weight(V);\n    for (int i = 0; i < V; i++) {\n        weight[i] = sqrt((double)dflat[i]);\n    }\n\n    // Random walk steps allowed so that we still have enough room to return to root\n    int S = L_MAX - L_cover - Dmax;\n    if (S < 0) S = 0; // extremely unlikely with given constraints, but safe-guard\n\n    int pos = root;\n\n    // Biased random walk part\n    for (int step = 0; step < S; step++) {\n        auto &nb = adj[pos];\n        int deg = (int)nb.size();\n        if (deg == 0) {\n            // Should not happen: graph is connected, so every node has at least one neighbor\n            break;\n        }\n        double sumw = 0.0;\n        for (const auto &e : nb) {\n            sumw += weight[e.to];\n        }\n        double r = rand_double() * sumw;\n        double acc = 0.0;\n        int chosen_idx = deg - 1; // fallback\n        for (int k = 0; k < deg; k++) {\n            acc += weight[nb[k].to];\n            if (acc >= r) {\n                chosen_idx = k;\n                break;\n            }\n        }\n        const auto &e = nb[chosen_idx];\n        route.push_back(e.dir);\n        pos = e.to;\n    }\n\n    // Return to root along BFS tree\n    int cur = pos;\n    while (cur != root) {\n        int p = parent_bfs[cur];\n        char dir = revdir(pdir_bfs[cur]); // move from cur to parent\n        route.push_back(dir);\n        cur = p;\n    }\n\n    // Safety: ensure route length within limit\n    if ((int)route.size() > L_MAX) {\n        // In very unlikely case, truncate (still a valid route but may not return to root).\n        // But given the construction, this should not happen.\n        route.resize(L_MAX);\n    }\n\n    cout << route << '\\n';\n    return 0;\n}","ahc028":"#include <bits/stdc++.h>\nusing namespace std;\n\n// Large enough INF for costs (max ~ 5000*29 = 145000)\nconst int INF = 1e9;\n\n// Compute overlap length: max k in [0..4] such that\n// suffix of a of length k == prefix of b of length k.\nint compute_overlap(const string &a, const string &b) {\n    const int L = 5;\n    for (int k = L - 1; k >= 1; --k) { // k=4..1\n        bool ok = true;\n        for (int i = 0; i < k; ++i) {\n            if (a[L - k + i] != b[i]) {\n                ok = false;\n                break;\n            }\n        }\n        if (ok) return k;\n    }\n    return 0;\n}\n\n// Local search: adjacent swaps to improve total overlap\nint local_search_adjacent_swaps(vector<int> &path, const vector<vector<int>> &ov) {\n    int M = (int)path.size();\n    if (M <= 1) return 0;\n\n    // Edge overlaps\n    vector<int> edgeOv(max(0, M - 1));\n    int totalOv = 0;\n    for (int i = 0; i + 1 < M; ++i) {\n        int val = ov[path[i]][path[i + 1]];\n        edgeOv[i] = val;\n        totalOv += val;\n    }\n\n    if (M <= 2) {\n        return totalOv; // nothing to improve\n    }\n\n    bool improved = true;\n    while (improved) {\n        improved = false;\n        for (int i = 0; i < M - 1; ++i) {\n            int delta = 0;\n            if (i == 0) {\n                // P[0], P[1], P[2]\n                if (M < 3) continue;\n                int A = path[0];\n                int B = path[1];\n                int C = path[2];\n\n                int old1 = ov[A][B];\n                int old2 = ov[B][C];\n\n                int new1 = ov[B][A];\n                int new2 = ov[A][C];\n\n                delta = (new1 + new2) - (old1 + old2);\n                if (delta > 0) {\n                    swap(path[0], path[1]);\n                    edgeOv[0] = new1;\n                    edgeOv[1] = new2;\n                    totalOv += delta;\n                    improved = true;\n                }\n            } else if (i == M - 2) {\n                // P[M-3], P[M-2], P[M-1]\n                if (M < 3) continue;\n                int D = path[M - 3];\n                int A = path[M - 2];\n                int B = path[M - 1];\n\n                int old1 = ov[D][A];\n                int old2 = ov[A][B];\n\n                int new1 = ov[D][B];\n                int new2 = ov[B][A];\n\n                delta = (new1 + new2) - (old1 + old2);\n                if (delta > 0) {\n                    swap(path[M - 2], path[M - 1]);\n                    edgeOv[M - 3] = new1;\n                    edgeOv[M - 2] = new2;\n                    totalOv += delta;\n                    improved = true;\n                }\n            } else {\n                // P[i-1], P[i], P[i+1], P[i+2]\n                int D = path[i - 1];\n                int A = path[i];\n                int B = path[i + 1];\n                int C = path[i + 2];\n\n                int old1 = ov[D][A];\n                int old2 = ov[A][B];\n                int old3 = ov[B][C];\n\n                int new1 = ov[D][B];\n                int new2 = ov[B][A];\n                int new3 = ov[A][C];\n\n                delta = (new1 + new2 + new3) - (old1 + old2 + old3);\n                if (delta > 0) {\n                    swap(path[i], path[i + 1]);\n                    edgeOv[i - 1] = new1;\n                    edgeOv[i] = new2;\n                    edgeOv[i + 1] = new3;\n                    totalOv += delta;\n                    improved = true;\n                }\n            }\n        }\n    }\n    return totalOv;\n}\n\n// DP cost computation without parent reconstruction\nint compute_cost_no_parent(\n    const string &S,\n    const vector<vector<int>> &dist,\n    const vector<vector<int>> &cellsByLetter,\n    int startIdx\n) {\n    int L = (int)S.size();\n    if (L == 0) return 0;\n    int G = (int)dist.size();\n\n    vector<int> dpPrev(G, INF), dpCur(G, INF);\n    vector<int> prevCells, curCells;\n    prevCells.reserve(G);\n    curCells.reserve(G);\n\n    int c0 = S[0] - 'A';\n    const auto &cand0 = cellsByLetter[c0];\n    prevCells.clear();\n    for (int cell : cand0) {\n        dpPrev[cell] = dist[startIdx][cell];\n        prevCells.push_back(cell);\n    }\n\n    for (int pos = 1; pos < L; ++pos) {\n        int c = S[pos] - 'A';\n        const auto &cand = cellsByLetter[c];\n        curCells.clear();\n\n        for (int b : cand) {\n            int best = INF;\n            for (int a : prevCells) {\n                int val = dpPrev[a] + dist[a][b];\n                if (val < best) best = val;\n            }\n            dpCur[b] = best;\n            curCells.push_back(b);\n        }\n\n        // Swap dp arrays and active cell lists\n        dpPrev.swap(dpCur);\n        prevCells.swap(curCells);\n    }\n\n    int bestCost = INF;\n    for (int a : prevCells) {\n        if (dpPrev[a] < bestCost) bestCost = dpPrev[a];\n    }\n    return bestCost;\n}\n\n// DP with parent reconstruction: returns sequence of cell indices\nvector<int> compute_path_with_parent(\n    const string &S,\n    const vector<vector<int>> &dist,\n    const vector<vector<int>> &cellsByLetter,\n    int startIdx\n) {\n    int L = (int)S.size();\n    int G = (int)dist.size();\n    vector<int> result(L);\n    if (L == 0) return result;\n\n    vector<vector<int>> parent(L, vector<int>(G, -1));\n    vector<int> dpPrev(G, INF), dpCur(G, INF);\n    vector<int> prevCells, curCells;\n    prevCells.reserve(G);\n    curCells.reserve(G);\n\n    int c0 = S[0] - 'A';\n    const auto &cand0 = cellsByLetter[c0];\n    prevCells.clear();\n    for (int cell : cand0) {\n        dpPrev[cell] = dist[startIdx][cell];\n        parent[0][cell] = startIdx;\n        prevCells.push_back(cell);\n    }\n\n    for (int pos = 1; pos < L; ++pos) {\n        int c = S[pos] - 'A';\n        const auto &cand = cellsByLetter[c];\n        curCells.clear();\n\n        for (int b : cand) {\n            int best = INF;\n            int bestPrevCell = -1;\n            for (int a : prevCells) {\n                int val = dpPrev[a] + dist[a][b];\n                if (val < best) {\n                    best = val;\n                    bestPrevCell = a;\n                }\n            }\n            dpCur[b] = best;\n            parent[pos][b] = bestPrevCell;\n            curCells.push_back(b);\n        }\n\n        dpPrev.swap(dpCur);\n        prevCells.swap(curCells);\n    }\n\n    int bestCost = INF;\n    int bestLastCell = -1;\n    for (int a : prevCells) {\n        if (dpPrev[a] < bestCost) {\n            bestCost = dpPrev[a];\n            bestLastCell = a;\n        }\n    }\n\n    int cell = bestLastCell;\n    for (int pos = L - 1; pos >= 0; --pos) {\n        result[pos] = cell;\n        cell = parent[pos][cell]; // for pos=0 this becomes startIdx; we ignore it\n    }\n\n    return result;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M;\n    if (!(cin >> N >> M)) {\n        return 0;\n    }\n    int si, sj;\n    cin >> si >> sj;\n    vector<string> grid(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> grid[i];\n    }\n\n    vector<string> words(M);\n    for (int i = 0; i < M; ++i) {\n        cin >> words[i];\n    }\n\n    int G = N * N;\n    int startIdx = si * N + sj;\n\n    // Precompute cell coordinates and letter lists\n    vector<pair<int,int>> coord(G);\n    for (int idx = 0; idx < G; ++idx) {\n        coord[idx] = {idx / N, idx % N};\n    }\n\n    vector<vector<int>> cellsByLetter(26);\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            char c = grid[i][j];\n            int idx = i * N + j;\n            cellsByLetter[c - 'A'].push_back(idx);\n        }\n    }\n\n    // Precompute distance matrix\n    vector<vector<int>> dist(G, vector<int>(G));\n    for (int a = 0; a < G; ++a) {\n        int ax = coord[a].first;\n        int ay = coord[a].second;\n        for (int b = 0; b < G; ++b) {\n            int bx = coord[b].first;\n            int by = coord[b].second;\n            dist[a][b] = abs(ax - bx) + abs(ay - by) + 1;\n        }\n    }\n\n    // Precompute overlap matrix between words\n    vector<vector<int>> ov(M, vector<int>(M, 0));\n    for (int i = 0; i < M; ++i) {\n        for (int j = 0; j < M; ++j) {\n            if (i == j) continue;\n            ov[i][j] = compute_overlap(words[i], words[j]);\n        }\n    }\n\n    mt19937 rng(712367821);\n\n    int numRestarts = 80;  // can be tuned\n\n    string bestS;\n    int bestCost = INF;\n\n    vector<int> path(M);\n    vector<char> used(M);\n\n    for (int r = 0; r < numRestarts; ++r) {\n        // Build greedy path\n        fill(used.begin(), used.end(), 0);\n        int startNode = (int)(rng() % M);\n        path[0] = startNode;\n        used[startNode] = 1;\n\n        for (int pos = 1; pos < M; ++pos) {\n            int u = path[pos - 1];\n            int bestOv = -1;\n            vector<int> cands;\n            cands.reserve(M);\n\n            for (int v = 0; v < M; ++v) {\n                if (used[v]) continue;\n                int o = ov[u][v];\n                if (o > bestOv) {\n                    bestOv = o;\n                    cands.clear();\n                    cands.push_back(v);\n                } else if (o == bestOv) {\n                    cands.push_back(v);\n                }\n            }\n\n            int v = cands[rng() % cands.size()];\n            path[pos] = v;\n            used[v] = 1;\n        }\n\n        // Local search to improve overlaps\n        int totalOv = local_search_adjacent_swaps(path, ov);\n        (void)totalOv; // not strictly needed afterwards, but kept for clarity\n\n        // Build superstring S from this path\n        string S = words[path[0]];\n        for (int i = 1; i < M; ++i) {\n            int prev = path[i - 1];\n            int cur = path[i];\n            int k = ov[prev][cur];\n            // Append from index k..4 (length 5)\n            S.append(words[cur].begin() + k, words[cur].end());\n        }\n\n        // Evaluate cost for S\n        int T = compute_cost_no_parent(S, dist, cellsByLetter, startIdx);\n        if (T < bestCost) {\n            bestCost = T;\n            bestS = move(S);\n        }\n    }\n\n    // Compute final path with parent reconstruction for best superstring\n    vector<int> bestCells = compute_path_with_parent(bestS, dist, cellsByLetter, startIdx);\n\n    // Output sequence of grid positions\n    int L = (int)bestCells.size();\n    for (int pos = 0; pos < L; ++pos) {\n        int idx = bestCells[pos];\n        int x = idx / N;\n        int y = idx % N;\n        cout << x << ' ' << y << '\\n';\n    }\n\n    return 0;\n}","ahc030":"#include <bits/stdc++.h>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M;\n    double eps;\n    if (!(cin >> N >> M >> eps)) {\n        return 0; // no input\n    }\n\n    // Read shapes (not used in this baseline, but read to match protocol)\n    vector<vector<pair<int,int>>> fields(M);\n    for (int k = 0; k < M; ++k) {\n        int d;\n        cin >> d;\n        fields[k].reserve(d);\n        for (int t = 0; t < d; ++t) {\n            int x, y;\n            cin >> x >> y;\n            fields[k].emplace_back(x, y);\n        }\n    }\n\n    vector<pair<int,int>> has_oil;\n    has_oil.reserve(N * N);\n\n    // Drill every cell (i, j)\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cout << \"q 1 \" << i << ' ' << j << '\\n' << flush;\n\n            string resp;\n            if (!(cin >> resp)) {\n                return 0; // defensive, in case of EOF\n            }\n\n            int v = stoi(resp);\n            if (v > 0) {\n                has_oil.emplace_back(i, j);\n            }\n        }\n    }\n\n    // Output all cells that yielded oil\n    cout << \"a \" << has_oil.size();\n    for (auto &p : has_oil) {\n        cout << ' ' << p.first << ' ' << p.second;\n    }\n    cout << '\\n' << flush;\n\n    // Read judge's verdict (1 = correct, 0 = wrong).\n    // In this baseline, it should always be 1.\n    string verdict;\n    if (!(cin >> verdict)) {\n        return 0;\n    }\n\n    // Optionally, we could assert(verdict == \"1\") in local testing.\n\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    if (!(cin >> W >> D >> N)) {\n        return 0;\n    }\n\n    // Read a[d][k]; guaranteed non-decreasing in k for each d.\n    vector<vector<long long>> a(D, vector<long long>(N));\n    for (int d = 0; d < D; d++) {\n        for (int k = 0; k < N; k++) {\n            cin >> a[d][k];\n        }\n    }\n\n    // Helper: compute total area deficiency (without factor 100)\n    auto compute_deficiency = [&](const vector<int> &widths) -> long long {\n        vector<int> w_sorted = widths;\n        sort(w_sorted.begin(), w_sorted.end());\n        vector<long long> cap(N);\n        for (int i = 0; i < N; i++) {\n            cap[i] = 1LL * W * w_sorted[i];\n        }\n        long long def = 0;\n        for (int d = 0; d < D; d++) {\n            for (int k = 0; k < N; k++) {\n                long long diff = a[d][k] - cap[k];\n                if (diff > 0) def += diff;\n            }\n        }\n        return def;\n    };\n\n    // Initialize widths: at least 1 each.\n    vector<int> widths(N, 1);\n    int sumW = N;\n    int budget = W - N;  // remaining width to distribute\n\n    long long current_def = compute_deficiency(widths);\n\n    // Greedy distribution of remaining width\n    for (int step = 0; step < budget; step++) {\n        long long best_def = LLONG_MAX;\n        int best_i = 0;\n        for (int i = 0; i < N; i++) {\n            widths[i]++;\n            long long new_def = compute_deficiency(widths);\n            if (new_def < best_def) {\n                best_def = new_def;\n                best_i = i;\n            }\n            widths[i]--;\n        }\n        widths[best_i]++;\n        current_def = best_def;\n        sumW++;\n    }\n\n    // Local improvement: move 1 unit of width from j to i\n    const int MAX_PASSES = 3;\n    for (int pass = 0; pass < MAX_PASSES; pass++) {\n        bool improved = false;\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                if (i == j) continue;\n                if (widths[j] <= 1) continue; // cannot shrink below 1\n                widths[i]++;\n                widths[j]--;\n                long long new_def = compute_deficiency(widths);\n                if (new_def < current_def) {\n                    current_def = new_def;\n                    improved = true;\n                } else {\n                    // revert\n                    widths[i]--;\n                    widths[j]++;\n                }\n            }\n        }\n        if (!improved) break;\n    }\n\n    // Sort widths to define final stripe order\n    vector<int> w_sorted = widths;\n    sort(w_sorted.begin(), w_sorted.end());\n\n    // Build rectangles (vertical stripes) from left to right\n    vector<int> x0(N), x1(N);\n    int x = 0;\n    for (int k = 0; k < N; k++) {\n        x0[k] = x;\n        x1[k] = x + w_sorted[k];\n        x = x1[k];\n    }\n    // x should be exactly W; if not, adjust the last stripe as a safety net\n    if (x != W) {\n        x1[N - 1] += (W - x);\n    }\n\n    // Output: same rectangles for all days, reservation k gets stripe k.\n    // Rectangle: (i0, j0, i1, j1) = (0, x0[k], W, x1[k])\n    for (int d = 0; d < D; d++) {\n        for (int k = 0; k < N; k++) {\n            int i0 = 0;\n            int j0 = x0[k];\n            int i1 = W;\n            int j1 = x1[k];\n            // Ensure constraints 0 <= i0 < i1 <= W, 0 <= j0 < j1 <= W.\n            if (j1 > W) j1 = W;\n            cout << i0 << ' ' << j0 << ' ' << i1 << ' ' << j1 << '\\n';\n        }\n    }\n\n    return 0;\n}","ahc032":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const long long MOD = 998244353LL;\n\n// Simple fast RNG (xorshift64)\nstruct XorShift64 {\n    uint64_t x;\n    XorShift64(uint64_t seed = 88172645463325252ull) { x = seed ? seed : 88172645463325252ull; }\n    inline uint64_t next() {\n        uint64_t y = x;\n        y ^= y << 7;\n        y ^= y >> 9;\n        return x = y;\n    }\n    inline int next_int(int n) { // 0..n-1\n        return (int)(next() % (uint64_t)n);\n    }\n    inline double next_double() { // [0,1)\n        // use high 53 bits for double\n        return (next() >> 11) * (1.0 / (1ULL << 53));\n    }\n};\n\nstruct Op {\n    int m;\n    int p;\n    int q;\n};\n\nstruct CellChange {\n    int idx;\n    int oldv;\n    int newv;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, K;\n    if (!(cin >> N >> M >> K)) {\n        return 0;\n    }\n\n    // Read initial board\n    vector<int> board(N * N);\n    long long cur_score = 0;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            long long v;\n            cin >> v;\n            v %= MOD;\n            board[i * N + j] = (int)v;\n            cur_score += v;\n        }\n    }\n\n    // Read stamps: s[m][3][3]\n    static int s[20][3][3]; // M=20 max\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                long long v;\n                cin >> v;\n                v %= MOD;\n                s[m][i][j] = (int)v;\n            }\n        }\n    }\n\n    // Precompute all candidate operations\n    vector<Op> all_ops;\n    all_ops.reserve(M * (N - 2) * (N - 2));\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                all_ops.push_back({m, p, q});\n            }\n        }\n    }\n    const int NUM_OPS = (int)all_ops.size(); // should be M * 7 * 7 = 980 when N=9\n\n    // RNG seed from clock\n    uint64_t seed = chrono::high_resolution_clock::now().time_since_epoch().count();\n    XorShift64 rng(seed);\n\n    vector<int> cur_ops;\n    cur_ops.reserve(K);\n\n    // Greedy initial solution\n    {\n        for (int step = 0; step < K; ++step) {\n            long long best_delta = 0;\n            int best_id = -1;\n            for (int op_id = 0; op_id < NUM_OPS; ++op_id) {\n                const Op &op = all_ops[op_id];\n                int m = op.m, p = op.p, q = op.q;\n                long long delta = 0;\n                for (int di = 0; di < 3; ++di) {\n                    int r = p + di;\n                    int base = r * N;\n                    for (int dj = 0; dj < 3; ++dj) {\n                        int c = q + dj;\n                        int idx = base + c;\n                        long long x = board[idx];\n                        long long d = s[m][di][dj];\n                        long long tmp = x + d;\n                        if (tmp >= MOD) tmp -= MOD;\n                        delta += tmp - x;\n                    }\n                }\n                if (delta > best_delta) {\n                    best_delta = delta;\n                    best_id = op_id;\n                }\n            }\n            if (best_id == -1 || best_delta <= 0) break;\n\n            // Apply best operation\n            const Op &op = all_ops[best_id];\n            int m = op.m, p = op.p, q = op.q;\n            for (int di = 0; di < 3; ++di) {\n                int r = p + di;\n                int base = r * N;\n                for (int dj = 0; dj < 3; ++dj) {\n                    int c = q + dj;\n                    int idx = base + c;\n                    long long x = board[idx];\n                    long long d = s[m][di][dj];\n                    long long tmp = x + d;\n                    if (tmp >= MOD) tmp -= MOD;\n                    board[idx] = (int)tmp;\n                }\n            }\n            cur_score += best_delta;\n            cur_ops.push_back(best_id);\n        }\n    }\n\n    long long best_score = cur_score;\n    vector<int> best_ops = cur_ops;\n\n    // Simulated annealing\n    const double TIME_LIMIT = 1.9; // seconds\n    auto time_start = chrono::steady_clock::now();\n\n    const double T0 = 1e8;\n    const double T_end = 1e4;\n    double T = T0;\n\n    CellChange changes[18]; // max affected cells for replace: 3x3 + 3x3 = 18\n    int iteration = 0;\n\n    while (true) {\n        if ((iteration & 1023) == 0) { // check time every 1024 iterations\n            auto now = chrono::steady_clock::now();\n            double elapsed = chrono::duration<double>(now - time_start).count();\n            if (elapsed >= TIME_LIMIT) break;\n            double progress = elapsed / TIME_LIMIT;\n            if (progress > 1.0) progress = 1.0;\n            T = T0 + (T_end - T0) * progress;\n        }\n        ++iteration;\n\n        int curL = (int)cur_ops.size();\n        int move_type; // 0=ADD, 1=REMOVE, 2=REPLACE\n        if (curL == 0) {\n            move_type = 0; // must add\n        } else if (curL == K) {\n            move_type = (rng.next_int(2) == 0 ? 1 : 2); // remove or replace\n        } else {\n            int r = rng.next_int(100);\n            if (r < 40) move_type = 0;        // 40% add\n            else if (r < 80) move_type = 2;   // 40% replace\n            else move_type = 1;               // 20% remove\n        }\n\n        long long deltaScore = 0;\n        int chN = 0;\n\n        if (move_type == 0) { // ADD\n            int op_new = rng.next_int(NUM_OPS);\n            const Op &B = all_ops[op_new];\n            int m_new = B.m, p_new = B.p, q_new = B.q;\n\n            // Only new patch cells (3x3)\n            for (int di = 0; di < 3; ++di) {\n                int r = p_new + di;\n                int base = r * N;\n                for (int dj = 0; dj < 3; ++dj) {\n                    int c = q_new + dj;\n                    int idx = base + c;\n                    long long x = board[idx];\n                    long long d_new = s[m_new][di][dj];\n                    if (d_new == 0) continue; // no change\n                    long long tmp = x + d_new;\n                    if (tmp >= MOD) tmp -= MOD;\n                    deltaScore += tmp - x;\n                    changes[chN++] = {idx, (int)x, (int)tmp};\n                }\n            }\n\n            bool accept;\n            if (deltaScore >= 0) {\n                accept = true;\n            } else {\n                double prob = exp((double)deltaScore / T);\n                if (prob <= 0.0) accept = false;\n                else accept = (rng.next_double() < prob);\n            }\n\n            if (accept) {\n                // apply changes\n                for (int i = 0; i < chN; ++i) {\n                    board[changes[i].idx] = changes[i].newv;\n                }\n                cur_score += deltaScore;\n                cur_ops.push_back(op_new);\n                if (cur_score > best_score) {\n                    best_score = cur_score;\n                    best_ops = cur_ops;\n                }\n            }\n        } else if (move_type == 1) { // REMOVE\n            if (curL == 0) continue; // safety\n            int idx_op = rng.next_int(curL);\n            int op_old = cur_ops[idx_op];\n            const Op &A = all_ops[op_old];\n            int m_old = A.m, p_old = A.p, q_old = A.q;\n\n            for (int di = 0; di < 3; ++di) {\n                int r = p_old + di;\n                int base = r * N;\n                for (int dj = 0; dj < 3; ++dj) {\n                    int c = q_old + dj;\n                    int idx = base + c;\n                    long long x = board[idx];\n                    long long d_old = s[m_old][di][dj];\n                    if (d_old == 0) continue;\n                    long long tmp = x - d_old;\n                    if (tmp < 0) tmp += MOD;\n                    deltaScore += tmp - x;\n                    changes[chN++] = {idx, (int)x, (int)tmp};\n                }\n            }\n\n            bool accept;\n            if (deltaScore >= 0) {\n                accept = true;\n            } else {\n                double prob = exp((double)deltaScore / T);\n                if (prob <= 0.0) accept = false;\n                else accept = (rng.next_double() < prob);\n            }\n\n            if (accept) {\n                for (int i = 0; i < chN; ++i) {\n                    board[changes[i].idx] = changes[i].newv;\n                }\n                cur_score += deltaScore;\n                // remove op at idx_op\n                cur_ops[idx_op] = cur_ops.back();\n                cur_ops.pop_back();\n                if (cur_score > best_score) {\n                    best_score = cur_score;\n                    best_ops = cur_ops;\n                }\n            }\n        } else { // REPLACE\n            if (curL == 0) continue; // safety\n            int idx_old = rng.next_int(curL);\n            int op_old = cur_ops[idx_old];\n            int op_new = rng.next_int(NUM_OPS);\n            if (op_new == op_old) {\n                // This replacement does nothing; skip to avoid waste (optional).\n                continue;\n            }\n\n            const Op &A = all_ops[op_old];\n            const Op &B = all_ops[op_new];\n            int m_old = A.m, p_old = A.p, q_old = A.q;\n            int m_new = B.m, p_new = B.p, q_new = B.q;\n\n            // build union of cells affected by old and new patches\n            int rs[18], cs[18];\n            int uc = 0;\n            auto add_cell = [&](int r, int c) {\n                for (int t = 0; t < uc; ++t) {\n                    if (rs[t] == r && cs[t] == c) return;\n                }\n                rs[uc] = r;\n                cs[uc] = c;\n                ++uc;\n            };\n            for (int di = 0; di < 3; ++di) {\n                int r = p_old + di;\n                for (int dj = 0; dj < 3; ++dj) {\n                    int c = q_old + dj;\n                    add_cell(r, c);\n                }\n            }\n            for (int di = 0; di < 3; ++di) {\n                int r = p_new + di;\n                for (int dj = 0; dj < 3; ++dj) {\n                    int c = q_new + dj;\n                    add_cell(r, c);\n                }\n            }\n\n            deltaScore = 0;\n            chN = 0;\n            for (int t = 0; t < uc; ++t) {\n                int r = rs[t];\n                int c = cs[t];\n                int idx = r * N + c;\n                long long x = board[idx];\n\n                long long d_old = 0, d_new = 0;\n                if (r >= p_old && r < p_old + 3 && c >= q_old && c < q_old + 3) {\n                    d_old = s[m_old][r - p_old][c - q_old];\n                }\n                if (r >= p_new && r < p_new + 3 && c >= q_new && c < q_new + 3) {\n                    d_new = s[m_new][r - p_new][c - q_new];\n                }\n                long long d = d_new - d_old;\n                if (d == 0) continue;\n                long long tmp = x + d;\n                if (tmp < 0) tmp += MOD;\n                else if (tmp >= MOD) tmp -= MOD;\n                deltaScore += tmp - x;\n                changes[chN++] = {idx, (int)x, (int)tmp};\n            }\n\n            bool accept;\n            if (deltaScore >= 0) {\n                accept = true;\n            } else {\n                double prob = exp((double)deltaScore / T);\n                if (prob <= 0.0) accept = false;\n                else accept = (rng.next_double() < prob);\n            }\n\n            if (accept) {\n                for (int i = 0; i < chN; ++i) {\n                    board[changes[i].idx] = changes[i].newv;\n                }\n                cur_score += deltaScore;\n                cur_ops[idx_old] = op_new;\n                if (cur_score > best_score) {\n                    best_score = cur_score;\n                    best_ops = cur_ops;\n                }\n            }\n        }\n    }\n\n    // Output best solution found\n    int L = (int)best_ops.size();\n    cout << L << '\\n';\n    for (int id : best_ops) {\n        const Op &op = all_ops[id];\n        cout << op.m << ' ' << op.p << ' ' << op.q << '\\n';\n    }\n\n    return 0;\n}","ahc033":"#include <bits/stdc++.h>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    if (!(cin >> N)) return 0;  // N is always 5 in this problem\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    // Grid: -1 means no container, otherwise container id\n    vector<vector<int>> grid(N, vector<int>(N, -1));\n\n    // Next container index to spawn for each row (0..N-1)\n    int next_idx[5] = {0,0,0,0,0};\n\n    // Large crane (index 0)\n    int bx = 0, by = 0;     // position\n    int carry = -1;         // carried container id, -1 if none\n\n    // Target for picking a container when not carrying\n    bool has_target = false;\n    int tx = -1, ty = -1;   // target position\n    int target_id = -1;\n\n    // Operation strings for 5 cranes\n    vector<string> ops(N);\n\n    int dispatched = 0;\n    const int total_containers = N * N;\n    const int MAX_TURNS = 10000;\n    int t = 0;\n\n    while (dispatched < total_containers && t < MAX_TURNS) {\n        // Step 1: spawn containers at receiving gates if possible\n        for (int i = 0; i < N; ++i) {\n            if (next_idx[i] < N && grid[i][0] == -1) {\n                // Spawn only if there is no crane holding a container on (i,0)\n                // Only large crane exists from t>=0 in our simulation; small cranes don't hold containers.\n                if (!(carry != -1 && bx == i && by == 0)) {\n                    grid[i][0] = A[i][next_idx[i]];\n                    ++next_idx[i];\n                }\n            }\n        }\n\n        // Step 2: decide commands\n\n        // Large crane command\n        char big_cmd;\n        if (carry == -1) {\n            // Not carrying: choose or follow a target container\n            // If we don't have a target (or it was just picked), select nearest container\n            if (!has_target) {\n                int best_dist = INT_MAX;\n                int best_id = -1;\n                int best_x = -1, best_y = -1;\n                for (int i = 0; i < N; ++i) {\n                    for (int j = 0; j < N; ++j) {\n                        if (grid[i][j] != -1) {\n                            int dist = abs(i - bx) + abs(j - by);\n                            int cid  = grid[i][j];\n                            if (dist < best_dist ||\n                                (dist == best_dist && cid < best_id)) {\n                                best_dist = dist;\n                                best_id   = cid;\n                                best_x    = i;\n                                best_y    = j;\n                            }\n                        }\n                    }\n                }\n                if (best_dist != INT_MAX) {\n                    has_target = true;\n                    tx = best_x;\n                    ty = best_y;\n                    target_id = best_id;\n                }\n            }\n\n            if (!has_target) {\n                // No containers on grid (should only happen when all dispatched)\n                big_cmd = '.';\n            } else if (bx == tx && by == ty) {\n                // At target -> pick\n                big_cmd = 'P';\n            } else {\n                // Move one step towards target (Manhattan shortest path)\n                if (bx != tx) {\n                    big_cmd = (tx > bx) ? 'D' : 'U';\n                } else if (by != ty) {\n                    big_cmd = (ty > by) ? 'R' : 'L';\n                } else {\n                    big_cmd = '.';\n                }\n            }\n        } else {\n            // Carrying a container: move to its dispatch gate (row = id / N, col = N-1)\n            int goal_x = carry / N;\n            int goal_y = N - 1;\n            if (bx == goal_x && by == goal_y) {\n                big_cmd = 'Q';\n            } else {\n                if (bx != goal_x) {\n                    big_cmd = (goal_x > bx) ? 'D' : 'U';\n                } else if (by != goal_y) {\n                    big_cmd = (goal_y > by) ? 'R' : 'L';\n                } else {\n                    big_cmd = '.';\n                }\n            }\n        }\n\n        // Small cranes: bomb at t=0, then always do nothing\n        char small_cmd = (t == 0 ? 'B' : '.');\n\n        // Append commands to operation strings\n        ops[0].push_back(big_cmd);\n        for (int i = 1; i < N; ++i) ops[i].push_back(small_cmd);\n\n        // Step 2: apply large crane action\n        if (big_cmd == 'P') {\n            // Pick up container at current cell\n            // Preconditions (by construction): carry == -1 and grid[bx][by] != -1\n            if (carry == -1 && grid[bx][by] != -1) {\n                carry = grid[bx][by];\n                grid[bx][by] = -1;\n            } else {\n                // Should not happen; fail-safe: ignore\n                big_cmd = '.';\n            }\n            has_target = false;  // target consumed\n        } else if (big_cmd == 'Q') {\n            // Put down carried container at current cell\n            // Pre: carry != -1 and grid[bx][by] == -1\n            if (carry != -1 && grid[bx][by] == -1) {\n                grid[bx][by] = carry;\n                carry = -1;\n            } else {\n                // Should not happen; ignore\n                big_cmd = '.';\n            }\n        } else if (big_cmd == 'U') {\n            if (bx > 0) --bx;\n        } else if (big_cmd == 'D') {\n            if (bx < N - 1) ++bx;\n        } else if (big_cmd == 'L') {\n            if (by > 0) --by;\n        } else if (big_cmd == 'R') {\n            if (by < N - 1) ++by;\n        } else {\n            // '.': do nothing\n        }\n\n        // Step 3: dispatch containers at right edge\n        for (int i = 0; i < N; ++i) {\n            if (grid[i][N - 1] != -1) {\n                // Container is dispatched and removed\n                grid[i][N - 1] = -1;\n                ++dispatched;\n            }\n        }\n\n        ++t;\n    }\n\n    // Output operation strings\n    for (int i = 0; i < N; ++i) {\n        cout << ops[i] << '\\n';\n    }\n\n    return 0;\n}","ahc034":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int MAXN = 20;\nconst int TOT_LIMIT = 100000;  // Hard limit from problem\nconst int LIMIT_GREEDY = 90000; // Cap for greedy stage, leave room for fallback\n\nint N;\nlong long h[MAXN][MAXN];\nvector<string> ops;\n\nint cur_r = 0, cur_c = 0;   // current truck position\nlong long load_truck = 0;   // current truck load\n\nvector<pair<int,int>> snakePath;\n\n// Move truck from current (cur_r, cur_c) to (tr, tc) along Manhattan path\nvoid move_to(int tr, int tc) {\n    while (cur_r < tr) {\n        ++cur_r;\n        ops.emplace_back(\"D\");\n    }\n    while (cur_r > tr) {\n        --cur_r;\n        ops.emplace_back(\"U\");\n    }\n    while (cur_c < tc) {\n        ++cur_c;\n        ops.emplace_back(\"R\");\n    }\n    while (cur_c > tc) {\n        --cur_c;\n        ops.emplace_back(\"L\");\n    }\n}\n\n// Find nearest cell of given sign from current position.\n// sign = +1: h > 0 (positive), sign = -1: h < 0 (negative).\n// Tie-break by larger |h|.\npair<int,int> findNearest(int sign) {\n    int bestR = -1, bestC = -1;\n    int bestd = INT_MAX;\n    long long bestVal = -1;\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            long long v = h[i][j];\n            if (sign == 1) {\n                if (v <= 0) continue;\n                int d = abs(i - cur_r) + abs(j - cur_c);\n                if (d < bestd || (d == bestd && v > bestVal)) {\n                    bestd = d;\n                    bestVal = v;\n                    bestR = i;\n                    bestC = j;\n                }\n            } else {\n                if (v >= 0) continue;\n                int d = abs(i - cur_r) + abs(j - cur_c);\n                long long absV = -v;\n                if (d < bestd || (d == bestd && absV > bestVal)) {\n                    bestd = d;\n                    bestVal = absV;\n                    bestR = i;\n                    bestC = j;\n                }\n            }\n        }\n    }\n    return {bestR, bestC};\n}\n\n// Stage 1: greedy shipping between nearest positives and negatives\nvoid greedy_phase() {\n    long long base_total = 0;\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            base_total += llabs(h[i][j]);\n\n    while (base_total > 0 && (int)ops.size() < LIMIT_GREEDY) {\n        if (load_truck == 0) {\n            // Need a positive cell\n            auto [pr, pc] = findNearest(+1);\n            if (pr == -1) break; // should not happen in a correct state\n            move_to(pr, pc);\n\n            long long v = h[pr][pc];\n            if (v > 0) {\n                long long d = v;\n                ops.emplace_back(\"+\" + to_string(d));\n                load_truck += d;\n                h[pr][pc] = 0;\n                base_total -= d;\n            }\n        } else {\n            // We have load, need a negative cell\n            auto [nr, nc] = findNearest(-1);\n            if (nr == -1) break; // should not happen if total sum is 0\n            move_to(nr, nc);\n\n            long long v = h[nr][nc];\n            if (v < 0) {\n                long long need = -v;\n                long long d = min(load_truck, need);\n                ops.emplace_back(\"-\" + to_string(d));\n                load_truck -= d;\n                h[nr][nc] += d;\n                base_total -= d;\n            }\n        }\n    }\n}\n\n// Build snake Hamiltonian path for fallback\nvoid buildSnakePath() {\n    snakePath.clear();\n    for (int i = 0; i < N; ++i) {\n        if (i % 2 == 0) {\n            for (int j = 0; j < N; ++j) {\n                snakePath.emplace_back(i, j);\n            }\n        } else {\n            for (int j = N - 1; j >= 0; --j) {\n                snakePath.emplace_back(i, j);\n            }\n        }\n    }\n}\n\n// Stage 2: fallback using two-pass snake sweep\nvoid fallback_snake() {\n    // Unload everything at current cell to make load_truck zero\n    if (load_truck > 0) {\n        ops.emplace_back(\"-\" + to_string(load_truck));\n        h[cur_r][cur_c] += load_truck;\n        load_truck = 0;\n    }\n\n    // Move to (0,0) which is snakePath[0]\n    move_to(0, 0);\n\n    int M = (int)snakePath.size();\n\n    // Forward pass\n    for (int idx = 0; idx < M; ++idx) {\n        int r = snakePath[idx].first;\n        int c = snakePath[idx].second;\n        move_to(r, c);\n\n        long long v = h[r][c];\n        if (v > 0) {\n            long long d = v;\n            ops.emplace_back(\"+\" + to_string(d));\n            load_truck += d;\n            h[r][c] = 0;\n        } else if (v < 0 && load_truck > 0) {\n            long long need = -v;\n            long long d = min(load_truck, need);\n            ops.emplace_back(\"-\" + to_string(d));\n            load_truck -= d;\n            h[r][c] += d;\n        }\n    }\n\n    // Backward pass\n    for (int idx = M - 1; idx >= 0; --idx) {\n        int r = snakePath[idx].first;\n        int c = snakePath[idx].second;\n        move_to(r, c);\n\n        long long v = h[r][c];\n        if (v < 0 && load_truck > 0) {\n            long long need = -v;\n            long long d = min(load_truck, need);\n            ops.emplace_back(\"-\" + to_string(d));\n            load_truck -= d;\n            h[r][c] += d;\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    if (!(cin >> N)) return 0;\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            cin >> h[i][j];\n\n    cur_r = 0;\n    cur_c = 0;\n    load_truck = 0;\n\n    buildSnakePath();\n    greedy_phase();\n\n    // Check if everything is leveled\n    bool all_zero = true;\n    for (int i = 0; i < N && all_zero; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (h[i][j] != 0) {\n                all_zero = false;\n                break;\n            }\n        }\n    }\n\n    if (!all_zero && (int)ops.size() < TOT_LIMIT) {\n        fallback_snake();\n    }\n\n    // Absolute safety: never output more than 100000 operations\n    if ((int)ops.size() > TOT_LIMIT) {\n        ops.resize(TOT_LIMIT);\n    }\n\n    for (const string &s : ops) {\n        cout << s << '\\n';\n    }\n    return 0;\n}","ahc035":"#include <bits/stdc++.h>\nusing namespace std;\n\n/*\n Heuristic strategy:\n\n - N=6, M=15, T=10 fixed.\n - Seed count per generation: S = 2*N*(N-1) = 60.\n - Each turn:\n   * Compute normalized scores using global per-dim maxima from initial seeds.\n   * Select 36 seeds:\n       - dimension champions (best for each dimension),\n       - fill remaining slots with highest normalized total score.\n   * Compute pairwise \"synergy\" S(a,b) = sum_l max(x_a_l, x_b_l)/X_l.\n   * Hill-climb a permutation of the 36 seeds onto the 6x6 grid\n     to maximize sum of synergies over all grid edges.\n   * Output the arrangement, then read the next generation seeds.\n*/\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, T;\n    if (!(cin >> N >> M >> T)) return 0;\n    const int SEED_COUNT = 2 * N * (N - 1); // 60 for N=6\n    const int SZ = N * N;                   // 36 for N=6\n\n    // Current seeds: x[k][l]\n    vector<vector<int>> x(SEED_COUNT, vector<int>(M));\n    for (int i = 0; i < SEED_COUNT; i++) {\n        for (int l = 0; l < M; l++) cin >> x[i][l];\n    }\n\n    // Global per-dimension maxima from initial seeds\n    vector<int> X_global(M, 0);\n    for (int l = 0; l < M; l++) {\n        int mx = 0;\n        for (int i = 0; i < SEED_COUNT; i++) {\n            if (x[i][l] > mx) mx = x[i][l];\n        }\n        X_global[l] = mx;\n    }\n\n    // Active dimensions (those with X_global[l] > 0, to avoid division by zero)\n    vector<int> active_dims;\n    active_dims.reserve(M);\n    for (int l = 0; l < M; l++) {\n        if (X_global[l] > 0) active_dims.push_back(l);\n    }\n\n    // Precompute grid adjacency (neighbors) and edges\n    vector<vector<int>> neighbors(SZ);\n    vector<pair<int,int>> edges;\n    edges.reserve(2 * N * (N - 1));\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            int pos = i * N + j;\n            if (j + 1 < N) {\n                int q = pos + 1;\n                edges.emplace_back(pos, q);\n                neighbors[pos].push_back(q);\n                neighbors[q].push_back(pos);\n            }\n            if (i + 1 < N) {\n                int q = pos + N;\n                edges.emplace_back(pos, q);\n                neighbors[pos].push_back(q);\n                neighbors[q].push_back(pos);\n            }\n        }\n    }\n\n    // Simple xorshift RNG (deterministic)\n    uint64_t rng_state = 88172645463325252ull;\n    auto rng = [&]() -> uint64_t {\n        rng_state ^= (rng_state << 7);\n        rng_state ^= (rng_state >> 9);\n        return rng_state;\n    };\n\n    // Normalized total scores per seed\n    vector<double> normV(SEED_COUNT);\n\n    // Synergy matrix: we only need [0..SEED_COUNT-1], but allocate a bit larger for safety\n    static double synergy[120][120];\n\n    for (int turn = 0; turn < T; turn++) {\n        // 1. Compute normalized total score for each seed\n        for (int k = 0; k < SEED_COUNT; k++) {\n            double s = 0.0;\n            for (int idx = 0; idx < (int)active_dims.size(); idx++) {\n                int l = active_dims[idx];\n                s += (double)x[k][l] / (double)X_global[l];\n            }\n            normV[k] = s;\n        }\n\n        // 2. Select 36 seeds: dimension champions + top by normV\n        vector<int> selected;\n        selected.reserve(SZ);\n        vector<char> used(SEED_COUNT, 0);\n\n        // Dimension champions\n        for (int idx = 0; idx < (int)active_dims.size(); idx++) {\n            int l = active_dims[idx];\n            int best = -1;\n            int bestVal = -1;\n            double bestNorm = -1.0;\n            for (int k = 0; k < SEED_COUNT; k++) {\n                int v = x[k][l];\n                if (v > bestVal || (v == bestVal && normV[k] > bestNorm)) {\n                    bestVal = v;\n                    bestNorm = normV[k];\n                    best = k;\n                }\n            }\n            if (best != -1 && !used[best]) {\n                used[best] = 1;\n                selected.push_back(best);\n                if ((int)selected.size() == SZ) break;\n            }\n        }\n\n        // Fill remaining slots with highest normV seeds\n        vector<int> ord(SEED_COUNT);\n        iota(ord.begin(), ord.end(), 0);\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            if (normV[a] != normV[b]) return normV[a] > normV[b];\n            return a < b;\n        });\n        for (int idx = 0; idx < SEED_COUNT && (int)selected.size() < SZ; idx++) {\n            int k = ord[idx];\n            if (!used[k]) {\n                used[k] = 1;\n                selected.push_back(k);\n            }\n        }\n        // Safety: if somehow still < SZ, fill arbitrarily\n        for (int k = 0; k < SEED_COUNT && (int)selected.size() < SZ; k++) {\n            if (!used[k]) {\n                used[k] = 1;\n                selected.push_back(k);\n            }\n        }\n\n        // 3. Compute synergy matrix for all seeds (we only use selected subset)\n        for (int i = 0; i < SEED_COUNT; i++) {\n            synergy[i][i] = 0.0;\n            for (int j = i + 1; j < SEED_COUNT; j++) {\n                double s = 0.0;\n                for (int idx = 0; idx < (int)active_dims.size(); idx++) {\n                    int l = active_dims[idx];\n                    s += (double)max(x[i][l], x[j][l]) / (double)X_global[l];\n                }\n                synergy[i][j] = synergy[j][i] = s;\n            }\n        }\n\n        // 4. Initial placement: just put selected seeds row-major\n        vector<int> arr(SZ);\n        for (int pos = 0; pos < SZ; pos++) {\n            arr[pos] = selected[pos];\n        }\n\n        // Compute initial total synergy score\n        double cur_score = 0.0;\n        for (auto &e : edges) {\n            cur_score += synergy[arr[e.first]][arr[e.second]];\n        }\n\n        // 5. Hill-climb to improve placement\n        const int ITER = 200000;  // can be tuned (time is generous per test)\n        for (int it = 0; it < ITER; it++) {\n            int p1 = (int)(rng() % SZ);\n            int p2 = (int)(rng() % SZ);\n            if (p1 == p2) continue;\n\n            int s1 = arr[p1];\n            int s2 = arr[p2];\n            if (s1 == s2) continue;\n\n            double delta = 0.0;\n\n            // Edges incident to p1 (excluding p2)\n            for (int nb : neighbors[p1]) {\n                if (nb == p2) continue; // edge (p1,p2) unchanged (synergy symmetric)\n                int s_nb = arr[nb];\n                delta -= synergy[s1][s_nb];\n                delta += synergy[s2][s_nb];\n            }\n            // Edges incident to p2 (excluding p1)\n            for (int nb : neighbors[p2]) {\n                if (nb == p1) continue;\n                int s_nb = arr[nb];\n                delta -= synergy[s2][s_nb];\n                delta += synergy[s1][s_nb];\n            }\n\n            if (delta > 0.0) {\n                cur_score += delta;\n                swap(arr[p1], arr[p2]);\n            }\n        }\n\n        // 6. Output arrangement for this turn\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                if (j) cout << ' ';\n                cout << arr[i * N + j];\n            }\n            cout << '\\n';\n        }\n        cout.flush();\n\n        // 7. Read next generation seeds (even after last turn, as per spec)\n        if (turn + 1 < T) {\n            for (int i = 0; i < SEED_COUNT; i++) {\n                for (int l = 0; l < M; l++) {\n                    cin >> x[i][l];\n                }\n            }\n        } else {\n            // For the last turn, the judge may still send the final seeds.\n            // Reading them is safe and matches the sample solution's behavior.\n            for (int i = 0; i < SEED_COUNT; i++) {\n                for (int l = 0; l < M; l++) {\n                    int tmp;\n                    if (!(cin >> tmp)) {\n                        // If input ends here, just stop reading.\n                        break;\n                    }\n                    // We don't use tmp, since this is the final generation.\n                }\n            }\n        }\n    }\n\n    return 0;\n}","ahc038":"#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, V;\n    if (!(cin >> N >> M >> V)) return 0;\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    // Occupancy grid (current takoyaki positions)\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            if (s[i][j] == '1') occ[i][j] = 1;\n        }\n    }\n\n    // Collect mismatched cells\n    vector<pair<int,int>> sources; // s=1, t=0\n    vector<pair<int,int>> targets; // s=0, t=1\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (s[i][j] == '1' && t[i][j] == '0') {\n                sources.emplace_back(i, j);\n            } else if (s[i][j] == '0' && t[i][j] == '1') {\n                targets.emplace_back(i, j);\n            }\n        }\n    }\n\n    // Simple pairing: sort row-major and pair i-th source with i-th target\n    sort(sources.begin(), sources.end());\n    sort(targets.begin(), targets.end());\n    int K = min((int)sources.size(), (int)targets.size());\n\n    // Arm model:\n    // V' = 2: vertex 0 = root, vertex 1 = fingertip, length = 1\n    const int Vp = 2;\n\n    // Movement directions: 0=Right, 1=Down, 2=Left, 3=Up\n    const int DX[4] = {0, 1, 0, -1};\n    const int DY[4] = {1, 0, -1, 0};\n\n    // Plan operations\n    vector<string> cmds;\n    cmds.reserve(100000);\n\n    int rootX = 0, rootY = 0; // initial root position\n    int initRootX = rootX, initRootY = rootY;\n    int dir = 0;              // initial direction: Right\n    bool holding = false;     // fingertip is empty\n\n    auto add_step = [&](char mv, char rot, bool doP) {\n        string S(2 * Vp, '.'); // length 4\n        S[0] = mv;             // movement\n        S[1] = rot;            // rotation of vertex 1\n        // S[2] is root action -> always '.'\n        if (doP) S[3] = 'P';   // fingertip action\n        cmds.push_back(S);\n\n        // Update root position\n        if (mv == 'U') rootX--;\n        else if (mv == 'D') rootX++;\n        else if (mv == 'L') rootY--;\n        else if (mv == 'R') rootY++;\n\n        // Update direction\n        if (rot == 'L') dir = (dir + 3) & 3;\n        else if (rot == 'R') dir = (dir + 1) & 3;\n    };\n\n    auto move_root = [&](int nx, int ny) {\n        while (rootX < nx) add_step('D', '.', false);\n        while (rootX > nx) add_step('U', '.', false);\n        while (rootY < ny) add_step('R', '.', false);\n        while (rootY > ny) add_step('L', '.', false);\n    };\n\n    auto rotate_to = [&](int ndir) {\n        int diff = (ndir - dir + 4) & 3;\n        if (diff == 0) return;\n        if (diff <= 2) {\n            for (int k = 0; k < diff; k++) add_step('.', 'R', false);\n        } else {\n            int steps = 4 - diff;\n            for (int k = 0; k < steps; k++) add_step('.', 'L', false);\n        }\n    };\n\n    auto finger_x = [&]() { return rootX + DX[dir]; };\n    auto finger_y = [&]() { return rootY + DY[dir]; };\n\n    // Move fingertip to be exactly on (tx, ty)\n    auto move_finger_to = [&](int tx, int ty) {\n        int bestNX = rootX, bestNY = rootY, bestDir = dir;\n        int bestCost = INT_MAX;\n\n        for (int ndir = 0; ndir < 4; ndir++) {\n            int nrX = tx - DX[ndir];\n            int nrY = ty - DY[ndir];\n            if (nrX < 0 || nrX >= N || nrY < 0 || nrY >= N) continue;\n            int dist = abs(nrX - rootX) + abs(nrY - rootY);\n            int diff = (ndir - dir + 4) & 3;\n            int rotCost = min(diff, 4 - diff);\n            int cost = dist + rotCost;\n            if (cost < bestCost) {\n                bestCost = cost;\n                bestNX = nrX;\n                bestNY = nrY;\n                bestDir = ndir;\n            }\n        }\n\n        move_root(bestNX, bestNY);\n        rotate_to(bestDir);\n        // Now fingertip should be at (tx, ty)\n    };\n\n    for (int i = 0; i < K; i++) {\n        int sx = sources[i].first;\n        int sy = sources[i].second;\n        int tx = targets[i].first;\n        int ty = targets[i].second;\n\n        // Move fingertip to source\n        move_finger_to(sx, sy);\n        int fx = finger_x(), fy = finger_y();\n        // Safety (should always hold)\n        // assert(fx == sx && fy == sy);\n        // Perform pick\n        // Ensure legality according to our internal state\n        if (!holding && fx >= 0 && fx < N && fy >= 0 && fy < N && occ[fx][fy] == 1) {\n            add_step('.', '.', true);\n            holding = true;\n            occ[fx][fy] = 0;\n        } else {\n            // Should not happen with our construction; if it does, skip P to avoid illegal move\n            add_step('.', '.', false);\n        }\n\n        // Move fingertip to target\n        move_finger_to(tx, ty);\n        fx = finger_x();\n        fy = finger_y();\n        // assert(fx == tx && fy == ty);\n        // Perform drop\n        if (holding && fx >= 0 && fx < N && fy >= 0 && fy < N && occ[fx][fy] == 0) {\n            add_step('.', '.', true);\n            holding = false;\n            occ[fx][fy] = 1;\n        } else {\n            // Again, should not happen; skip P if something is inconsistent\n            add_step('.', '.', false);\n        }\n    }\n\n    // Output\n    // 1) Tree description\n    cout << Vp << '\\n';\n    // vertex 1: parent 0, length 1\n    cout << 0 << ' ' << 1 << '\\n';\n\n    // 2) Initial root position\n    cout << initRootX << ' ' << initRootY << '\\n';\n\n    // 3) Operation sequence\n    for (const string &S : cmds) {\n        cout << S << '\\n';\n    }\n\n    return 0;\n}","ahc039":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Rect {\n    int xL, yB, xR, yT;\n    int diff;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    if (!(cin >> N)) return 0;\n    int total = 2 * N;\n\n    const int MAXC = 100000;\n    const int FULL = MAXC + 1; // 100001\n\n    vector<int> xs(total), ys(total);\n    for (int i = 0; i < total; ++i) {\n        cin >> xs[i] >> ys[i];\n    }\n\n    // Evaluate diff (mackerels - sardines) inside a given rectangle.\n    auto evaluateRectDiff = [&](int xL, int yB, int xR, int yT) -> int {\n        if (xL > xR || yB > yT) return INT_MIN / 2;\n        int diff = 0;\n        for (int i = 0; i < total; ++i) {\n            if (xs[i] >= xL && xs[i] <= xR &&\n                ys[i] >= yB && ys[i] <= yT) {\n                diff += (i < N ? 1 : -1);\n            }\n        }\n        return diff;\n    };\n\n    // Start with whole area: includes all fish, diff = 0.\n    Rect best;\n    best.xL = 0;\n    best.yB = 0;\n    best.xR = MAXC;\n    best.yT = MAXC;\n    best.diff = 0;\n\n    // Grid sizes to try (square grids S x S).\n    vector<int> gridSizes = {40, 60, 90, 130};\n    // Weight modes: {weight_mackerel, weight_sardine}\n    vector<pair<int,int>> weightModes = {\n        {1, -1},\n        {1, -2}\n    };\n\n    vector<int> grid;\n    vector<int> colSum;\n\n    for (int S : gridSizes) {\n        int H = S, W = S;\n        grid.assign(H * W, 0);\n        colSum.assign(W, 0);\n\n        for (auto [wM, wS] : weightModes) {\n            fill(grid.begin(), grid.end(), 0);\n\n            // Accumulate grid values\n            for (int i = 0; i < total; ++i) {\n                long long x = xs[i];\n                long long y = ys[i];\n                int ix = int(x * W / FULL); // 0..W-1\n                int iy = int(y * H / FULL); // 0..H-1\n                int w = (i < N ? wM : wS);\n                grid[iy * W + ix] += w;\n            }\n\n            // 2D Kadane: max sum sub-rectangle\n            int bestSum = INT_MIN / 2;\n            int bestTop = 0, bestBottom = 0, bestLeft = 0, bestRight = 0;\n\n            for (int top = 0; top < H; ++top) {\n                fill(colSum.begin(), colSum.end(), 0);\n                for (int bottom = top; bottom < H; ++bottom) {\n                    int rowOffset = bottom * W;\n                    for (int c = 0; c < W; ++c) {\n                        colSum[c] += grid[rowOffset + c];\n                    }\n                    // 1D Kadane on colSum\n                    int sum = 0, curLeft = 0;\n                    for (int c = 0; c < W; ++c) {\n                        if (sum <= 0) {\n                            sum = colSum[c];\n                            curLeft = c;\n                        } else {\n                            sum += colSum[c];\n                        }\n                        if (sum > bestSum) {\n                            bestSum = sum;\n                            bestTop = top;\n                            bestBottom = bottom;\n                            bestLeft = curLeft;\n                            bestRight = c;\n                        }\n                    }\n                }\n            }\n\n            // Map grid indices to coordinate rectangle.\n            // We don't need exact tight mapping; any rectangle covering the\n            // selected grid cells is fine since we re-evaluate true diff.\n            int left = bestLeft;\n            int right = bestRight;\n            int top = bestTop;\n            int bottom = bestBottom;\n\n            // Map so that all points in those grid cells are certainly inside.\n            // Approximate mapping: scale indices to [0, MAXC].\n            int xL = int((1LL * left * FULL + W - 1) / W);                // ceil\n            int xR = int((1LL * (right + 1) * FULL - 1) / W);             // floor\n            int yB = int((1LL * top * FULL + H - 1) / H);                 // ceil\n            int yT = int((1LL * (bottom + 1) * FULL - 1) / H);            // floor\n\n            // Clamp to valid coordinate range\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\n            if (xL > xR || yB > yT) continue;\n\n            int diff = evaluateRectDiff(xL, yB, xR, yT);\n            if (diff > best.diff) {\n                best = {xL, yB, xR, yT, diff};\n            }\n        }\n    }\n\n    // Optional fallback: if no positive diff found, try small rectangles\n    // around each mackerel. Usually this won't be needed.\n    if (best.diff <= 0) {\n        const int delta = 1000;\n        for (int i = 0; i < N; ++i) {\n            int xL = max(0, xs[i] - delta);\n            int xR = min(MAXC, xs[i] + delta);\n            int yB = max(0, ys[i] - delta);\n            int yT = min(MAXC, ys[i] + delta);\n            int diff = evaluateRectDiff(xL, yB, xR, yT);\n            if (diff > best.diff) {\n                best = {xL, yB, xR, yT, diff};\n            }\n        }\n    }\n\n    // Ensure positive width/height (should already be true, but be safe).\n    if (best.xL == best.xR) {\n        if (best.xL > 0) best.xL--;\n        else best.xR++;\n    }\n    if (best.yB == best.yT) {\n        if (best.yB > 0) best.yB--;\n        else best.yT++;\n    }\n    best.xL = max(0, min(MAXC, best.xL));\n    best.xR = max(0, min(MAXC, best.xR));\n    best.yB = max(0, min(MAXC, best.yB));\n    best.yT = max(0, min(MAXC, best.yT));\n\n    // Output rectangle polygon (4 vertices).\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\n    return 0;\n}","ahc040":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct EvalResult {\n    long long W = (1LL<<62);\n    long long H = (1LL<<62);\n    long long S = (1LL<<62);\n    vector<int> cuts; // row boundaries: 0 = cuts[0] < ... < cuts[R] = N\n};\n\n// Evaluate a given orientation vector 'rot' (0=no-rot,1=rot):\n// compute best shelf segmentation (contiguous rows) and return W,H,S and cuts.\nEvalResult evaluate_orientation(const vector<long long>& w0,\n                                const vector<long long>& h0,\n                                const vector<int>& rot) {\n    int N = (int)w0.size();\n    const long long INF = (1LL<<62);\n\n    // Build width/height under this orientation\n    vector<long long> width(N), height(N);\n    long long sumW = 0, maxW = 0;\n    long double area = 0.0L;\n\n    for (int i = 0; i < N; i++) {\n        if (rot[i] == 0) {\n            width[i]  = w0[i];\n            height[i] = h0[i];\n        } else {\n            width[i]  = h0[i];\n            height[i] = w0[i];\n        }\n        sumW += width[i];\n        maxW = max(maxW, width[i]);\n        area += (long double)width[i] * (long double)height[i];\n    }\n\n    if (sumW == 0) { // degenerate, shouldn't happen\n        EvalResult res;\n        res.W = res.H = res.S = 0;\n        res.cuts = {0, N};\n        return res;\n    }\n\n    // Candidate width limits\n    vector<long long> Ws;\n    Ws.reserve(16);\n    Ws.push_back(sumW);  // one big row (upper extreme)\n    Ws.push_back(maxW);  // narrow rows (lower extreme)\n\n    long double base = sqrtl(max((long double)1.0L, area));\n    long double low  = max((long double)maxW, base * 0.5L);\n    long double high = min((long double)sumW, base * 2.0L);\n    if (high < low) high = low;\n\n    const int EXTRA = 10;\n    if (high == low) {\n        long long Wc = (long long)(low + 0.5L);\n        Ws.push_back(Wc);\n    } else {\n        for (int k = 0; k < EXTRA; k++) {\n            long double t = (k + 0.5L) / (long double)EXTRA;\n            long double w = low + (high - low) * t;\n            long long Wc = (long long)(w + 0.5L);\n            if (Wc < maxW) Wc = maxW;\n            if (Wc > sumW) Wc = sumW;\n            Ws.push_back(Wc);\n        }\n    }\n\n    sort(Ws.begin(), Ws.end());\n    Ws.erase(unique(Ws.begin(), Ws.end()), Ws.end());\n\n    EvalResult best;\n\n    vector<long long> dp(N + 1);\n    vector<int> prev(N + 1);\n\n    for (long long W_limit : Ws) {\n        // DP over prefix length\n        dp[0] = 0;\n        prev[0] = -1;\n        for (int i = 1; i <= N; i++) {\n            long long bestH = INF;\n            int bestJ = -1;\n            long long rowW = 0;\n            long long rowH = 0;\n            // consider last row being [j, i)\n            for (int j = i - 1; j >= 0; j--) {\n                rowW += width[j];\n                if (rowW > W_limit) break;\n                if (height[j] > rowH) rowH = height[j];\n                long long cand = dp[j] + rowH;\n                if (cand < bestH) {\n                    bestH = cand;\n                    bestJ = j;\n                }\n            }\n            dp[i] = bestH;\n            prev[i] = bestJ;\n        }\n        if (prev[N] == -1 || dp[N] >= INF) continue;\n\n        // Recover cuts\n        vector<int> cuts;\n        int cur = N;\n        cuts.push_back(N);\n        while (cur > 0) {\n            int pj = prev[cur];\n            if (pj < 0) { cuts.clear(); break; }\n            cuts.push_back(pj);\n            cur = pj;\n        }\n        if (cuts.empty()) continue;\n        if (cuts.back() != 0) {\n            // something went wrong; skip\n            continue;\n        }\n        reverse(cuts.begin(), cuts.end());\n\n        // Compute actual W,H\n        long long Htotal = 0;\n        long long Wactual = 0;\n        int R = (int)cuts.size() - 1;\n        for (int r = 0; r < R; r++) {\n            int L = cuts[r];\n            int Ridx = cuts[r+1];\n            long long rowW = 0;\n            long long rowH = 0;\n            for (int i = L; i < Ridx; i++) {\n                rowW += width[i];\n                if (height[i] > rowH) rowH = height[i];\n            }\n            Htotal += rowH;\n            if (rowW > Wactual) Wactual = rowW;\n        }\n        long long S = Htotal + Wactual;\n        if (S < best.S) {\n            best.S = S;\n            best.W = Wactual;\n            best.H = Htotal;\n            best.cuts = std::move(cuts);\n        }\n    }\n\n    // As a fallback, ensure we have some segmentation\n    if (best.S >= INF) {\n        best.cuts = {0, N};\n        long long Htotal = 0, Wactual = 0;\n        long long rowW = 0, rowH = 0;\n        for (int i = 0; i < N; i++) {\n            rowW += width[i];\n            if (height[i] > rowH) rowH = height[i];\n        }\n        Htotal = rowH;\n        Wactual = rowW;\n        best.W = Wactual;\n        best.H = Htotal;\n        best.S = Wactual + Htotal;\n    }\n\n    return best;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, T;\n    long long sigma;\n    if (!(cin >> N >> T >> sigma)) {\n        return 0;\n    }\n\n    vector<long long> w0(N), h0(N);\n    for (int i = 0; i < N; i++) {\n        cin >> w0[i] >> h0[i];\n        if (w0[i] < 1) w0[i] = 1;\n        if (h0[i] < 1) h0[i] = 1;\n    }\n\n    // Initial orientation: minimize height\n    vector<int> rot(N);\n    for (int i = 0; i < N; i++) {\n        // If h <= w, keep; else rotate so height=min\n        rot[i] = (h0[i] > w0[i]) ? 1 : 0;\n    }\n\n    // Local search over orientations\n    EvalResult bestEval = evaluate_orientation(w0, h0, rot);\n\n    const int MAX_PASSES = 2;\n    for (int pass = 0; pass < MAX_PASSES; pass++) {\n        bool improved = false;\n        for (int i = 0; i < N; i++) {\n            rot[i] ^= 1; // toggle\n            EvalResult cand = evaluate_orientation(w0, h0, rot);\n            if (cand.S < bestEval.S) {\n                bestEval = cand;\n                improved = true;\n            } else {\n                rot[i] ^= 1; // revert\n            }\n        }\n        if (!improved) break;\n    }\n\n    // Final width/height arrays under chosen orientation\n    vector<long long> width(N), height(N);\n    for (int i = 0; i < N; i++) {\n        if (rot[i] == 0) {\n            width[i]  = w0[i];\n            height[i] = h0[i];\n        } else {\n            width[i]  = h0[i];\n            height[i] = w0[i];\n        }\n    }\n\n    // Derive row index for each rectangle, and bases per row\n    vector<int>& cuts = bestEval.cuts;\n    int R = (int)cuts.size() - 1; // number of rows\n    vector<int> rowOf(N, 0);\n    for (int r = 0; r < R; r++) {\n        for (int i = cuts[r]; i < cuts[r+1]; i++) {\n            rowOf[i] = r;\n        }\n    }\n    vector<int> base(R, -1);\n    for (int r = 0; r < R; r++) {\n        int L = cuts[r];\n        int Ridx = cuts[r+1];\n        long long bestH = -1;\n        int bestIdx = L;\n        for (int i = L; i < Ridx; i++) {\n            if (height[i] > bestH) {\n                bestH = height[i];\n                bestIdx = i;\n            }\n        }\n        base[r] = bestIdx;\n    }\n\n    // We output the same arrangement T times\n    for (int t = 0; t < T; t++) {\n        // Number of rectangles used: all N\n        cout << N << '\\n';\n        for (int i = 0; i < N; i++) {\n            int r = rowOf[i];\n            int b = -1;\n            if (r > 0) {\n                b = base[r - 1]; // base of previous row\n            }\n            char d = 'L';\n            cout << i << ' ' << rot[i] << ' ' << d << ' ' << b << '\\n';\n        }\n        cout.flush();\n\n        long long Wm, Hm;\n        if (!(cin >> Wm >> Hm)) {\n            // In official judge this should not happen, but be safe\n            return 0;\n        }\n    }\n\n    return 0;\n}","ahc041":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct FastRand {\n    uint64_t x;\n    FastRand() {\n        x = 88172645463393265ull;\n    }\n    uint64_t next() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return x;\n    }\n    int nextInt(int n) { // 0..n-1\n        return (int)(next() % (uint64_t)n);\n    }\n    double nextDouble() {\n        return (next() >> 11) * (1.0 / 9007199254740992.0); // [0,1)\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, H;\n    if (!(cin >> N >> M >> H)) {\n        return 0;\n    }\n\n    vector<int> A(N);\n    for (int i = 0; i < N; ++i) cin >> A[i];\n\n    vector<vector<int>> adj(N);\n    for (int i = 0; i < M; ++i) {\n        int u, v;\n        cin >> u >> v;\n        adj[u].push_back(v);\n        adj[v].push_back(u);\n    }\n\n    // Read coordinates but we don't use them in this solution.\n    vector<int> x(N), y(N);\n    for (int i = 0; i < N; ++i) cin >> x[i] >> y[i];\n\n    // ---------- Initial forest construction (ascending beauty) ----------\n\n    vector<int> parent(N, -1);\n    vector<int> depth(N, 0);\n    vector<char> processed(N, 0);\n\n    vector<int> order(N);\n    iota(order.begin(), order.end(), 0);\n    sort(order.begin(), order.end(), [&](int i, int j) {\n        if (A[i] != A[j]) return A[i] < A[j];\n        return i < j;\n    });\n\n    for (int idx = 0; idx < N; ++idx) {\n        int v = order[idx];\n        processed[v] = 1;\n        int bestParent = -1;\n        int bestDepth = -1;\n        for (int u : adj[v]) {\n            if (!processed[u]) continue; // only earlier vertices\n            if (depth[u] > H - 1) continue; // parent depth must allow child depth \u2264 H\n            if (depth[u] > bestDepth) {\n                bestDepth = depth[u];\n                bestParent = u;\n            }\n        }\n        if (bestParent == -1) {\n            parent[v] = -1;\n            depth[v] = 0;\n        } else {\n            parent[v] = bestParent;\n            depth[v] = depth[bestParent] + 1;\n            if (depth[v] > H) {\n                // Should not happen due to check above, but just in case, clamp:\n                depth[v] = H;\n            }\n        }\n    }\n\n    // ---------- Build children lists ----------\n    vector<vector<int>> children(N);\n    for (int v = 0; v < N; ++v) {\n        int p = parent[v];\n        if (p != -1) {\n            children[p].push_back(v);\n        }\n    }\n\n    // ---------- Compute subtreeSum and subHeight bottom-up ----------\n    vector<vector<int>> nodesAtDepth(H + 1);\n    for (int v = 0; v < N; ++v) {\n        int d = depth[v];\n        if (d < 0) d = 0;\n        if (d > H) d = H; // safety\n        nodesAtDepth[d].push_back(v);\n    }\n\n    vector<long long> subtreeSum(N, 0);\n    vector<int> subHeight(N, 0);\n\n    for (int d = H; d >= 0; --d) {\n        for (int v : nodesAtDepth[d]) {\n            long long sum = A[v];\n            int h = 0;\n            for (int c : children[v]) {\n                sum += subtreeSum[c];\n                h = max(h, 1 + subHeight[c]);\n            }\n            subtreeSum[v] = sum;\n            subHeight[v] = h;\n        }\n    }\n\n    // ---------- Compute initial score ----------\n    long long score = 0;\n    for (int v = 0; v < N; ++v) {\n        int d = depth[v];\n        if (d < 0) d = 0;\n        if (d > H) d = H; // safety\n        score += (long long)(d + 1) * (long long)A[v];\n    }\n\n    // After this, we no longer trust `depth[]` and compute depths on demand.\n\n    auto getDepth = [&](int v) -> int {\n        int d = 0;\n        while (parent[v] != -1) {\n            v = parent[v];\n            ++d;\n        }\n        return d; // at most H\n    };\n\n    auto recomputeHeightFrom = [&](int start) {\n        int x = start;\n        while (x != -1) {\n            int old_h = subHeight[x];\n            int new_h = 0;\n            for (int c : children[x]) {\n                new_h = max(new_h, 1 + subHeight[c]);\n            }\n            if (new_h == old_h) break;\n            subHeight[x] = new_h;\n            x = parent[x];\n        }\n    };\n\n    auto reparentFn = [&](int v, int newParent, int oldDepth, int newDepth) {\n        int oldParent = parent[v];\n        if (oldParent == newParent) return;\n        long long deltaDepth = (long long)(newDepth - oldDepth);\n        long long deltaScore = deltaDepth * subtreeSum[v];\n        score += deltaScore;\n\n        // Update subtreeSum along old parent path\n        if (oldParent != -1) {\n            for (int x = oldParent; x != -1; x = parent[x]) {\n                subtreeSum[x] -= subtreeSum[v];\n            }\n        }\n\n        // Update subtreeSum along new parent path\n        if (newParent != -1) {\n            for (int x = newParent; x != -1; x = parent[x]) {\n                subtreeSum[x] += subtreeSum[v];\n            }\n        }\n\n        // Update children lists\n        if (oldParent != -1) {\n            auto &vec = children[oldParent];\n            for (int i = 0; i < (int)vec.size(); ++i) {\n                if (vec[i] == v) {\n                    vec[i] = vec.back();\n                    vec.pop_back();\n                    break;\n                }\n            }\n        }\n        if (newParent != -1) {\n            children[newParent].push_back(v);\n        }\n\n        parent[v] = newParent;\n\n        // Update heights along old and new parent paths\n        if (oldParent != -1) {\n            recomputeHeightFrom(oldParent);\n        }\n        if (newParent != -1) {\n            recomputeHeightFrom(newParent);\n        }\n    };\n\n    // ---------- Greedy local improvement ----------\n\n    vector<int> orderDesc(N);\n    iota(orderDesc.begin(), orderDesc.end(), 0);\n    sort(orderDesc.begin(), orderDesc.end(), [&](int i, int j) {\n        if (A[i] != A[j]) return A[i] > A[j];\n        return i < j;\n    });\n\n    bool improved;\n    do {\n        improved = false;\n        for (int v : orderDesc) {\n            int oldParent = parent[v];\n            int oldDepth = getDepth(v);\n            long long bestDelta = 0;\n            int bestParent = oldParent;\n            int bestNewDepth = oldDepth;\n\n            for (int u : adj[v]) {\n                if (u == oldParent) continue;\n\n                // Check if u is in subtree of v (avoid cycles)\n                int x = u;\n                bool cyc = false;\n                while (x != -1) {\n                    if (x == v) {\n                        cyc = true;\n                        break;\n                    }\n                    x = parent[x];\n                }\n                if (cyc) continue;\n\n                int depth_u = getDepth(u);\n                int newDepth = depth_u + 1;\n                if (newDepth > H) continue;\n                if (newDepth + subHeight[v] > H) continue;\n\n                long long deltaScore = (long long)(newDepth - oldDepth) * subtreeSum[v];\n                if (deltaScore > bestDelta) {\n                    bestDelta = deltaScore;\n                    bestParent = u;\n                    bestNewDepth = newDepth;\n                }\n            }\n\n            if (bestParent != oldParent && bestDelta > 0) {\n                reparentFn(v, bestParent, oldDepth, bestNewDepth);\n                improved = true;\n            }\n        }\n    } while (improved);\n\n    // ---------- Output ----------\n    for (int i = 0; i < N; ++i) {\n        if (i) cout << ' ';\n        cout << parent[i];\n    }\n    cout << '\\n';\n\n    return 0;\n}","ahc042":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Operation {\n    char dir;      // 'U', 'D', 'L', 'R' : direction of the first half\n    int  p;        // row or column index\n    int  len;      // number of shifts in each direction\n    int  cost;     // 2 * len\n    uint64_t mask; // which Oni are removed by this operation\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    if (!(cin >> N)) return 0; // just in case\n    vector<string> C(N);\n    for (int i = 0; i < N; ++i) cin >> C[i];\n\n    // Collect Oni and Fuku positions\n    vector<pair<int,int>> oni;  // (row,col) for each Oni\n    vector<vector<int>> oni_id(N, vector<int>(N, -1));\n    vector<vector<bool>> fuku(N, vector<bool>(N, false));\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            char ch = C[i][j];\n            if (ch == 'x') {\n                int id = (int)oni.size();\n                oni.emplace_back(i, j);\n                oni_id[i][j] = id;\n            } else if (ch == 'o') {\n                fuku[i][j] = true;\n            }\n        }\n    }\n\n    int M = (int)oni.size(); // number of Oni, should be 2N\n    if (M == 0) {\n        // No Oni: nothing to do\n        return 0;\n    }\n\n    // Prefix sums of Fuku for rows and columns\n    vector<vector<int>> row_pref(N, vector<int>(N, 0));\n    vector<vector<int>> col_pref(N, vector<int>(N, 0));\n\n    for (int i = 0; i < N; ++i) {\n        int acc = 0;\n        for (int j = 0; j < N; ++j) {\n            if (fuku[i][j]) acc++;\n            row_pref[i][j] = acc;\n        }\n    }\n    for (int j = 0; j < N; ++j) {\n        int acc = 0;\n        for (int i = 0; i < N; ++i) {\n            if (fuku[i][j]) acc++;\n            col_pref[j][i] = acc;\n        }\n    }\n\n    vector<Operation> ops;\n\n    // Build all safe column operations\n    for (int j = 0; j < N; ++j) {\n        int total_fuku_col = col_pref[j][N-1];\n\n        // Up-prefix [0..h]\n        for (int h = 0; h < N; ++h) {\n            if (col_pref[j][h] == 0) { // no Fuku in [0..h]\n                uint64_t mask = 0;\n                for (int id = 0; id < M; ++id) {\n                    auto [r, c] = oni[id];\n                    if (c == j && r <= h) {\n                        mask |= (1ULL << id);\n                    }\n                }\n                if (mask) {\n                    int len = h + 1;\n                    Operation op;\n                    op.dir = 'U';\n                    op.p = j;\n                    op.len = len;\n                    op.cost = 2 * len;\n                    op.mask = mask;\n                    ops.push_back(op);\n                }\n            }\n        }\n\n        // Down-suffix [h..N-1]\n        for (int h = 0; h < N; ++h) {\n            int fuku_cnt = total_fuku_col - (h > 0 ? col_pref[j][h-1] : 0);\n            if (fuku_cnt == 0) { // no Fuku in [h..N-1]\n                uint64_t mask = 0;\n                for (int id = 0; id < M; ++id) {\n                    auto [r, c] = oni[id];\n                    if (c == j && r >= h) {\n                        mask |= (1ULL << id);\n                    }\n                }\n                if (mask) {\n                    int len = N - h;\n                    Operation op;\n                    op.dir = 'D';\n                    op.p = j;\n                    op.len = len;\n                    op.cost = 2 * len;\n                    op.mask = mask;\n                    ops.push_back(op);\n                }\n            }\n        }\n    }\n\n    // Build all safe row operations\n    for (int i = 0; i < N; ++i) {\n        int total_fuku_row = row_pref[i][N-1];\n\n        // Left-prefix [0..h]\n        for (int h = 0; h < N; ++h) {\n            if (row_pref[i][h] == 0) { // no Fuku in [0..h]\n                uint64_t mask = 0;\n                for (int id = 0; id < M; ++id) {\n                    auto [r, c] = oni[id];\n                    if (r == i && c <= h) {\n                        mask |= (1ULL << id);\n                    }\n                }\n                if (mask) {\n                    int len = h + 1;\n                    Operation op;\n                    op.dir = 'L';\n                    op.p = i;\n                    op.len = len;\n                    op.cost = 2 * len;\n                    op.mask = mask;\n                    ops.push_back(op);\n                }\n            }\n        }\n\n        // Right-suffix [h..N-1]\n        for (int h = 0; h < N; ++h) {\n            int fuku_cnt = total_fuku_row - (h > 0 ? row_pref[i][h-1] : 0);\n            if (fuku_cnt == 0) { // no Fuku in [h..N-1]\n                uint64_t mask = 0;\n                for (int id = 0; id < M; ++id) {\n                    auto [r, c] = oni[id];\n                    if (r == i && c >= h) {\n                        mask |= (1ULL << id);\n                    }\n                }\n                if (mask) {\n                    int len = N - h;\n                    Operation op;\n                    op.dir = 'R';\n                    op.p = i;\n                    op.len = len;\n                    op.cost = 2 * len;\n                    op.mask = mask;\n                    ops.push_back(op);\n                }\n            }\n        }\n    }\n\n    if (ops.empty()) {\n        // Should not happen due to problem guarantees, but be safe:\n        // fall back to doing nothing (this will score very poorly but stay legal).\n        return 0;\n    }\n\n    uint64_t all_mask = (M == 64) ? ~0ULL : ((1ULL << M) - 1);\n\n    // RNG for randomized greedy\n    uint64_t seed = chrono::steady_clock::now().time_since_epoch().count();\n    mt19937_64 rng(seed);\n\n    auto run_greedy = [&](mt19937_64 &rng) -> pair<int, vector<int>> {\n        uint64_t uncovered = all_mask;\n        vector<int> sel;\n        int total_cost = 0;\n\n        // At most M iterations since each step must cover at least one new Oni\n        while (uncovered) {\n            double best_ratio = -1.0;\n            vector<int> best_ops;\n\n            // First pass: find best ratio and collect all ops with that ratio (for tie-breaking)\n            for (int i = 0; i < (int)ops.size(); ++i) {\n                uint64_t gain_mask = ops[i].mask & uncovered;\n                if (!gain_mask) continue;\n                int gain = __builtin_popcountll(gain_mask);\n                double ratio = (double)gain / (double)ops[i].cost;\n                if (ratio > best_ratio + 1e-12) {\n                    best_ratio = ratio;\n                    best_ops.clear();\n                    best_ops.push_back(i);\n                } else if (ratio >= best_ratio - 1e-12) {\n                    best_ops.push_back(i);\n                }\n            }\n\n            if (best_ops.empty()) {\n                // Should not happen: every uncovered Oni should belong to at least one operation\n                break;\n            }\n\n            int chosen_idx;\n            if ((int)best_ops.size() == 1) {\n                chosen_idx = best_ops[0];\n            } else {\n                uniform_int_distribution<int> dist(0, (int)best_ops.size()-1);\n                chosen_idx = best_ops[dist(rng)];\n            }\n\n            sel.push_back(chosen_idx);\n            uint64_t covered_now = ops[chosen_idx].mask & uncovered;\n            uncovered &= ~covered_now;\n            total_cost += ops[chosen_idx].cost;\n        }\n\n        // Simple pruning: try to delete redundant operations\n        vector<int> cover_count(M, 0);\n        for (int idx : sel) {\n            uint64_t m = ops[idx].mask;\n            while (m) {\n                int b = __builtin_ctzll(m);\n                m &= m - 1;\n                cover_count[b]++;\n            }\n        }\n\n        bool improved = true;\n        while (improved) {\n            improved = false;\n            for (int pos = 0; pos < (int)sel.size(); ++pos) {\n                int op_idx = sel[pos];\n                uint64_t m = ops[op_idx].mask;\n                bool canRemove = true;\n                uint64_t tmp = m;\n                while (tmp) {\n                    int b = __builtin_ctzll(tmp);\n                    tmp &= tmp - 1;\n                    if (cover_count[b] == 1) { // unique coverage\n                        canRemove = false;\n                        break;\n                    }\n                }\n                if (!canRemove) continue;\n                // Remove op_idx\n                tmp = m;\n                while (tmp) {\n                    int b = __builtin_ctzll(tmp);\n                    tmp &= tmp - 1;\n                    cover_count[b]--;\n                }\n                total_cost -= ops[op_idx].cost;\n                sel.erase(sel.begin() + pos);\n                --pos;\n                improved = true;\n            }\n        }\n\n        return {total_cost, sel};\n    };\n\n    int best_cost = INT_MAX;\n    vector<int> best_sel;\n\n    const int MAX_RUNS = 400; // number of multi-start greedy runs\n    for (int iter = 0; iter < MAX_RUNS; ++iter) {\n        auto [cost, sel] = run_greedy(rng);\n        // Verify that this solution indeed covers all Oni (for safety)\n        uint64_t covered = 0;\n        for (int idx : sel) covered |= ops[idx].mask;\n        if (covered != all_mask) {\n            // Should not happen; skip if incomplete\n            continue;\n        }\n        if (cost < best_cost) {\n            best_cost = cost;\n            best_sel = move(sel);\n        }\n    }\n\n    if (best_sel.empty()) {\n        // Fallback: run one deterministic greedy without pruning\n        auto [cost, sel] = run_greedy(rng);\n        best_cost = cost;\n        best_sel = move(sel);\n    }\n\n    // Build the actual move sequence from best_sel\n    vector<pair<char,int>> moves;\n    moves.reserve(best_cost); // upper bound on moves\n\n    for (int idx : best_sel) {\n        const Operation &op = ops[idx];\n        char d1 = op.dir;\n        char d2;\n        if      (d1 == 'U') d2 = 'D';\n        else if (d1 == 'D') d2 = 'U';\n        else if (d1 == 'L') d2 = 'R';\n        else               d2 = 'L';\n\n        for (int k = 0; k < op.len; ++k) moves.emplace_back(d1, op.p);\n        for (int k = 0; k < op.len; ++k) moves.emplace_back(d2, op.p);\n    }\n\n    // Safety: ensure we don't exceed move limit\n    int T = (int)moves.size();\n    if (T > 4 * N * N) {\n        // In the very unlikely event this happens, we output nothing to stay legal.\n        // (But by construction T <= 40 * 40 = 1600 == 4*N*N when N=20.)\n        return 0;\n    }\n\n    // Output moves\n    for (auto &mv : moves) {\n        cout << mv.first << ' ' << mv.second << '\\n';\n    }\n\n    return 0;\n}","ahc044":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const int MAXN = 100;\n\nstruct Candidate {\n    int a[MAXN];\n    int b[MAXN];\n    int t[MAXN];\n    long long E;\n};\n\n// Evaluate candidate by rotor-router simulation for L weeks\nvoid evalCandidate(Candidate &cand, int N, int L, const vector<long long> &T) {\n    static int rotor[MAXN];\n    for (int i = 0; i < N; ++i) {\n        cand.t[i] = 0;\n        rotor[i] = 0;\n    }\n    int cur = 0;  // week 1 cleaner is 0\n\n    // weeks 1..L-1: decide next cleaner\n    for (int week = 0; week < L - 1; ++week) {\n        int x = cur;\n        cand.t[x]++;\n\n        int nxt = (rotor[x] == 0 ? cand.a[x] : cand.b[x]);\n        rotor[x] ^= 1;\n        cur = nxt;\n    }\n    // last week: count the final cleaner\n    cand.t[cur]++;\n\n    long long E = 0;\n    for (int i = 0; i < N; ++i) {\n        E += llabs((long long)cand.t[i] - T[i]);\n    }\n    cand.E = E;\n}\n\n// Build an \"ideal schedule\" based candidate using majority transitions\nCandidate buildMajorityCandidate(int N, int L, const vector<long long> &T, mt19937_64 &rng) {\n    Candidate cand;\n\n    // Work copy of T, ensure employee 0 appears at least once\n    vector<int> Twork(N);\n    for (int i = 0; i < N; ++i) Twork[i] = (int)T[i];\n\n    if (Twork[0] == 0) {\n        // find some j > 0 with maximum T[j]\n        int j = 1;\n        for (int i = 2; i < N; ++i) {\n            if (Twork[i] > Twork[j]) j = i;\n        }\n        // decrease that j, increase Twork[0]\n        if (Twork[j] > 0) {\n            Twork[0] = 1;\n            Twork[j]--;\n        } else {\n            // theoretically impossible because sum T = L > 0\n            // but keep safe: just set Twork[0] = 1 and reduce someone else if possible\n            for (int i = 1; i < N; ++i) {\n                if (Twork[i] > 0) {\n                    Twork[i]--;\n                    break;\n                }\n            }\n        }\n    }\n\n    // Build sequence of length L with counts Twork\n    vector<int> seq(L);\n    int pos = 0;\n    for (int i = 0; i < N; ++i) {\n        for (int k = 0; k < Twork[i]; ++k) {\n            if (pos < L) seq[pos++] = i;\n        }\n    }\n    // Just in case of rounding anomalies, truncate / fill (shouldn't happen in this construction)\n    if (pos < L) {\n        for (; pos < L; ++pos) seq[pos] = 0;\n    } else if (pos > L) {\n        seq.resize(L);\n    }\n\n    shuffle(seq.begin(), seq.end(), rng);\n\n    // Ensure seq[0] == 0 (since week1 cleaner is 0 in real process)\n    if (seq[0] != 0) {\n        for (int i = 1; i < L; ++i) {\n            if (seq[i] == 0) {\n                swap(seq[0], seq[i]);\n                break;\n            }\n        }\n        // if still not 0 (shouldn't happen if Twork[0] >= 1), just force it\n        seq[0] = 0;\n    }\n\n    // freqOdd[x][y]: # of times an odd visit to x is followed by y in seq\n    // freqEven[x][y]: even visits\n    vector<vector<int>> freqOdd(N, vector<int>(N, 0));\n    vector<vector<int>> freqEven(N, vector<int>(N, 0));\n    vector<int> cntVisit(N, 0);\n\n    for (int i = 0; i < N; ++i) cntVisit[i] = 0;\n\n    for (int i = 0; i < L - 1; ++i) {\n        int x = seq[i];\n        int y = seq[i + 1];\n        int k = ++cntVisit[x];\n        if (k & 1) freqOdd[x][y]++;\n        else       freqEven[x][y]++;\n    }\n\n    // Fallback destination: employee with largest T[i]\n    int fallback = 0;\n    for (int i = 1; i < N; ++i) {\n        if (T[i] > T[fallback]) fallback = i;\n    }\n\n    for (int x = 0; x < N; ++x) {\n        // choose a_x from odd visits\n        int best_j = fallback;\n        int best_c = 0;\n        for (int y = 0; y < N; ++y) {\n            if (freqOdd[x][y] > best_c) {\n                best_c = freqOdd[x][y];\n                best_j = y;\n            }\n        }\n        cand.a[x] = best_j;\n\n        // choose b_x from even visits\n        best_j = fallback;\n        best_c = 0;\n        for (int y = 0; y < N; ++y) {\n            if (freqEven[x][y] > best_c) {\n                best_c = freqEven[x][y];\n                best_j = y;\n            }\n        }\n        cand.b[x] = best_j;\n    }\n\n    evalCandidate(cand, N, L, T);\n    return cand;\n}\n\n// Build template of edge destinations by apportionment according to T\nvector<int> buildDestTemplate(int N, const vector<long long> &T) {\n    vector<double> w(N);\n    double sumW = 0.0;\n    for (int i = 0; i < N; ++i) {\n        // +1 to avoid zero weight\n        w[i] = (double)T[i] + 1.0;\n        sumW += w[i];\n    }\n    int totalEdges = 2 * N;\n\n    vector<double> ideal(N), frac(N);\n    vector<int> destCount(N, 0);\n    long long S = 0;\n\n    for (int i = 0; i < N; ++i) {\n        double val = totalEdges * w[i] / sumW;\n        ideal[i] = val;\n        int base = (int)floor(val);\n        destCount[i] = base;\n        frac[i] = val - base;\n        S += base;\n    }\n    int R = totalEdges - (int)S;\n    if (R < 0) R = 0;\n\n    // distribute remaining edges by largest fractional parts\n    vector<int> ord(N);\n    iota(ord.begin(), ord.end(), 0);\n    sort(ord.begin(), ord.end(), [&](int a, int b) {\n        return frac[a] > frac[b];\n    });\n    for (int k = 0; k < R && k < N; ++k) {\n        destCount[ord[k]]++;\n    }\n\n    vector<int> edgesDest;\n    edgesDest.reserve(totalEdges);\n    for (int i = 0; i < N; ++i) {\n        for (int c = 0; c < destCount[i]; ++c) {\n            edgesDest.push_back(i);\n        }\n    }\n    // If due to rounding we have slightly more/less, adjust just in case\n    while ((int)edgesDest.size() > totalEdges) edgesDest.pop_back();\n    while ((int)edgesDest.size() < totalEdges) edgesDest.push_back(0);\n\n    return edgesDest;\n}\n\n// Build a random candidate from a given destination template\nCandidate buildRandomCandidateFromTemplate(const vector<int> &edgesTemplate,\n                                           int N, int L,\n                                           const vector<long long> &T,\n                                           mt19937_64 &rng) {\n    Candidate cand;\n    vector<int> edges = edgesTemplate; // copy\n    shuffle(edges.begin(), edges.end(), rng);\n\n    for (int i = 0; i < N; ++i) {\n        cand.a[i] = edges[2 * i];\n        cand.b[i] = edges[2 * i + 1];\n    }\n    evalCandidate(cand, N, L, T);\n    return cand;\n}\n\n// Mutate node idx's outgoing edges in candidate based on deficits\nvoid mutateNode(int idx,\n                Candidate &cand,\n                int N,\n                const vector<long long> &T,\n                const vector<int> &deficit,\n                const vector<int> &posIndices,\n                const vector<long long> &posPrefix,\n                long long sumPos,\n                const vector<long long> &Tprefix,\n                long long sumTw,\n                mt19937_64 &rng) {\n    auto samplePos = [&]() -> int {\n        if (sumPos <= 0 || posIndices.empty()) {\n            return idx; // fallback (should not generally happen)\n        }\n        long long r = (long long)(rng() % sumPos);\n        int pos = int(lower_bound(posPrefix.begin(), posPrefix.end(), r + 1) - posPrefix.begin());\n        if (pos < 0) pos = 0;\n        if (pos >= (int)posIndices.size()) pos = (int)posIndices.size() - 1;\n        return posIndices[pos];\n    };\n\n    auto sampleTdist = [&]() -> int {\n        if (sumTw <= 0) return idx;\n        long long r = (long long)(rng() % sumTw);\n        int pos = int(upper_bound(Tprefix.begin(), Tprefix.end(), r) - Tprefix.begin());\n        if (pos < 0) pos = 0;\n        if (pos >= N) pos = N - 1;\n        return pos;\n    };\n\n    if (deficit[idx] > 0) {\n        // node needs more visits: encourage self-loop\n        cand.a[idx] = idx;\n        if (sumPos > 0) {\n            cand.b[idx] = samplePos();\n        } else {\n            cand.b[idx] = sampleTdist();\n        }\n    } else {\n        // node has enough or too many visits: redirect to under-visited nodes\n        if (sumPos > 0) {\n            cand.a[idx] = samplePos();\n            cand.b[idx] = samplePos();\n        } else {\n            cand.a[idx] = sampleTdist();\n            cand.b[idx] = sampleTdist();\n        }\n    }\n\n    // Ensure indices are within [0, N-1]\n    cand.a[idx] %= N;\n    cand.b[idx] %= N;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, L;\n    if (!(cin >> N >> L)) {\n        return 0;\n    }\n    vector<long long> T(N);\n    for (int i = 0; i < N; ++i) cin >> T[i];\n\n    // Problem guarantees N=100, L=500000, but we keep code general.\n    mt19937_64 rng(123456789ULL);\n\n    auto startTime = chrono::steady_clock::now();\n    const int TIME_LIMIT_MS = 1900;\n\n    // Pre-build destination template from T\n    vector<int> destTemplate = buildDestTemplate(N, T);\n\n    // Best candidate\n    Candidate best;\n    bool bestInitialized = false;\n\n    // 1) Majority-based candidate from a shuffled ideal sequence\n    Candidate candMaj = buildMajorityCandidate(N, L, T, rng);\n    best = candMaj;\n    bestInitialized = true;\n\n    // 2) Some random candidates from destination template\n    const int INIT_RANDOM = 50;\n    for (int i = 0; i < INIT_RANDOM; ++i) {\n        Candidate c = buildRandomCandidateFromTemplate(destTemplate, N, L, T, rng);\n        if (!bestInitialized || c.E < best.E) {\n            best = c;\n            bestInitialized = true;\n        }\n    }\n\n    // Precompute T-weighted distribution for fallback sampling in local search\n    vector<long long> Tprefix(N);\n    long long sumTw = 0;\n    for (int i = 0; i < N; ++i) {\n        sumTw += (long long)T[i] + 1;\n        Tprefix[i] = sumTw;\n    }\n\n    // Local search: deficits and positive-deficit distribution\n    vector<int> deficit(N);\n    for (int i = 0; i < N; ++i) {\n        deficit[i] = (int)(T[i] - best.t[i]);\n    }\n\n    vector<int> posIndices;\n    vector<long long> posPrefix;\n    long long sumPos = 0;\n\n    auto updatePosDist = [&]() {\n        posIndices.clear();\n        posPrefix.clear();\n        sumPos = 0;\n        for (int i = 0; i < N; ++i) {\n            if (deficit[i] > 0) {\n                posIndices.push_back(i);\n                sumPos += deficit[i];\n                posPrefix.push_back(sumPos);\n            }\n        }\n    };\n    updatePosDist();\n\n    const int LOCAL_ITER_MAX = 260;\n    for (int iter = 0; iter < LOCAL_ITER_MAX; ++iter) {\n        if (iter % 8 == 0) {\n            auto now = chrono::steady_clock::now();\n            long long elapsed = chrono::duration_cast<chrono::milliseconds>(now - startTime).count();\n            if (elapsed > TIME_LIMIT_MS) break;\n        }\n\n        Candidate cand = best;  // copy\n\n        int numMut = 1;\n        if (iter > 80)  numMut = 2;\n        if (iter > 160) numMut = 3;\n\n        for (int k = 0; k < numMut; ++k) {\n            int idx = (int)(rng() % N);\n            mutateNode(idx, cand, N, T, deficit, posIndices, posPrefix, sumPos,\n                       Tprefix, sumTw, rng);\n        }\n\n        evalCandidate(cand, N, L, T);\n\n        if (cand.E < best.E) {\n            best = cand;\n            for (int i = 0; i < N; ++i) {\n                deficit[i] = (int)(T[i] - best.t[i]);\n            }\n            updatePosDist();\n        }\n    }\n\n    // Output best found a_i, b_i\n    for (int i = 0; i < N; ++i) {\n        int ai = best.a[i];\n        int bi = best.b[i];\n        if (ai < 0) ai = 0;\n        if (ai >= N) ai = N - 1;\n        if (bi < 0) bi = 0;\n        if (bi >= N) bi = N - 1;\n        cout << ai << ' ' << bi << '\\n';\n    }\n\n    return 0;\n}","ahc045":"#include <bits/stdc++.h>\nusing namespace std;\n\n// Compute Hilbert order of (x, y) for given number of bits.\n// x, y must be in [0, 2^pow).\nstatic uint64_t hilbert_order(int x, int y, int pow_bits) {\n    uint64_t res = 0;\n    for (int s = pow_bits - 1; s >= 0; --s) {\n        int rx = (x >> s) & 1;\n        int ry = (y >> s) & 1;\n        res <<= 2;\n        res |= (uint64_t)((rx * 3) ^ ry);\n        if (ry == 0) {\n            if (rx == 1) {\n                x = ((1 << pow_bits) - 1) - x;\n                y = ((1 << pow_bits) - 1) - y;\n            }\n            std::swap(x, y);\n        }\n    }\n    return res;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, Q, L, W;\n    if (!(cin >> N >> M >> Q >> L >> W)) {\n        return 0;\n    }\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    // Approximate coordinates by centers\n    vector<int> cx(N), cy(N);\n    for (int i = 0; i < N; ++i) {\n        cx[i] = (lx[i] + rx[i]) / 2;\n        cy[i] = (ly[i] + ry[i]) / 2;\n    }\n\n    // Compute Hilbert order keys\n    const int HILBERT_BITS = 15; // 2^15 = 32768 > 10000\n    vector<pair<uint64_t,int>> ord(N);\n    for (int i = 0; i < N; ++i) {\n        uint64_t h = hilbert_order(cx[i], cy[i], HILBERT_BITS);\n        ord[i] = {h, i};\n    }\n    sort(ord.begin(), ord.end());\n\n    // Reorder group sizes: sort sizes descending to assign larger segments first.\n    vector<pair<int,int>> sizes; // {size, original_index}\n    sizes.reserve(M);\n    for (int i = 0; i < M; ++i) {\n        sizes.emplace_back(G[i], i);\n    }\n    sort(sizes.begin(), sizes.end(), [](const auto& a, const auto& b) {\n        // larger size first\n        if (a.first != b.first) return a.first > b.first;\n        return a.second < b.second;\n    });\n\n    // Assign cities along Hilbert order to groups according to sorted sizes.\n    vector<vector<int>> groups(M);\n    int pos = 0;\n    for (auto [sz, orig_idx] : sizes) {\n        groups[orig_idx].reserve(sz);\n        for (int k = 0; k < sz; ++k) {\n            groups[orig_idx].push_back(ord[pos++].second);\n        }\n    }\n    // Sanity: we should have used all cities exactly once.\n    // (We trust input constraints: sum G[i] = N.)\n\n    // Distance function using approximate centers, squared distance\n    auto dist2 = [&](int i, int j) -> int {\n        long dx = (long)cx[i] - (long)cx[j];\n        long dy = (long)cy[i] - (long)cy[j];\n        long v = dx * dx + dy * dy;\n        if (v > INT_MAX) v = INT_MAX; // very safe guard, shouldn't happen\n        return (int)v;\n    };\n\n    // Build approximate MST for each group with Prim's algorithm\n    vector<vector<pair<int,int>>> group_edges(M);\n    for (int g = 0; g < M; ++g) {\n        const auto &nodes = groups[g];\n        int m = (int)nodes.size();\n        if (m <= 1) {\n            continue; // no edges needed\n        }\n        vector<int> best(m, INT_MAX);\n        vector<int> parent(m, -1);\n        vector<char> used(m, 0);\n\n        // Start from node 0 in this group's index space\n        used[0] = 1;\n        for (int j = 1; j < m; ++j) {\n            int d = dist2(nodes[0], nodes[j]);\n            best[j] = d;\n            parent[j] = 0;\n        }\n\n        group_edges[g].reserve(m - 1);\n        for (int it = 1; it < m; ++it) {\n            int t = -1;\n            int bd = INT_MAX;\n            for (int i = 0; i < m; ++i) {\n                if (!used[i] && best[i] < bd) {\n                    bd = best[i];\n                    t = i;\n                }\n            }\n            if (t == -1) {\n                // Should not happen, but in case of numerical issues,\n                // connect any remaining node in a simple way.\n                for (int i = 0; i < m; ++i) {\n                    if (!used[i]) {\n                        t = i;\n                        parent[i] = 0;\n                        break;\n                    }\n                }\n            }\n            used[t] = 1;\n            // Add edge between nodes[t] and parent[t]\n            if (parent[t] != -1) {\n                group_edges[g].push_back({nodes[t], nodes[parent[t]]});\n            } else {\n                // This only happens for the initial root; we skip adding an edge.\n            }\n\n            // Update distances\n            for (int i = 0; i < m; ++i) {\n                if (!used[i]) {\n                    int d = dist2(nodes[t], nodes[i]);\n                    if (d < best[i]) {\n                        best[i] = d;\n                        parent[i] = t;\n                    }\n                }\n            }\n        }\n    }\n\n    // Output: no queries, directly final answer\n    cout << \"!\\n\";\n    for (int g = 0; g < M; ++g) {\n        const auto &nodes = groups[g];\n        int m = (int)nodes.size();\n        // First line: cities in this group\n        for (int i = 0; i < m; ++i) {\n            if (i) cout << ' ';\n            cout << nodes[i];\n        }\n        cout << '\\n';\n        // Then exactly (G[g]-1) edges\n        const auto &edges = group_edges[g];\n        // We expect edges.size() == max(0, m-1)\n        for (auto &e : edges) {\n            cout << e.first << ' ' << e.second << '\\n';\n        }\n    }\n\n    return 0;\n}","ahc046":"#include <bits/stdc++.h>\nusing namespace std;\n\n// Directions: Up, Down, Left, Right\nconst int DX[4] = {-1, 1, 0, 0};\nconst int DY[4] = {0, 0, -1, 1};\nconst char DCH[4] = {'U', 'D', 'L', 'R'};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M;\n    if (!(cin >> N >> M)) return 0;\n\n    vector<pair<int,int>> points(M);\n    for (int k = 0; k < M; ++k) {\n        cin >> points[k].first >> points[k].second;\n    }\n\n    vector<char> actions; actions.reserve(2 * N * M);\n    vector<char> dirs;    dirs.reserve(2 * N * M);\n\n    int totalCells = N * N;\n\n    // BFS for each segment from points[k-1] to points[k]\n    for (int k = 1; k < M; ++k) {\n        int sx = points[k-1].first;\n        int sy = points[k-1].second;\n        int gx = points[k].first;\n        int gy = points[k].second;\n\n        int sidx = sx * N + sy;\n        int gidx = gx * N + gy;\n\n        // BFS arrays\n        static int dist[400];\n        static int prev_idx[400];\n        static char prev_action[400];\n        static char prev_dir[400];\n\n        const int INF = 1e9;\n        for (int i = 0; i < totalCells; ++i) {\n            dist[i] = INF;\n        }\n\n        queue<int> q;\n        dist[sidx] = 0;\n        prev_idx[sidx] = -1;\n        q.push(sidx);\n\n        while (!q.empty()) {\n            int v = q.front(); q.pop();\n            if (v == gidx) break;\n\n            int x = v / N;\n            int y = v % N;\n\n            for (int d = 0; d < 4; ++d) {\n                // Move\n                {\n                    int nx = x + DX[d];\n                    int ny = y + DY[d];\n                    if (0 <= nx && nx < N && 0 <= ny && ny < N) {\n                        int to = nx * N + ny;\n                        if (dist[to] == INF) {\n                            dist[to] = dist[v] + 1;\n                            prev_idx[to] = v;\n                            prev_action[to] = 'M';\n                            prev_dir[to] = DCH[d];\n                            q.push(to);\n                        }\n                    }\n                }\n                // Slide to border (no internal blocks)\n                {\n                    int nx = x, ny = y;\n                    if (d == 0) nx = 0;          // Up\n                    else if (d == 1) nx = N - 1; // Down\n                    else if (d == 2) ny = 0;     // Left\n                    else if (d == 3) ny = N - 1; // Right\n\n                    int to = nx * N + ny;\n                    if (to != v && dist[to] == INF) {\n                        dist[to] = dist[v] + 1;\n                        prev_idx[to] = v;\n                        prev_action[to] = 'S';\n                        prev_dir[to] = DCH[d];\n                        q.push(to);\n                    }\n                }\n            }\n        }\n\n        // Reconstruct path from gidx back to sidx\n        vector<char> seg_actions;\n        vector<char> seg_dirs;\n        int cur = gidx;\n        while (cur != sidx) {\n            seg_actions.push_back(prev_action[cur]);\n            seg_dirs.push_back(prev_dir[cur]);\n            cur = prev_idx[cur];\n        }\n        // Reverse to get correct order\n        for (int i = (int)seg_actions.size() - 1; i >= 0; --i) {\n            actions.push_back(seg_actions[i]);\n            dirs.push_back(seg_dirs[i]);\n        }\n    }\n\n    // Output\n    int T = (int)actions.size();\n    // We are guaranteed T <= 2*N*M from argument (<=1482 when no blocks)\n    for (int t = 0; t < T; ++t) {\n        cout << actions[t] << ' ' << dirs[t] << '\\n';\n    }\n\n    return 0;\n}"},"2":{"ahc001":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Rect {\n    int a, b, c, d; // [a,c) x [b,d)\n};\n\nint n;\nvector<int> xs, ys;\nvector<long long> rs;\n\n// satisfaction for s <= r\ninline double satisfaction(long long s, long long r) {\n    if (s <= 0) return 0.0;\n    double q = (double)s / (double)r; // q in (0,1]\n    double t = 1.0 - q;\n    return 1.0 - t * t; // = 2q - q^2\n}\n\n// positive-area overlap?\ninline bool overlap(const Rect &x, const Rect &y) {\n    return (x.a < y.c && y.a < x.c && x.b < y.d && y.b < x.d);\n}\n\n// Greedy growth for a given order. Fills rect and area, returns total score.\ndouble run_order(const vector<int> &order, vector<Rect> &rect, vector<long long> &area) {\n    rect.assign(n, Rect());\n    area.assign(n, 1);\n\n    // initialize as 1x1 at seeds\n    for (int i = 0; i < n; ++i) {\n        rect[i].a = xs[i];\n        rect[i].c = xs[i] + 1;\n        rect[i].b = ys[i];\n        rect[i].d = ys[i] + 1;\n        area[i] = 1;\n    }\n\n    for (int pos = 0; pos < n; ++pos) {\n        int i = order[pos];\n        long long target = rs[i];\n        if (target <= 1) continue;\n\n        while (area[i] < target) {\n            Rect &cur = rect[i];\n            int w = cur.c - cur.a;\n            int h = cur.d - cur.b;\n            if (w <= 0 || h <= 0) break;\n            long long remaining = target - area[i];\n\n            int bestDir = -1;\n            int bestL = 0;\n            long long bestDelta = 0;\n\n            // 0: up (increase d)\n            if (cur.d < 10000 && remaining >= w) {\n                long long L_area = remaining / w;\n                if (L_area > 0) {\n                    int limit = 10000 - cur.d;\n                    if (limit > 0) {\n                        for (int j = 0; j < n; ++j) {\n                            if (j == i) continue;\n                            const Rect &s = rect[j];\n                            // x-overlap?\n                            if (s.a >= cur.c || s.c <= cur.a) continue;\n                            if (cur.d >= s.d) continue; // s below or touching\n                            if (s.b <= cur.d) {\n                                // s.b <= d < s.d, any extension hits s\n                                limit = 0;\n                                break;\n                            } else {\n                                int cand = s.b - cur.d;\n                                if (cand < limit) {\n                                    limit = cand;\n                                    if (limit <= 0) {\n                                        limit = 0;\n                                        break;\n                                    }\n                                }\n                            }\n                        }\n                        if (limit > 0) {\n                            int L = (int)min<long long>(limit, L_area);\n                            if (L > 0) {\n                                long long delta = 1LL * L * w;\n                                if (delta > bestDelta) {\n                                    bestDelta = delta;\n                                    bestDir = 0;\n                                    bestL = L;\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n\n            // 1: down (decrease b)\n            if (cur.b > 0 && remaining >= w) {\n                long long L_area = remaining / w;\n                if (L_area > 0) {\n                    int limit = cur.b;\n                    if (limit > 0) {\n                        for (int j = 0; j < n; ++j) {\n                            if (j == i) continue;\n                            const Rect &s = rect[j];\n                            // x-overlap?\n                            if (s.a >= cur.c || s.c <= cur.a) continue;\n                            if (s.b >= cur.b) continue; // s above or touching\n                            if (s.d > cur.b) {\n                                // s.b < b < s.d\n                                limit = 0;\n                                break;\n                            } else {\n                                int cand = cur.b - s.d;\n                                if (cand < limit) {\n                                    limit = cand;\n                                    if (limit <= 0) {\n                                        limit = 0;\n                                        break;\n                                    }\n                                }\n                            }\n                        }\n                        if (limit > 0) {\n                            int L = (int)min<long long>(limit, L_area);\n                            if (L > 0) {\n                                long long delta = 1LL * L * w;\n                                if (delta > bestDelta) {\n                                    bestDelta = delta;\n                                    bestDir = 1;\n                                    bestL = L;\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n\n            // 2: left (decrease a)\n            if (cur.a > 0 && remaining >= h) {\n                long long L_area = remaining / h;\n                if (L_area > 0) {\n                    int limit = cur.a;\n                    if (limit > 0) {\n                        for (int j = 0; j < n; ++j) {\n                            if (j == i) continue;\n                            const Rect &s = rect[j];\n                            // y-overlap?\n                            if (s.d <= cur.b || cur.d <= s.b) continue;\n                            if (s.a >= cur.a) {\n                                // s to the right or touching\n                                continue;\n                            } else {\n                                if (s.c > cur.a) {\n                                    // s crosses x = cur.a\n                                    limit = 0;\n                                    break;\n                                } else {\n                                    int cand = cur.a - s.c;\n                                    if (cand < limit) {\n                                        limit = cand;\n                                        if (limit <= 0) {\n                                            limit = 0;\n                                            break;\n                                        }\n                                    }\n                                }\n                            }\n                        }\n                        if (limit > 0) {\n                            int L = (int)min<long long>(limit, L_area);\n                            if (L > 0) {\n                                long long delta = 1LL * L * h;\n                                if (delta > bestDelta) {\n                                    bestDelta = delta;\n                                    bestDir = 2;\n                                    bestL = L;\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n\n            // 3: right (increase c)\n            if (cur.c < 10000 && remaining >= h) {\n                long long L_area = remaining / h;\n                if (L_area > 0) {\n                    int limit = 10000 - cur.c;\n                    if (limit > 0) {\n                        for (int j = 0; j < n; ++j) {\n                            if (j == i) continue;\n                            const Rect &s = rect[j];\n                            // y-overlap?\n                            if (s.d <= cur.b || cur.d <= s.b) continue;\n                            if (cur.c >= s.c) {\n                                // s to the left or touching\n                                continue;\n                            } else {\n                                if (s.a <= cur.c) {\n                                    // s crosses x = cur.c\n                                    limit = 0;\n                                    break;\n                                } else {\n                                    int cand = s.a - cur.c;\n                                    if (cand < limit) {\n                                        limit = cand;\n                                        if (limit <= 0) {\n                                            limit = 0;\n                                            break;\n                                        }\n                                    }\n                                }\n                            }\n                        }\n                        if (limit > 0) {\n                            int L = (int)min<long long>(limit, L_area);\n                            if (L > 0) {\n                                long long delta = 1LL * L * h;\n                                if (delta > bestDelta) {\n                                    bestDelta = delta;\n                                    bestDir = 3;\n                                    bestL = L;\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n\n            if (bestDir == -1 || bestL <= 0 || bestDelta <= 0) break;\n\n            switch (bestDir) {\n                case 0: cur.d += bestL; break;\n                case 1: cur.b -= bestL; break;\n                case 2: cur.a -= bestL; break;\n                case 3: cur.c += bestL; break;\n            }\n            area[i] += bestDelta;\n        }\n    }\n\n    double score = 0.0;\n    for (int i = 0; i < n; ++i) {\n        score += satisfaction(area[i], rs[i]);\n    }\n    return score;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> n;\n    xs.resize(n);\n    ys.resize(n);\n    rs.resize(n);\n    for (int i = 0; i < n; ++i) {\n        cin >> xs[i] >> ys[i] >> rs[i];\n    }\n\n    // Time management\n    const double TIME_LIMIT = 4.8;      // seconds (slightly below 5s)\n    const double ORDER_PHASE_END = 2.5; // use ~2.5s for random orders\n    const double SA_PHASE_END = 4.7;    // use until ~4.7s for SA\n\n    auto time_start = chrono::steady_clock::now();\n    auto elapsed = [&]() -> double {\n        return chrono::duration<double>(chrono::steady_clock::now() - time_start).count();\n    };\n\n    // RNG\n    uint64_t seed = chrono::steady_clock::now().time_since_epoch().count();\n    seed ^= (uint64_t)n << 32;\n    if (n > 0) {\n        seed ^= (uint64_t)xs[0] * 10007 + (uint64_t)ys[0] * 1000003;\n    }\n    std::mt19937_64 rng(seed);\n\n    vector<int> base(n);\n    iota(base.begin(), base.end(), 0);\n\n    vector<Rect> rect, bestRect;\n    vector<long long> area, bestArea;\n    double bestScore = -1.0;\n\n    // Deterministic orders\n    auto try_order = [&](const vector<int> &order) {\n        double sc = run_order(order, rect, area);\n        if (sc > bestScore) {\n            bestScore = sc;\n            bestRect = rect;\n            bestArea = area;\n        }\n    };\n\n    // 1) increasing r\n    {\n        vector<int> ord = base;\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            if (rs[a] != rs[b]) return rs[a] < rs[b];\n            return a < b;\n        });\n        try_order(ord);\n    }\n    // 2) decreasing r\n    {\n        vector<int> ord = base;\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            if (rs[a] != rs[b]) return rs[a] > rs[b];\n            return a < b;\n        });\n        try_order(ord);\n    }\n    // 3) increasing x\n    {\n        vector<int> ord = base;\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            if (xs[a] != xs[b]) return xs[a] < xs[b];\n            return a < b;\n        });\n        try_order(ord);\n    }\n    // 4) increasing y\n    {\n        vector<int> ord = base;\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            if (ys[a] != ys[b]) return ys[a] < ys[b];\n            return a < b;\n        });\n        try_order(ord);\n    }\n\n    // Random permutations until ORDER_PHASE_END\n    {\n        vector<int> ord = base;\n        while (elapsed() < ORDER_PHASE_END) {\n            shuffle(ord.begin(), ord.end(), rng);\n            try_order(ord);\n        }\n    }\n\n    // Local search (simulated annealing) starting from bestRect\n    // Prepare current state\n    vector<Rect> curRect = bestRect;\n    vector<long long> curArea = bestArea;\n    vector<double> curP(n);\n    double curScore = 0.0;\n    for (int i = 0; i < n; ++i) {\n        curP[i] = satisfaction(curArea[i], rs[i]);\n        curScore += curP[i];\n    }\n    bestScore = curScore;\n    bestRect = curRect; // ensure consistency\n\n    double sa_start_time = elapsed();\n    double sa_total = SA_PHASE_END - sa_start_time;\n    if (sa_total > 0.0) {\n        uniform_int_distribution<int> distRect(0, n - 1);\n        uniform_int_distribution<int> distOp(0, 7);\n        uniform_real_distribution<double> dist01(0.0, 1.0);\n\n        const double T0 = 0.1;\n        const double T1 = 0.01;\n\n        while (true) {\n            double tnow = elapsed();\n            if (tnow >= SA_PHASE_END) break;\n            double sa_elapsed = tnow - sa_start_time;\n            double progress = sa_elapsed / sa_total;\n            if (progress > 1.0) progress = 1.0;\n            // geometric cooling\n            double T = T0 * pow(T1 / T0, progress);\n            if (T < 1e-4) T = 1e-4;\n\n            int i = distRect(rng);\n            int op = distOp(rng);\n\n            Rect old = curRect[i];\n            Rect cand = old;\n            long long oldArea = curArea[i];\n            double oldPi = curP[i];\n            long long newArea = oldArea;\n            bool changed = false;\n            bool ok = true;\n\n            int w = old.c - old.a;\n            int h = old.d - old.b;\n\n            switch (op) {\n                case 0: { // expand left\n                    if (old.a == 0) { ok = false; break; }\n                    if (oldArea + h > rs[i]) { ok = false; break; }\n                    cand.a = old.a - 1;\n                    newArea = oldArea + h;\n                    // check overlap\n                    for (int j = 0; j < n; ++j) if (j != i) {\n                        if (overlap(cand, curRect[j])) { ok = false; break; }\n                    }\n                    if (!ok) break;\n                    changed = true;\n                    break;\n                }\n                case 1: { // expand right\n                    if (old.c == 10000) { ok = false; break; }\n                    if (oldArea + h > rs[i]) { ok = false; break; }\n                    cand.c = old.c + 1;\n                    newArea = oldArea + h;\n                    for (int j = 0; j < n; ++j) if (j != i) {\n                        if (overlap(cand, curRect[j])) { ok = false; break; }\n                    }\n                    if (!ok) break;\n                    changed = true;\n                    break;\n                }\n                case 2: { // expand down\n                    if (old.b == 0) { ok = false; break; }\n                    if (oldArea + w > rs[i]) { ok = false; break; }\n                    cand.b = old.b - 1;\n                    newArea = oldArea + w;\n                    for (int j = 0; j < n; ++j) if (j != i) {\n                        if (overlap(cand, curRect[j])) { ok = false; break; }\n                    }\n                    if (!ok) break;\n                    changed = true;\n                    break;\n                }\n                case 3: { // expand up\n                    if (old.d == 10000) { ok = false; break; }\n                    if (oldArea + w > rs[i]) { ok = false; break; }\n                    cand.d = old.d + 1;\n                    newArea = oldArea + w;\n                    for (int j = 0; j < n; ++j) if (j != i) {\n                        if (overlap(cand, curRect[j])) { ok = false; break; }\n                    }\n                    if (!ok) break;\n                    changed = true;\n                    break;\n                }\n                case 4: { // shrink left\n                    if (w <= 1) { ok = false; break; }\n                    // seed must stay inside\n                    if (xs[i] == old.a) { ok = false; break; }\n                    cand.a = old.a + 1;\n                    newArea = oldArea - h;\n                    changed = true;\n                    break;\n                }\n                case 5: { // shrink right\n                    if (w <= 1) { ok = false; break; }\n                    if (xs[i] == old.c - 1) { ok = false; break; }\n                    cand.c = old.c - 1;\n                    newArea = oldArea - h;\n                    changed = true;\n                    break;\n                }\n                case 6: { // shrink down\n                    if (h <= 1) { ok = false; break; }\n                    if (ys[i] == old.b) { ok = false; break; }\n                    cand.b = old.b + 1;\n                    newArea = oldArea - w;\n                    changed = true;\n                    break;\n                }\n                case 7: { // shrink up\n                    if (h <= 1) { ok = false; break; }\n                    if (ys[i] == old.d - 1) { ok = false; break; }\n                    cand.d = old.d - 1;\n                    newArea = oldArea - w;\n                    changed = true;\n                    break;\n                }\n            }\n\n            if (!ok || !changed) continue;\n\n            // sanity: positive area\n            if (!(cand.a < cand.c && cand.b < cand.d)) continue;\n\n            double newPi = satisfaction(newArea, rs[i]);\n            double delta = newPi - oldPi;\n            double newScore = curScore + delta;\n\n            if (delta >= 0.0) {\n                // always accept improvement\n                curRect[i] = cand;\n                curArea[i] = newArea;\n                curP[i] = newPi;\n                curScore = newScore;\n                if (curScore > bestScore) {\n                    bestScore = curScore;\n                    bestRect = curRect;\n                }\n            } else {\n                double prob = exp(delta / T);\n                double r = dist01(rng);\n                if (r < prob) {\n                    // accept worse move\n                    curRect[i] = cand;\n                    curArea[i] = newArea;\n                    curP[i] = newPi;\n                    curScore = newScore;\n                    if (curScore > bestScore) {\n                        bestScore = curScore;\n                        bestRect = curRect;\n                    }\n                }\n                // else reject, keep old state\n            }\n        }\n    }\n\n    // Output best layout\n    for (int i = 0; i < n; ++i) {\n        cout << bestRect[i].a << ' ' << bestRect[i].b << ' '\n             << bestRect[i].c << ' ' << bestRect[i].d << '\\n';\n    }\n\n    return 0;\n}","ahc002":"#include <bits/stdc++.h>\nusing namespace std;\n\n// Fast xorshift RNG\nstruct XorShift64 {\n    uint64_t x;\n    XorShift64() {\n        uint64_t seed = chrono::steady_clock::now().time_since_epoch().count();\n        x = seed ^ (seed << 13);\n    }\n    inline uint64_t next() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return x;\n    }\n    inline uint32_t next_u32() {\n        return static_cast<uint32_t>(next());\n    }\n};\n\nstruct Path {\n    int score;\n    vector<int> seq;\n};\n\n// Globals for simplicity (grid is fixed 50x50)\nconstexpr int H = 50;\nconstexpr int W = 50;\nconstexpr int N = H * W;\nconstexpr int MAX_TILES = 2500;\n\nint tileID[N];                 // tile index for each cell\nint valCell[N];                // score of each cell\nint nei[N][4];                 // neighbors (cell indices)\nint neiCnt[N];                 // number of neighbors for each cell\nint visitedTime[MAX_TILES];    // last iteration stamp when tile was visited\nint startCell;                 // starting cell index\nint maxTileId;                 // max tile id in input\n\nint iterStamp = 0;\nXorShift64 rng;\n\n// Check if tile t is visited in current walk\ninline bool isVisitedTile(int t) {\n    return visitedTime[t] == iterStamp;\n}\n\n// Build one path using a given mode (0,1,2)\nPath build_path(int mode) {\n    ++iterStamp;\n    Path path;\n    path.seq.reserve(N);\n    path.score = 0;\n\n    int cur = startCell;\n    path.seq.push_back(cur);\n    path.score += valCell[cur];\n    visitedTime[tileID[cur]] = iterStamp;\n\n    while (true) {\n        int cand[4];\n        int candCount = 0;\n\n        // Collect candidate neighbors: adjacent cells whose tile is not yet visited\n        for (int k = 0; k < neiCnt[cur]; ++k) {\n            int v = nei[cur][k];\n            int t = tileID[v];\n            if (isVisitedTile(t)) continue; // tile already visited\n            cand[candCount++] = v;\n        }\n\n        if (candCount == 0) break;\n\n        int deg[4];\n\n        // Compute \"forward degree\" for each candidate: how many moves are possible after stepping there\n        for (int i = 0; i < candCount; ++i) {\n            int v = cand[i];\n            int tv = tileID[v];\n            int d = 0;\n            for (int k = 0; k < neiCnt[v]; ++k) {\n                int w = nei[v][k];\n                int tw = tileID[w];\n                if (tw == tv) continue;                 // same tile, won't be allowed after step\n                if (isVisitedTile(tw)) continue;        // tile already used\n                ++d;\n            }\n            deg[i] = d;\n        }\n\n        int chosenIdx = 0;\n\n        if (mode == 0) {\n            // Mode 0: balanced\n            // Prefer class 0 (deg>=2), then 1 (deg==1), then 2 (deg==0)\n            // Within class: smaller deg first, then higher value\n            int bestClass = 3;\n            int bestDeg = 1000;\n            int bestVal = -1;\n            for (int i = 0; i < candCount; ++i) {\n                int d = deg[i];\n                int cls = (d >= 2 ? 0 : (d == 1 ? 1 : 2));\n                int v = cand[i];\n                int pv = valCell[v];\n                bool better = false;\n\n                if (cls < bestClass) {\n                    better = true;\n                } else if (cls == bestClass) {\n                    if (d < bestDeg) {\n                        better = true;\n                    } else if (d == bestDeg) {\n                        if (pv > bestVal) {\n                            better = true;\n                        } else if (pv == bestVal) {\n                            // random tie-break\n                            if (rng.next_u32() & 1u) better = true;\n                        }\n                    }\n                }\n\n                if (better) {\n                    bestClass = cls;\n                    bestDeg = d;\n                    bestVal = pv;\n                    chosenIdx = i;\n                }\n            }\n        } else if (mode == 1) {\n            // Mode 1: pure Warnsdorff (minimize deg), tie by high value\n            int bestDeg = 1000;\n            int bestVal = -1;\n            for (int i = 0; i < candCount; ++i) {\n                int d = deg[i];\n                int v = cand[i];\n                int pv = valCell[v];\n                bool better = false;\n\n                if (d < bestDeg) {\n                    better = true;\n                } else if (d == bestDeg) {\n                    if (pv > bestVal) {\n                        better = true;\n                    } else if (pv == bestVal) {\n                        if (rng.next_u32() & 1u) better = true;\n                    }\n                }\n\n                if (better) {\n                    bestDeg = d;\n                    bestVal = pv;\n                    chosenIdx = i;\n                }\n            }\n        } else {\n            // Mode 2: value-first, tie by larger deg\n            int bestVal = -1;\n            int bestDeg = -1;\n            for (int i = 0; i < candCount; ++i) {\n                int v = cand[i];\n                int pv = valCell[v];\n                int d = deg[i];\n                bool better = false;\n\n                if (pv > bestVal) {\n                    better = true;\n                } else if (pv == bestVal) {\n                    if (d > bestDeg) {\n                        better = true;\n                    } else if (d == bestDeg) {\n                        if (rng.next_u32() & 1u) better = true;\n                    }\n                }\n\n                if (better) {\n                    bestVal = pv;\n                    bestDeg = d;\n                    chosenIdx = i;\n                }\n            }\n        }\n\n        // Small random exploration: 5% chance choose totally random candidate\n        if (candCount > 1 && (rng.next_u32() % 20u == 0u)) {\n            chosenIdx = rng.next_u32() % candCount;\n        }\n\n        int nextCell = cand[chosenIdx];\n        cur = nextCell;\n        path.seq.push_back(cur);\n        path.score += valCell[cur];\n        visitedTime[tileID[cur]] = iterStamp;\n    }\n\n    return path;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int si, sj;\n    if (!(cin >> si >> sj)) {\n        return 0;\n    }\n\n    maxTileId = -1;\n\n    // Read tiles\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            int t;\n            cin >> t;\n            int idx = i * W + j;\n            tileID[idx] = t;\n            if (t > maxTileId) maxTileId = t;\n        }\n    }\n\n    // Read cell values\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            int p;\n            cin >> p;\n            int idx = i * W + j;\n            valCell[idx] = p;\n        }\n    }\n\n    // Precompute neighbors on the grid (4-neighborhood)\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            int idx = i * W + j;\n            int cnt = 0;\n            if (i > 0)    nei[idx][cnt++] = (i - 1) * W + j;\n            if (i + 1 < H) nei[idx][cnt++] = (i + 1) * W + j;\n            if (j > 0)    nei[idx][cnt++] = i * W + (j - 1);\n            if (j + 1 < W) nei[idx][cnt++] = i * W + (j + 1);\n            neiCnt[idx] = cnt;\n        }\n    }\n\n    // Initialize visitedTime\n    for (int i = 0; i <= maxTileId; ++i) visitedTime[i] = 0;\n\n    startCell = si * W + sj;\n\n    auto startTime = chrono::steady_clock::now();\n    const double TIME_LIMIT = 1.9; // seconds\n\n    Path best;\n    best.score = -1;\n\n    int iterations = 0;\n    while (true) {\n        int mode = static_cast<int>(rng.next_u32() % 3u); // 0,1,2\n        Path cur = build_path(mode);\n\n        if (cur.score > best.score ||\n            (cur.score == best.score && cur.seq.size() > best.seq.size())) {\n            best = std::move(cur);\n        }\n\n        ++iterations;\n        if ((iterations & 7) == 0) { // check time every 8 iterations\n            auto now = chrono::steady_clock::now();\n            double elapsed = chrono::duration<double>(now - startTime).count();\n            if (elapsed > TIME_LIMIT) break;\n        }\n    }\n\n    // Convert best.seq (cells) into moves string\n    string ans;\n    ans.reserve(best.seq.size());\n    for (size_t k = 1; k < best.seq.size(); ++k) {\n        int prev = best.seq[k - 1];\n        int cur = best.seq[k];\n        int pi = prev / W, pj = prev % W;\n        int ci = cur / W, cj = cur % W;\n        if (ci == pi) {\n            if (cj == pj + 1) ans.push_back('R');\n            else if (cj == pj - 1) ans.push_back('L');\n        } else if (cj == pj) {\n            if (ci == pi + 1) ans.push_back('D');\n            else if (ci == pi - 1) ans.push_back('U');\n        }\n        // Since we only move along neighbors, no other case should occur.\n    }\n\n    cout << ans << '\\n';\n    return 0;\n}","ahc003":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const int H = 30;\nstatic const int W = 30;\nstatic const int N = H * W;\nstatic const int EH = H * (W - 1);\nstatic const int EV = (H - 1) * W;\nstatic const int E = EH + EV;\nstatic const double INF = 1e100;\n\n// Edge indices for canonical orientations\nint h_id[H][W - 1]; // horizontal: (i,j)-(i,j+1) -> h_id[i][j]\nint v_id[H - 1][W]; // vertical:   (i,j)-(i+1,j) -> v_id[i][j]\n\n// Adjacency: for each vertex, (to, edge_id)\nvector<pair<int,int>> adj[N];\n\n// Edge weights (our estimates) and their randomized version per query\nvector<double> w(E), eff_w(E);\n\n// Dijkstra buffers\ndouble dist_arr[N];\nint prev_v_arr[N];\nint prev_e_arr[N];\n\ninline int vid(int i, int j) {\n    return i * W + j;\n}\n\n// RNG for jitter\nmt19937_64 rng(71236782123ULL);\n\ninline double rand01() {\n    return std::generate_canonical<double, 53>(rng); // [0,1)\n}\n\n// Dijkstra using eff_w, returns path as \"UDLR\"\nstring dijkstra_path(int si, int sj, int ti, int tj, int query_id) {\n    // Jitter decreases over time\n    const double JITTER0 = 0.03;\n    double jitter = JITTER0 * max(0.0, 1.0 - (double)query_id / 800.0);\n    if (jitter < 0.0) jitter = 0.0;\n\n    // Build jittered weights\n    for (int e = 0; e < E; ++e) {\n        double u = 2.0 * rand01() - 1.0; // [-1,1)\n        double factor = 1.0 + jitter * u;\n        if (factor < 0.5) factor = 0.5; // safety\n        eff_w[e] = w[e] * factor;\n        if (eff_w[e] < 1.0) eff_w[e] = 1.0; // strictly positive\n    }\n\n    int s = vid(si, sj);\n    int t = vid(ti, tj);\n\n    // Initialize Dijkstra\n    for (int i = 0; i < N; ++i) {\n        dist_arr[i] = INF;\n        prev_v_arr[i] = -1;\n        prev_e_arr[i] = -1;\n    }\n    dist_arr[s] = 0.0;\n\n    using P = pair<double,int>;\n    priority_queue<P, vector<P>, greater<P>> pq;\n    pq.emplace(0.0, s);\n\n    while (!pq.empty()) {\n        auto [d, u] = pq.top();\n        pq.pop();\n        if (d != dist_arr[u]) continue;\n        if (u == t) break;\n        for (auto &pe : adj[u]) {\n            int v = pe.first;\n            int eid = pe.second;\n            double nd = d + eff_w[eid];\n            if (nd < dist_arr[v]) {\n                dist_arr[v] = nd;\n                prev_v_arr[v] = u;\n                prev_e_arr[v] = eid;\n                pq.emplace(nd, v);\n            }\n        }\n    }\n\n    // Reconstruct path\n    string rev;\n    int v = t;\n    while (v != s) {\n        int u = prev_v_arr[v];\n        if (u == -1) {\n            // Fallback: Manhattan path if something goes wrong\n            rev.clear();\n            int ci = si, cj = sj;\n            while (ci < ti) { rev.push_back('D'); ++ci; }\n            while (ci > ti) { rev.push_back('U'); --ci; }\n            while (cj < tj) { rev.push_back('R'); ++cj; }\n            while (cj > tj) { rev.push_back('L'); --cj; }\n            break;\n        }\n        int ui = u / W, uj = u % W;\n        int vi = v / W, vj = v % W;\n        if (vi == ui) {\n            if (vj == uj + 1) rev.push_back('R');\n            else if (vj == uj - 1) rev.push_back('L');\n        } else if (vj == uj) {\n            if (vi == ui + 1) rev.push_back('D');\n            else if (vi == ui - 1) rev.push_back('U');\n        }\n        v = u;\n    }\n    reverse(rev.begin(), rev.end());\n    return rev;\n}\n\n// Convert move string into list of edge IDs\nvoid path_to_edges(int si, int sj, const string &path, vector<int> &edges) {\n    edges.clear();\n    edges.reserve(path.size());\n    int i = si, j = sj;\n    for (char c : path) {\n        int eid = -1;\n        if (c == 'U') {\n            int ni = i - 1;\n            eid = v_id[ni][j]; // edge between (ni,j) and (ni+1,j)\n            i = ni;\n        } else if (c == 'D') {\n            eid = v_id[i][j]; // edge between (i,j) and (i+1,j)\n            i = i + 1;\n        } else if (c == 'L') {\n            int nj = j - 1;\n            eid = h_id[i][nj]; // edge between (i,nj) and (i,nj+1)\n            j = nj;\n        } else if (c == 'R') {\n            eid = h_id[i][j]; // edge between (i,j) and (i,j+1)\n            j = j + 1;\n        }\n        edges.push_back(eid);\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // Build graph and edge indexing\n    int eid = 0;\n    // Horizontal edges\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W - 1; ++j) {\n            h_id[i][j] = eid;\n            int u = vid(i, j);\n            int v = vid(i, j + 1);\n            adj[u].emplace_back(v, eid);\n            adj[v].emplace_back(u, eid);\n            ++eid;\n        }\n    }\n    // Vertical edges\n    for (int i = 0; i < H - 1; ++i) {\n        for (int j = 0; j < W; ++j) {\n            v_id[i][j] = eid;\n            int u = vid(i, j);\n            int v = vid(i + 1, j);\n            adj[u].emplace_back(v, eid);\n            adj[v].emplace_back(u, eid);\n            ++eid;\n        }\n    }\n\n    // Initialize weights\n    w.assign(E, 5000.0);\n    eff_w.assign(E, 5000.0);\n\n    vector<int> edges;\n    const double ETA = 0.5; // learning rate multiplier\n\n    for (int q = 0; q < 1000; ++q) {\n        int si, sj, ti, tj;\n        if (!(cin >> si >> sj >> ti >> tj)) {\n            return 0; // EOF / error\n        }\n\n        // Compute path\n        string path = dijkstra_path(si, sj, ti, tj, q);\n\n        // Output and flush\n        cout << path << '\\n';\n        cout.flush();\n\n        long long y_ll;\n        if (!(cin >> y_ll)) {\n            return 0; // EOF / error\n        }\n        double y = (double)y_ll;\n\n        // Update weights based on feedback\n        path_to_edges(si, sj, path, edges);\n        int L = (int)edges.size();\n        if (L == 0) continue; // shouldn't happen (distance >= 10)\n\n        double pred = 0.0;\n        for (int e : edges) {\n            pred += w[e];\n        }\n        double error = y - pred;\n\n        double lr = ETA / (double)L;\n        for (int e : edges) {\n            w[e] += lr * error;\n            if (w[e] < 1000.0) w[e] = 1000.0;\n            else if (w[e] > 9000.0) w[e] = 9000.0;\n        }\n    }\n\n    return 0;\n}","ahc004":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const int MAX_N = 20;\nstatic const int MAX_M = 800;\nstatic const int ALPHA = 8;\nstatic const int MAXW = (MAX_M + 63) / 64;\n\nint N, M;\nint WORDS; // actual number of 64-bit words used\nvector<string> patterns;\n\n// bitset over up to MAX_M bits\nstruct BS {\n    uint64_t w[MAXW];\n};\n\n// bitset helpers\ninline void bs_clear(BS &b) {\n    // clear all words; cost is tiny (<= 13 words)\n    memset(b.w, 0, sizeof(b.w));\n}\ninline void bs_or_inplace(BS &a, const BS &b) {\n    for (int i = 0; i < WORDS; ++i) a.w[i] |= b.w[i];\n}\ninline void bs_xor(BS &res, const BS &a, const BS &b) {\n    for (int i = 0; i < WORDS; ++i) res.w[i] = a.w[i] ^ b.w[i];\n}\ninline void bs_or(BS &res, const BS &a, const BS &b) {\n    for (int i = 0; i < WORDS; ++i) res.w[i] = a.w[i] | b.w[i];\n}\ninline bool bs_test(const BS &b, int idx) {\n    return (b.w[idx >> 6] >> (idx & 63)) & 1ULL;\n}\ninline void bs_set(BS &b, int idx) {\n    b.w[idx >> 6] |= 1ULL << (idx & 63);\n}\ninline void bs_reset(BS &b, int idx) {\n    b.w[idx >> 6] &= ~(1ULL << (idx & 63));\n}\n\n// iterate over set bits of b, calling f(idx) for each\ntemplate <class F>\ninline void bs_for_each(const BS &b, F f) {\n    for (int w = 0; w < WORDS; ++w) {\n        uint64_t x = b.w[w];\n        while (x) {\n            int lsb = __builtin_ctzll(x);\n            int idx = (w << 6) + lsb;\n            if (idx >= M) return; // safety; bits >=M are never set\n            f(idx);\n            x &= x - 1; // clear lowest set bit\n        }\n    }\n}\n\n// Aho\u2013Corasick automaton\nstruct Node {\n    int next[ALPHA];\n    int link;\n    BS out; // bitset of patterns that end at this state (including via failure)\n    Node() {\n        fill(next, next + ALPHA, -1);\n        link = 0;\n        bs_clear(out);\n    }\n};\nvector<Node> ac;\n\n// grid\nchar grid[MAX_N][MAX_N];\n\n// row/col pattern presence\nBS row_bs[MAX_N], col_bs[MAX_N];\n\n// pattern coverage count across all rows+cols\nint pattern_cov_count[MAX_M];\nint current_c = 0;\n\n// RNG\nmt19937_64 rng;\n\ninline int ch_idx(char c) {\n    return c - 'A'; // 'A'..'H' -> 0..7\n}\n\nvoid build_automaton() {\n    ac.clear();\n    ac.emplace_back(); // root\n\n    // build trie and set pattern bits\n    for (int i = 0; i < M; ++i) {\n        const string &s = patterns[i];\n        int v = 0;\n        for (char ch : s) {\n            int c = ch_idx(ch);\n            if (ac[v].next[c] == -1) {\n                ac[v].next[c] = (int)ac.size();\n                ac.emplace_back();\n            }\n            v = ac[v].next[c];\n        }\n        bs_set(ac[v].out, i);\n    }\n\n    // build failure links\n    queue<int> q;\n\n    // initialize root transitions\n    for (int c = 0; c < ALPHA; ++c) {\n        int u = ac[0].next[c];\n        if (u != -1) {\n            ac[u].link = 0;\n            q.push(u);\n        } else {\n            ac[0].next[c] = 0;\n        }\n    }\n\n    while (!q.empty()) {\n        int v = q.front(); q.pop();\n        int link = ac[v].link;\n\n        // propagate pattern bits from failure link\n        bs_or_inplace(ac[v].out, ac[link].out);\n\n        for (int c = 0; c < ALPHA; ++c) {\n            int u = ac[v].next[c];\n            if (u != -1) {\n                ac[u].link = ac[link].next[c];\n                q.push(u);\n            } else {\n                ac[v].next[c] = ac[link].next[c];\n            }\n        }\n    }\n}\n\n// scan a line through AC, return bitset of patterns appearing\ninline BS scan_line(const char *s, int len) {\n    BS res;\n    bs_clear(res);\n    int v = 0;\n    for (int i = 0; i < len; ++i) {\n        int c = ch_idx(s[i]);\n        v = ac[v].next[c];\n        bs_or_inplace(res, ac[v].out);\n    }\n    return res;\n}\n\n// recompute one row r and update global counts\nvoid recalc_row(int r) {\n    char line[2 * MAX_N];\n    for (int j = 0; j < N; ++j) line[j] = grid[r][j];\n    for (int j = 0; j < N; ++j) line[N + j] = line[j];\n\n    BS mark = scan_line(line, 2 * N);\n    BS changed;\n    bs_xor(changed, row_bs[r], mark);\n\n    bs_for_each(changed, [&](int i) {\n        bool oldFlag = bs_test(row_bs[r], i);\n        bool newFlag = bs_test(mark, i);\n        if (oldFlag == newFlag) return; // should not happen but safe\n\n        if (newFlag) {\n            bs_set(row_bs[r], i);\n            if (pattern_cov_count[i] == 0) current_c++;\n            pattern_cov_count[i]++;\n        } else {\n            bs_reset(row_bs[r], i);\n            pattern_cov_count[i]--;\n            if (pattern_cov_count[i] == 0) current_c--;\n        }\n    });\n}\n\n// recompute one column c and update global counts\nvoid recalc_col(int c) {\n    char line[2 * MAX_N];\n    for (int i = 0; i < N; ++i) line[i] = grid[i][c];\n    for (int i = 0; i < N; ++i) line[N + i] = line[i];\n\n    BS mark = scan_line(line, 2 * N);\n    BS changed;\n    bs_xor(changed, col_bs[c], mark);\n\n    bs_for_each(changed, [&](int i) {\n        bool oldFlag = bs_test(col_bs[c], i);\n        bool newFlag = bs_test(mark, i);\n        if (oldFlag == newFlag) return; // should not happen but safe\n\n        if (newFlag) {\n            bs_set(col_bs[c], i);\n            if (pattern_cov_count[i] == 0) current_c++;\n            pattern_cov_count[i]++;\n        } else {\n            bs_reset(col_bs[c], i);\n            pattern_cov_count[i]--;\n            if (pattern_cov_count[i] == 0) current_c--;\n        }\n    });\n}\n\n// pattern \"kick\" move: force-place a random pattern somewhere\nvoid apply_pattern_kick() {\n    uniform_int_distribution<int> pat_dist(0, M - 1);\n    int pid = pat_dist(rng);\n    const string &s = patterns[pid];\n    int len = (int)s.size();\n\n    uniform_int_distribution<int> dir_dist(0, 1);\n    int dir = dir_dist(rng); // 0: horizontal, 1: vertical\n\n    bool rowChanged[MAX_N] = {false};\n    bool colChanged[MAX_N] = {false};\n\n    if (dir == 0) {\n        uniform_int_distribution<int> row_dist(0, N - 1);\n        uniform_int_distribution<int> col_dist(0, N - 1);\n        int r = row_dist(rng);\n        int c0 = col_dist(rng);\n\n        int c = c0;\n        for (int t = 0; t < len; ++t) {\n            if (grid[r][c] != s[t]) {\n                grid[r][c] = s[t];\n                rowChanged[r] = true;\n                colChanged[c] = true;\n            }\n            c++;\n            if (c == N) c = 0;\n        }\n    } else {\n        uniform_int_distribution<int> row_dist(0, N - 1);\n        uniform_int_distribution<int> col_dist(0, N - 1);\n        int r0 = row_dist(rng);\n        int c = col_dist(rng);\n\n        int r = r0;\n        for (int t = 0; t < len; ++t) {\n            if (grid[r][c] != s[t]) {\n                grid[r][c] = s[t];\n                rowChanged[r] = true;\n                colChanged[c] = true;\n            }\n            r++;\n            if (r == N) r = 0;\n        }\n    }\n\n    for (int r = 0; r < N; ++r) if (rowChanged[r]) recalc_row(r);\n    for (int c = 0; c < N; ++c) if (colChanged[c]) recalc_col(c);\n}\n\ndouble my_rand_double() {\n    // 53-bit mantissa random double in [0,1)\n    return (rng() >> 11) * (1.0 / (1ULL << 53));\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> M;\n    patterns.resize(M);\n    for (int i = 0; i < M; ++i) cin >> patterns[i];\n\n    WORDS = (M + 63) / 64;\n\n    // init RNG\n    uint64_t seed = chrono::high_resolution_clock::now().time_since_epoch().count();\n    rng.seed(seed);\n\n    build_automaton();\n\n    uniform_int_distribution<int> letter_dist(0, ALPHA - 1);\n\n    // initial grid: random letters\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            grid[i][j] = char('A' + letter_dist(rng));\n\n    // constructive pass: greedily place patterns to align with existing letters\n    vector<int> order(M);\n    iota(order.begin(), order.end(), 0);\n    shuffle(order.begin(), order.end(), rng);\n\n    for (int idx = 0; idx < M; ++idx) {\n        int pid = order[idx];\n        const string &s = patterns[pid];\n        int len = (int)s.size();\n\n        int bestScore = -1;\n        int bestDir = 0;\n        int bestR = 0;\n        int bestC = 0;\n\n        // horizontal candidates\n        for (int r = 0; r < N; ++r) {\n            for (int c0 = 0; c0 < N; ++c0) {\n                int score = 0;\n                int c = c0;\n                for (int t = 0; t < len; ++t) {\n                    if (grid[r][c] == s[t]) score++;\n                    c++;\n                    if (c == N) c = 0;\n                }\n                if (score > bestScore) {\n                    bestScore = score;\n                    bestDir = 0;\n                    bestR = r;\n                    bestC = c0;\n                } else if (score == bestScore && my_rand_double() < 0.5) {\n                    bestScore = score;\n                    bestDir = 0;\n                    bestR = r;\n                    bestC = c0;\n                }\n            }\n        }\n\n        // vertical candidates\n        for (int c = 0; c < N; ++c) {\n            for (int r0 = 0; r0 < N; ++r0) {\n                int score = 0;\n                int r = r0;\n                for (int t = 0; t < len; ++t) {\n                    if (grid[r][c] == s[t]) score++;\n                    r++;\n                    if (r == N) r = 0;\n                }\n                if (score > bestScore) {\n                    bestScore = score;\n                    bestDir = 1;\n                    bestR = r0;\n                    bestC = c;\n                } else if (score == bestScore && my_rand_double() < 0.5) {\n                    bestScore = score;\n                    bestDir = 1;\n                    bestR = r0;\n                    bestC = c;\n                }\n            }\n        }\n\n        // apply best placement\n        if (bestDir == 0) {\n            int r = bestR;\n            int c = bestC;\n            for (int t = 0; t < len; ++t) {\n                grid[r][c] = s[t];\n                c++;\n                if (c == N) c = 0;\n            }\n        } else {\n            int c = bestC;\n            int r = bestR;\n            for (int t = 0; t < len; ++t) {\n                grid[r][c] = s[t];\n                r++;\n                if (r == N) r = 0;\n            }\n        }\n    }\n\n    // Initialize evaluation\n    for (int r = 0; r < N; ++r) bs_clear(row_bs[r]);\n    for (int c = 0; c < N; ++c) bs_clear(col_bs[c]);\n    fill(pattern_cov_count, pattern_cov_count + M, 0);\n    current_c = 0;\n\n    for (int r = 0; r < N; ++r) recalc_row(r);\n    for (int c = 0; c < N; ++c) recalc_col(c);\n\n    // SA parameters\n    const double TIME_LIMIT = 2.75; // seconds for SA part\n    auto start_time = chrono::high_resolution_clock::now();\n    double T0 = 1.5;\n    double T1 = 0.05;\n\n    // keep best grid\n    char best_grid[MAX_N][MAX_N];\n    int best_c = current_c;\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            best_grid[i][j] = grid[i][j];\n\n    int iter = 0;\n    uniform_int_distribution<int> row_dist(0, N - 1);\n    uniform_int_distribution<int> col_dist(0, N - 1);\n\n    while (true) {\n        auto now = chrono::high_resolution_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        if (elapsed > TIME_LIMIT) break;\n        double progress = elapsed / TIME_LIMIT;\n        double T = T0 + (T1 - T0) * progress;\n\n        // occasional pattern kick in early phase\n        if ((iter % 2000 == 0) && (progress < 0.5)) {\n            apply_pattern_kick();\n            if (current_c > best_c) {\n                best_c = current_c;\n                for (int i = 0; i < N; ++i)\n                    for (int j = 0; j < N; ++j)\n                        best_grid[i][j] = grid[i][j];\n            }\n        }\n\n        int r = row_dist(rng);\n        int c = col_dist(rng);\n        char oldCh = grid[r][c];\n\n        char newCh;\n        do {\n            newCh = char('A' + letter_dist(rng));\n        } while (newCh == oldCh);\n\n        // candidate row\n        char row_line[2 * MAX_N];\n        for (int j = 0; j < N; ++j)\n            row_line[j] = (j == c) ? newCh : grid[r][j];\n        for (int j = 0; j < N; ++j)\n            row_line[N + j] = row_line[j];\n\n        BS mark_row = scan_line(row_line, 2 * N);\n\n        // candidate column\n        char col_line[2 * MAX_N];\n        for (int i = 0; i < N; ++i)\n            col_line[i] = (i == r) ? newCh : grid[i][c];\n        for (int i = 0; i < N; ++i)\n            col_line[N + i] = col_line[i];\n\n        BS mark_col = scan_line(col_line, 2 * N);\n\n        // changed patterns on row and column\n        BS changed_row, changed_col, changed_union;\n        bs_xor(changed_row, row_bs[r], mark_row);\n        bs_xor(changed_col, col_bs[c], mark_col);\n        bs_or(changed_union, changed_row, changed_col);\n\n        int new_c = current_c;\n\n        // compute new_c considering only changed patterns\n        bs_for_each(changed_union, [&](int i) {\n            int oldCov = pattern_cov_count[i];\n            int newCov = oldCov;\n\n            bool oldRow = bs_test(row_bs[r], i);\n            bool newRow = bs_test(mark_row, i);\n            newCov += (int)newRow - (int)oldRow;\n\n            bool oldCol = bs_test(col_bs[c], i);\n            bool newCol = bs_test(mark_col, i);\n            newCov += (int)newCol - (int)oldCol;\n\n            if (oldCov == 0 && newCov > 0) new_c++;\n            else if (oldCov > 0 && newCov == 0) new_c--;\n        });\n\n        int delta = new_c - current_c;\n        bool accept = false;\n        if (delta >= 0) {\n            accept = true;\n        } else {\n            double prob = exp((double)delta / T);\n            if (prob > my_rand_double()) accept = true;\n        }\n\n        if (accept) {\n            // commit the change\n            grid[r][c] = newCh;\n            bs_for_each(changed_union, [&](int i) {\n                int oldCov = pattern_cov_count[i];\n                int newCov = oldCov;\n\n                bool oldRow = bs_test(row_bs[r], i);\n                bool newRow = bs_test(mark_row, i);\n                newCov += (int)newRow - (int)oldRow;\n\n                bool oldCol = bs_test(col_bs[c], i);\n                bool newCol = bs_test(mark_col, i);\n                newCov += (int)newCol - (int)oldCol;\n\n                pattern_cov_count[i] = newCov;\n\n                if (newRow) bs_set(row_bs[r], i);\n                else bs_reset(row_bs[r], i);\n                if (newCol) bs_set(col_bs[c], i);\n                else bs_reset(col_bs[c], i);\n            });\n            current_c = new_c;\n\n            if (current_c > best_c) {\n                best_c = current_c;\n                for (int i = 0; i < N; ++i)\n                    for (int j = 0; j < N; ++j)\n                        best_grid[i][j] = grid[i][j];\n            }\n        }\n\n        ++iter;\n    }\n\n    // Output best grid\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cout << best_grid[i][j];\n        }\n        cout << '\\n';\n    }\n\n    return 0;\n}","ahc005":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Edge {\n    int to;\n    int w;\n};\n\nconst int INF = 1e9;\n\n// Compute travel time of a route (sequence of cell IDs).\n// Cost to move into cell v is cost[v].\nlong long computeTravelTime(const vector<int> &route, const vector<int> &cost) {\n    long long t = 0;\n    for (int i = 1; i < (int)route.size(); ++i) {\n        t += cost[route[i]];\n    }\n    return t;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, si, sj;\n    if (!(cin >> N >> si >> sj)) return 0;\n    vector<string> grid(N);\n    for (int i = 0; i < N; ++i) cin >> grid[i];\n\n    // Map each road cell to an ID\n    static int idOf[70][70];\n    int r = 0;\n    vector<pair<int,int>> pos;   // id -> (i,j)\n    vector<int> cost;            // id -> cell cost (5-9)\n    pos.reserve(N * N);\n    cost.reserve(N * N);\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (grid[i][j] != '#') {\n                idOf[i][j] = r++;\n                pos.emplace_back(i, j);\n                cost.push_back(grid[i][j] - '0');\n            } else {\n                idOf[i][j] = -1;\n            }\n        }\n    }\n\n    if (r == 0) {\n        cout << \"\\n\";\n        return 0;\n    }\n\n    int startId = idOf[si][sj];\n\n    // Build graph of road cells\n    vector<vector<Edge>> G(r);\n    int di[4] = {-1, 1, 0, 0};\n    int dj[4] = {0, 0, -1, 1};\n    for (int id = 0; id < r; ++id) {\n        auto [i, j] = pos[id];\n        for (int d = 0; d < 4; ++d) {\n            int ni = i + di[d], nj = j + dj[d];\n            if (0 <= ni && ni < N && 0 <= nj && nj < N && idOf[ni][nj] != -1) {\n                int v = idOf[ni][nj];\n                G[id].push_back({v, cost[v]});\n            }\n        }\n    }\n\n    // ---------- Fallback DFS route (visits all cells) ----------\n    auto buildDFSRoute = [&]() -> vector<int> {\n        vector<int> route;\n        route.reserve(2 * r + 5);\n        vector<char> used(r, 0);\n        vector<int> st;\n        vector<int> edgeIdx(r, 0);\n\n        route.push_back(startId);\n        used[startId] = 1;\n        st.push_back(startId);\n\n        while (!st.empty()) {\n            int u = st.back();\n            bool advanced = false;\n            int &ei = edgeIdx[u];\n            while (ei < (int)G[u].size()) {\n                int v = G[u][ei].to;\n                ++ei;\n                if (!used[v]) {\n                    used[v] = 1;\n                    st.push_back(v);\n                    route.push_back(v);\n                    advanced = true;\n                    break;\n                }\n            }\n            if (!advanced) {\n                st.pop_back();\n                if (!st.empty()) {\n                    route.push_back(st.back());\n                }\n            }\n        }\n        return route; // starts and ends at startId\n    };\n\n    vector<int> fallbackRoute = buildDFSRoute();\n    long long fallbackTime = computeTravelTime(fallbackRoute, cost);\n\n    // ---------- Build horizontal and vertical segments ----------\n    vector<vector<int>> rowSegCells;\n    vector<int> rowSegIdOfCell(r, -1);\n    for (int i = 0; i < N; ++i) {\n        int j = 0;\n        while (j < N) {\n            if (grid[i][j] == '#') {\n                ++j;\n                continue;\n            }\n            int segIdx = (int)rowSegCells.size();\n            rowSegCells.emplace_back();\n            while (j < N && grid[i][j] != '#') {\n                int id = idOf[i][j];\n                rowSegIdOfCell[id] = segIdx;\n                rowSegCells.back().push_back(id);\n                ++j;\n            }\n        }\n    }\n\n    vector<vector<int>> colSegCells;\n    vector<int> colSegIdOfCell(r, -1);\n    for (int j = 0; j < N; ++j) {\n        int i = 0;\n        while (i < N) {\n            if (grid[i][j] == '#') {\n                ++i;\n                continue;\n            }\n            int segIdx = (int)colSegCells.size();\n            colSegCells.emplace_back();\n            while (i < N && grid[i][j] != '#') {\n                int id = idOf[i][j];\n                colSegIdOfCell[id] = segIdx;\n                colSegCells.back().push_back(id);\n                ++i;\n            }\n        }\n    }\n\n    // ---------- Precompute visibility (coverage) for all cells ----------\n    vector<vector<int>> coverageAll(r);\n    for (int id = 0; id < r; ++id) {\n        auto &v = coverageAll[id];\n        auto &rowV = rowSegCells[rowSegIdOfCell[id]];\n        auto &colV = colSegCells[colSegIdOfCell[id]];\n        v.reserve(rowV.size() + colV.size());\n        for (int x : rowV) v.push_back(x);\n        for (int x : colV) v.push_back(x);\n    }\n\n    // ---------- Build candidate vantage cells (mostly intersections) ----------\n    vector<char> isIntersection(r, 0);\n    vector<char> hasInterRow(rowSegCells.size(), 0);\n    vector<char> hasInterCol(colSegCells.size(), 0);\n\n    for (int id = 0; id < r; ++id) {\n        auto [i, j] = pos[id];\n        bool hor = false, ver = false;\n        if (j > 0 && idOf[i][j-1] != -1) hor = true;\n        if (j+1 < N && idOf[i][j+1] != -1) hor = true;\n        if (i > 0 && idOf[i-1][j] != -1) ver = true;\n        if (i+1 < N && idOf[i+1][j] != -1) ver = true;\n        if (hor && ver) {\n            isIntersection[id] = 1;\n            hasInterRow[rowSegIdOfCell[id]] = 1;\n            hasInterCol[colSegIdOfCell[id]] = 1;\n        }\n    }\n\n    vector<char> isCandidate(r, 0);\n    vector<int> candidateCells;\n    candidateCells.reserve(r);\n\n    // Intersections\n    for (int id = 0; id < r; ++id) {\n        if (isIntersection[id]) {\n            isCandidate[id] = 1;\n            candidateCells.push_back(id);\n        }\n    }\n    // Midpoints of segments without intersections\n    for (int s = 0; s < (int)rowSegCells.size(); ++s) {\n        if (!hasInterRow[s]) {\n            int mid = rowSegCells[s][rowSegCells[s].size() / 2];\n            if (!isCandidate[mid]) {\n                isCandidate[mid] = 1;\n                candidateCells.push_back(mid);\n            }\n        }\n    }\n    for (int s = 0; s < (int)colSegCells.size(); ++s) {\n        if (!hasInterCol[s]) {\n            int mid = colSegCells[s][colSegCells[s].size() / 2];\n            if (!isCandidate[mid]) {\n                isCandidate[mid] = 1;\n                candidateCells.push_back(mid);\n            }\n        }\n    }\n    // Ensure start cell is candidate\n    if (!isCandidate[startId]) {\n        isCandidate[startId] = 1;\n        candidateCells.push_back(startId);\n    }\n\n    // Coverage of candidates, and which cells are coverable by some candidate\n    int C = (int)candidateCells.size();\n    vector<vector<int>> candCover;\n    candCover.reserve(C);\n    vector<char> cellCovered(r, 0);\n    for (int idx = 0; idx < C; ++idx) {\n        int cell = candidateCells[idx];\n        candCover.push_back(coverageAll[cell]);\n        for (int x : candCover.back()) cellCovered[x] = 1;\n    }\n\n    // Patch: if some cell is not covered by any candidate, add it itself as candidate\n    for (int id = 0; id < r; ++id) {\n        if (!cellCovered[id]) {\n            candidateCells.push_back(id);\n            candCover.push_back(coverageAll[id]);\n            for (int x : coverageAll[id]) cellCovered[x] = 1;\n        }\n    }\n    C = (int)candidateCells.size();\n\n    // ---------- Greedy set cover on candidates (cell-based) ----------\n    vector<int> vantageCells;\n    vantageCells.reserve(C);\n\n    vector<char> coveredCells(r, 0);\n    int coveredCount = 0;\n    vector<char> candSelected(C, 0);\n\n    auto selectCandidate = [&](int idx) {\n        if (candSelected[idx]) return;\n        candSelected[idx] = 1;\n        int cell = candidateCells[idx];\n        vantageCells.push_back(cell);\n        for (int x : candCover[idx]) {\n            if (!coveredCells[x]) {\n                coveredCells[x] = 1;\n                ++coveredCount;\n            }\n        }\n    };\n\n    // Use start cell as the first vantage (it's \"free\" since we start there)\n    int startCandIdx = -1;\n    for (int idx = 0; idx < C; ++idx) {\n        if (candidateCells[idx] == startId) {\n            startCandIdx = idx;\n            break;\n        }\n    }\n    if (startCandIdx == -1) {\n        // Safeguard (shouldn't happen)\n        vantageCells.push_back(startId);\n        for (int x : coverageAll[startId]) {\n            if (!coveredCells[x]) {\n                coveredCells[x] = 1;\n                ++coveredCount;\n            }\n        }\n    } else {\n        selectCandidate(startCandIdx);\n    }\n\n    // Greedy: repeatedly add candidate with maximum marginal gain\n    while (coveredCount < r) {\n        int bestIdx = -1;\n        int bestGain = -1;\n        for (int idx = 0; idx < C; ++idx) {\n            if (candSelected[idx]) continue;\n            int gain = 0;\n            for (int x : candCover[idx]) {\n                if (!coveredCells[x]) ++gain;\n            }\n            if (gain > bestGain) {\n                bestGain = gain;\n                bestIdx = idx;\n            } else if (gain == bestGain && gain > 0 && bestIdx != -1) {\n                // Tie-break: closer to start (Manhattan)\n                int cellNew = candidateCells[idx];\n                int cellBest = candidateCells[bestIdx];\n                auto [ni, nj] = pos[cellNew];\n                auto [bi, bj] = pos[cellBest];\n                int manNew = abs(ni - si) + abs(nj - sj);\n                int manBest = abs(bi - si) + abs(bj - sj);\n                if (manNew < manBest) bestIdx = idx;\n            }\n        }\n\n        if (bestIdx == -1 || bestGain <= 0) {\n            // Safeguard: directly add some uncovered cell as vantage\n            int uncoveredId = -1;\n            for (int id = 0; id < r; ++id) {\n                if (!coveredCells[id]) {\n                    uncoveredId = id;\n                    break;\n                }\n            }\n            if (uncoveredId == -1) break; // should not happen\n            vantageCells.push_back(uncoveredId);\n            for (int x : coverageAll[uncoveredId]) {\n                if (!coveredCells[x]) {\n                    coveredCells[x] = 1;\n                    ++coveredCount;\n                }\n            }\n        } else {\n            selectCandidate(bestIdx);\n        }\n    }\n\n    // Deduplicate vantages (just in case)\n    sort(vantageCells.begin(), vantageCells.end());\n    vantageCells.erase(unique(vantageCells.begin(), vantageCells.end()), vantageCells.end());\n\n    // ---------- Dijkstra helpers ----------\n    vector<int> dist(r), prevv(r);\n\n    auto dijkstraNearestTarget = [&](int src,\n                                     const vector<char> &isTarget,\n                                     const vector<char> &visitedTarget) -> int {\n        fill(dist.begin(), dist.end(), INF);\n        fill(prevv.begin(), prevv.end(), -1);\n        priority_queue<pair<int,int>, vector<pair<int,int>>, greater<pair<int,int>>> pq;\n        dist[src] = 0;\n        pq.push({0, src});\n        int target = -1;\n        while (!pq.empty()) {\n            auto [d, u] = pq.top();\n            pq.pop();\n            if (d != dist[u]) continue;\n            if (isTarget[u] && !visitedTarget[u]) {\n                target = u;\n                break;\n            }\n            for (auto &e : G[u]) {\n                int v = e.to;\n                int nd = d + e.w;\n                if (nd < dist[v]) {\n                    dist[v] = nd;\n                    prevv[v] = u;\n                    pq.push({nd, v});\n                }\n            }\n        }\n        return target;\n    };\n\n    auto dijkstraToDest = [&](int src, int dest) {\n        fill(dist.begin(), dist.end(), INF);\n        fill(prevv.begin(), prevv.end(), -1);\n        priority_queue<pair<int,int>, vector<pair<int,int>>, greater<pair<int,int>>> pq;\n        dist[src] = 0;\n        pq.push({0, src});\n        while (!pq.empty()) {\n            auto [d, u] = pq.top();\n            pq.pop();\n            if (d != dist[u]) continue;\n            if (u == dest) break;\n            for (auto &e : G[u]) {\n                int v = e.to;\n                int nd = d + e.w;\n                if (nd < dist[v]) {\n                    dist[v] = nd;\n                    prevv[v] = u;\n                    pq.push({nd, v});\n                }\n            }\n        }\n    };\n\n    auto appendPath = [&](vector<int> &route, int src, int dest) {\n        if (src == dest) return;\n        dijkstraToDest(src, dest);\n        vector<int> tmp;\n        int x = dest;\n        while (x != src && x != -1) {\n            tmp.push_back(x);\n            x = prevv[x];\n        }\n        for (int i = (int)tmp.size() - 1; i >= 0; --i) {\n            route.push_back(tmp[i]);\n        }\n    };\n\n    // ---------- Route 1: Greedy nearest neighbor on vantages ----------\n    auto buildRouteGreedyNN = [&](const vector<int> &vantages) -> vector<int> {\n        vector<int> route;\n        route.reserve(2 * r + 5);\n\n        vector<char> isTarget(r, 0), visitedTarget(r, 0);\n        for (int id : vantages) isTarget[id] = 1;\n\n        int remainingTargets = 0;\n        for (int id : vantages) {\n            if (id == startId) {\n                visitedTarget[id] = 1;\n            } else {\n                ++remainingTargets;\n            }\n        }\n\n        route.push_back(startId);\n        int curr = startId;\n\n        while (remainingTargets > 0) {\n            int target = dijkstraNearestTarget(curr, isTarget, visitedTarget);\n            if (target == -1) break; // should not happen (connected component)\n\n            // Reconstruct path curr -> target using prevv from dijkstraNearestTarget\n            vector<int> tmp;\n            int x = target;\n            while (x != curr && x != -1) {\n                tmp.push_back(x);\n                x = prevv[x];\n            }\n            for (int i = (int)tmp.size() - 1; i >= 0; --i) {\n                int node = tmp[i];\n                route.push_back(node);\n                if (isTarget[node] && !visitedTarget[node]) {\n                    visitedTarget[node] = 1;\n                    --remainingTargets;\n                }\n            }\n            curr = target;\n        }\n\n        // Return to start\n        if (curr != startId) {\n            appendPath(route, curr, startId);\n        }\n        return route;\n    };\n\n    vector<int> routeNN = buildRouteGreedyNN(vantageCells);\n    long long timeNN = computeTravelTime(routeNN, cost);\n\n    // ---------- Route 2: Approximate TSP (Manhattan + 2-opt) on vantages ----------\n    vector<int> routeTSP;\n    long long timeTSP = (1LL << 60);\n\n    if (!vantageCells.empty()) {\n        // Build node list: start + all vantages (without duplicating start)\n        vector<int> nodes;\n        nodes.reserve(vantageCells.size() + 1);\n        nodes.push_back(startId);\n        for (int v : vantageCells) {\n            if (v != startId) nodes.push_back(v);\n        }\n        int K = (int)nodes.size();\n\n        // Limit TSP heuristic to moderate size to keep cost under control\n        if (K <= 250) {\n            // Manhattan distances as cheap approximation\n            vector<vector<int>> approxDist(K, vector<int>(K, 0));\n            for (int i = 0; i < K; ++i) {\n                auto [xi, yi] = pos[nodes[i]];\n                for (int j = i + 1; j < K; ++j) {\n                    auto [xj, yj] = pos[nodes[j]];\n                    int d = abs(xi - xj) + abs(yi - yj);\n                    approxDist[i][j] = approxDist[j][i] = d;\n                }\n            }\n\n            // Initial route: nearest neighbor on approxDist\n            vector<int> order(K);\n            vector<char> used(K, 0);\n            order[0] = 0;\n            used[0] = 1;\n            for (int t = 1; t < K; ++t) {\n                int prevIdx = order[t - 1];\n                int best = -1;\n                int bestD = INT_MAX;\n                for (int j = 0; j < K; ++j) {\n                    if (used[j]) continue;\n                    int d = approxDist[prevIdx][j];\n                    if (d < bestD) {\n                        bestD = d;\n                        best = j;\n                    }\n                }\n                if (best == -1) best = 0; // safety\n                order[t] = best;\n                used[best] = 1;\n            }\n\n            // 2-opt improvement (first-improvement, keep start fixed at order[0] = 0)\n            bool improved = true;\n            while (improved) {\n                improved = false;\n                for (int i = 1; i < K - 1 && !improved; ++i) {\n                    int a = order[i - 1];\n                    int b = order[i];\n                    for (int j = i + 1; j < K; ++j) {\n                        int c = order[j];\n                        int d = (j + 1 < K ? order[j + 1] : order[0]);\n                        int curCost = approxDist[a][b] + approxDist[c][d];\n                        int newCost = approxDist[a][c] + approxDist[b][d];\n                        if (newCost < curCost) {\n                            reverse(order.begin() + i, order.begin() + j + 1);\n                            improved = true;\n                            break;\n                        }\n                    }\n                }\n            }\n\n            // Build actual route following this order (0..K-1), starting at startId\n            routeTSP.reserve(2 * r + 5);\n            routeTSP.push_back(startId);\n            int curr = startId;\n            for (int idxPos = 1; idxPos < K; ++idxPos) {\n                int nodeIdx = order[idxPos];\n                int dest = nodes[nodeIdx];\n                if (dest == curr) continue;\n                appendPath(routeTSP, curr, dest);\n                curr = dest;\n            }\n            if (curr != startId) {\n                appendPath(routeTSP, curr, startId);\n            }\n            timeTSP = computeTravelTime(routeTSP, cost);\n        }\n    }\n\n    // ---------- Choose the best route among: DFS fallback, NN, TSP ----------\n    vector<int> bestRoute = fallbackRoute;\n    long long bestTime = fallbackTime;\n\n    if (!routeNN.empty() && timeNN < bestTime) {\n        bestTime = timeNN;\n        bestRoute = std::move(routeNN);\n    }\n    if (!routeTSP.empty() && timeTSP < bestTime) {\n        bestTime = timeTSP;\n        bestRoute = std::move(routeTSP);\n    }\n\n    // If route has no movement, add a tiny loop to avoid t=0\n    if ((int)bestRoute.size() == 1) {\n        int u = startId;\n        int v = -1;\n        for (auto &e : G[u]) {\n            v = e.to;\n            break;\n        }\n        if (v != -1) {\n            bestRoute.push_back(v);\n            bestRoute.push_back(u);\n        }\n    }\n\n    // ---------- Convert node sequence to direction string ----------\n    string ans;\n    ans.reserve(bestRoute.size());\n    for (int i = 1; i < (int)bestRoute.size(); ++i) {\n        auto [i1, j1] = pos[bestRoute[i-1]];\n        auto [i2, j2] = pos[bestRoute[i]];\n        if (i2 == i1 - 1 && j2 == j1) ans.push_back('U');\n        else if (i2 == i1 + 1 && j2 == j1) ans.push_back('D');\n        else if (j2 == j1 - 1 && i2 == i1) ans.push_back('L');\n        else if (j2 == j1 + 1 && i2 == i1) ans.push_back('R');\n        else {\n            // Should not happen with valid shortest paths\n        }\n    }\n\n    cout << ans << '\\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    if (!(cin >> N >> M >> K >> R)) return 0;\n\n    // Task requirements d[i][k]\n    vector<vector<int>> d(N, vector<int>(K));\n    for (int i = 0; i < N; ++i) {\n        for (int k = 0; k < K; ++k) cin >> d[i][k];\n    }\n\n    // Dependencies: u -> v\n    vector<vector<int>> out(N);\n    vector<int> indeg(N, 0);\n    for (int e = 0; e < R; ++e) {\n        int u, v;\n        cin >> u >> v;\n        --u; --v;\n        out[u].push_back(v);\n        indeg[v]++;\n    }\n\n    // Precompute depth-from-end (longest path length to any sink)\n    vector<int> depth(N, 0);\n    for (int i = N - 1; i >= 0; --i) {\n        int best = 0;\n        for (int v : out[i]) {\n            best = max(best, depth[v] + 1);\n        }\n        depth[i] = best;\n    }\n\n    // Precompute simple difficulty measure (L1 norm)\n    vector<int> diffL1(N, 0);\n    for (int i = 0; i < N; ++i) {\n        int s = 0;\n        for (int k = 0; k < K; ++k) s += d[i][k];\n        diffL1[i] = s;\n    }\n\n    // Task states\n    const int NOT_STARTED = 0;\n    const int IN_PROGRESS = 1;\n    const int DONE = 2;\n    vector<int> state(N, NOT_STARTED);\n    vector<int> degRem = indeg;\n    int tasksDone = 0;\n\n    // Worker states\n    vector<int> curTask(M, -1);\n    vector<int> startDay(M, -1);\n\n    // Worker skill vectors s_j[k]\n    vector<vector<double>> skill(M, vector<double>(K, 0.0));\n    // History of (task, w_obs) per worker for fitting\n    vector<vector<int>> histTasks(M);\n    vector<vector<double>> histW(M);\n\n    const int    FIT_ITERS = 5;\n    const double LR        = 0.05;\n    const double SKILL_MAX = 100.0;\n\n    // Fitting function for one worker (small batch GD over its history)\n    auto fitWorker = [&](int j) {\n        auto &s  = skill[j];\n        auto &ht = histTasks[j];\n        auto &hw = histW[j];\n        int S = (int)ht.size();\n        if (S == 0) return;\n        for (int it = 0; it < FIT_ITERS; ++it) {\n            for (int idx = 0; idx < S; ++idx) {\n                int ti = ht[idx];\n                double w_obs = hw[idx];\n\n                // Compute w_pred = sum_k max(0, d[ti][k] - s[k])\n                const auto &dv = d[ti];\n                double w_pred = 0.0;\n                for (int k = 0; k < K; ++k) {\n                    double diff = (double)dv[k] - s[k];\n                    if (diff > 0.0) w_pred += diff;\n                }\n\n                double e = w_pred - w_obs;\n                if (e == 0.0) continue;\n                double step = LR * e;\n\n                // Gradient: for dims where d > s, s[k] += step\n                for (int k = 0; k < K; ++k) {\n                    if ((double)dv[k] > s[k]) {\n                        s[k] += step;\n                        if (s[k] < 0.0) s[k] = 0.0;\n                        if (s[k] > SKILL_MAX) s[k] = SKILL_MAX;\n                    }\n                }\n            }\n        }\n    };\n\n    int day = 0;\n    const int MAX_CAND = 400;  // number of candidate tasks per day to consider\n\n    while (true) {\n        day++;\n\n        // Compute available tasks (not started and all prerequisites done)\n        vector<int> available;\n        if (tasksDone < N) {\n            available.reserve(N);\n            for (int i = 0; i < N; ++i) {\n                if (state[i] == NOT_STARTED && degRem[i] == 0) {\n                    available.push_back(i);\n                }\n            }\n        }\n\n        // Collect free workers\n        vector<int> freeWorkers;\n        freeWorkers.reserve(M);\n        for (int j = 0; j < M; ++j) {\n            if (curTask[j] == -1) freeWorkers.push_back(j);\n        }\n\n        vector<pair<int,int>> assigns; // (worker, task)\n\n        if (!freeWorkers.empty() && !available.empty()) {\n            // Sort available tasks by priority: depth desc, diffL1 desc, id asc\n            auto cmpTask = [&](int x, int y) {\n                if (depth[x] != depth[y]) return depth[x] > depth[y];\n                if (diffL1[x] != diffL1[y]) return diffL1[x] > diffL1[y];\n                return x < y;\n            };\n\n            int sz = (int)available.size();\n            if (sz > MAX_CAND) {\n                int limit = MAX_CAND;\n                partial_sort(available.begin(), available.begin() + limit,\n                             available.end(), cmpTask);\n                available.resize(limit);\n                sz = limit;\n            } else {\n                sort(available.begin(), available.end(), cmpTask);\n            }\n\n            // Build all (worker, task) options with predicted cost = t_pred\n            struct Option {\n                double cost;\n                int w;\n                int task;\n            };\n            vector<Option> options;\n            options.reserve(freeWorkers.size() * sz);\n\n            for (int widx = 0; widx < (int)freeWorkers.size(); ++widx) {\n                int j = freeWorkers[widx];\n                const auto &sj = skill[j];\n                for (int tidx = 0; tidx < sz; ++tidx) {\n                    int ti = available[tidx];\n                    const auto &dv = d[ti];\n                    double w_pred = 0.0;\n                    for (int k = 0; k < K; ++k) {\n                        double diff = (double)dv[k] - sj[k];\n                        if (diff > 0.0) w_pred += diff;\n                    }\n                    if (w_pred < 0.0) w_pred = 0.0;\n                    double t_pred = (w_pred < 1.0 ? 1.0 : w_pred);\n                    options.push_back(Option{t_pred, j, ti});\n                }\n            }\n\n            sort(options.begin(), options.end(),\n                 [](const Option &a, const Option &b) {\n                     if (a.cost != b.cost) return a.cost < b.cost;\n                     if (a.w != b.w) return a.w < b.w;\n                     return a.task < b.task;\n                 });\n\n            vector<char> workerUsed(M, 0);\n            vector<char> taskUsed(N, 0);\n            assigns.reserve(freeWorkers.size());\n\n            for (const auto &opt : options) {\n                if ((int)assigns.size() == (int)freeWorkers.size()) break;\n                int j  = opt.w;\n                int ti = opt.task;\n                if (workerUsed[j] || taskUsed[ti]) continue;\n                workerUsed[j] = 1;\n                taskUsed[ti]  = 1;\n                assigns.emplace_back(j, ti);\n            }\n        }\n\n        // Output assignments and update worker/task states\n        int m = (int)assigns.size();\n        cout << m;\n        for (auto &p : assigns) {\n            int j  = p.first;\n            int ti = p.second;\n            cout << ' ' << (j + 1) << ' ' << (ti + 1);\n            curTask[j] = ti;\n            startDay[j] = day;\n            state[ti] = IN_PROGRESS;\n        }\n        cout << '\\n' << flush;\n\n        // Read feedback: list of finished workers\n        int n;\n        if (!(cin >> n)) return 0;\n        if (n == -1) break;\n\n        vector<int> finishedWorkers;\n        finishedWorkers.reserve(n);\n        for (int i = 0; i < n; ++i) {\n            int f;\n            cin >> f;\n            finishedWorkers.push_back(f - 1); // zero-based\n        }\n\n        // Process completions\n        for (int idx = 0; idx < n; ++idx) {\n            int j = finishedWorkers[idx];\n            int ti = (j >= 0 && j < M) ? curTask[j] : -1;\n            if (ti < 0) continue;\n\n            int st = startDay[j];\n            if (st < 1) st = day;  // safety\n            int t_obs = day - st + 1;\n            if (t_obs < 1) t_obs = 1;\n            int w_obs_int = t_obs - 1;\n            if (w_obs_int < 0) w_obs_int = 0;\n            double w_obs = (double)w_obs_int;\n\n            // Record sample for worker j\n            histTasks[j].push_back(ti);\n            histW[j].push_back(w_obs);\n            // Re-fit worker j's skill vector\n            fitWorker(j);\n\n            // Mark task completion\n            state[ti] = DONE;\n            tasksDone++;\n            curTask[j] = -1;\n            startDay[j] = -1;\n\n            // Update indegrees of children\n            for (int v : out[ti]) {\n                degRem[v]--;\n            }\n        }\n    }\n\n    return 0;\n}","ahc006":"#include <bits/stdc++.h>\nusing namespace std;\n\n// ---------------------------------------------------------------\n// Types and globals\n// ---------------------------------------------------------------\n\nstruct TourResult {\n    vector<int> tour; // sequence of node indices, starts and ends with 0 (office)\n    int cost;\n};\n\nstatic int distMat[52][52];   // for TSP up to 51 nodes (0..50)\nstatic int nodeX[52], nodeY[52];\n\nconst int OFFICE_X = 400;\nconst int OFFICE_Y = 400;\n\n// RNG: simple xorshift\nstruct XorShift {\n    uint64_t x;\n    XorShift(uint64_t seed = 88172645463393265ULL) { x = seed; }\n    uint64_t next_u64() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return x;\n    }\n    uint32_t next_u32() { return (uint32_t)next_u64(); }\n    uint32_t next_uint(uint32_t mod) { return (uint32_t)(next_u64() % mod); }\n    double next_double() {\n        return (next_u64() >> 11) * (1.0 / (1ULL << 53));\n    }\n};\n\n// Manhattan distance\ninline int manhattan(int x1, int y1, int x2, int y2) {\n    return abs(x1 - x2) + abs(y1 - y2);\n}\n\n// ---------------------------------------------------------------\n// TSP solver: nearest neighbor + 2-opt\n// Points: X[i], Y[i] for i=0..m-1 correspond to nodes 1..m.\n// Node 0 is the office at (400,400).\n// ---------------------------------------------------------------\nTourResult solve_tsp_points(const vector<int>& X, const vector<int>& Y) {\n    int m = (int)X.size();       // number of non-office nodes (<=50)\n    int nNodes = m + 1;          // nodes 0..m\n\n    // Build node coordinates (0: office)\n    nodeX[0] = OFFICE_X;\n    nodeY[0] = OFFICE_Y;\n    for (int i = 1; i <= m; ++i) {\n        nodeX[i] = X[i - 1];\n        nodeY[i] = Y[i - 1];\n    }\n\n    // Distance matrix\n    for (int i = 0; i <= m; ++i) {\n        for (int j = 0; j <= m; ++j) {\n            distMat[i][j] = manhattan(nodeX[i], nodeY[i], nodeX[j], nodeY[j]);\n        }\n    }\n\n    // Nearest neighbor construction, start at office (0)\n    vector<int> tour;\n    tour.reserve(nNodes + 1);\n    vector<char> used(nNodes, 0);\n    int cur = 0;\n    used[0] = 1;\n    tour.push_back(0);\n    for (int step = 0; step < m; ++step) {\n        int best = -1;\n        int bestDist = INT_MAX;\n        for (int v = 1; v <= m; ++v) {\n            if (!used[v]) {\n                int d = distMat[cur][v];\n                if (d < bestDist) {\n                    bestDist = d;\n                    best = v;\n                }\n            }\n        }\n        used[best] = 1;\n        tour.push_back(best);\n        cur = best;\n    }\n    tour.push_back(0); // return to office\n\n    // 2-opt improvement with fixed endpoints\n    int M = (int)tour.size(); // should be m+2\n    bool improved = true;\n    while (improved) {\n        improved = false;\n        for (int i = 1; i <= M - 3; ++i) {\n            int a = tour[i - 1];\n            int b = tour[i];\n            for (int k = i + 1; k <= M - 2; ++k) {\n                int c = tour[k];\n                int d = tour[k + 1];\n                int delta = distMat[a][c] + distMat[b][d]\n                          - distMat[a][b] - distMat[c][d];\n                if (delta < 0) {\n                    reverse(tour.begin() + i, tour.begin() + k + 1);\n                    improved = true;\n                    goto next_iteration;\n                }\n            }\n        }\n        next_iteration:;\n    }\n\n    int cost = 0;\n    for (int i = 0; i < M - 1; ++i) {\n        cost += distMat[tour[i]][tour[i + 1]];\n    }\n\n    TourResult res;\n    res.tour = move(tour);\n    res.cost = cost;\n    return res;\n}\n\n// ---------------------------------------------------------------\n// Evaluate a selection of orders:\n//   selection: vector of indices (0-based) of orders.\n//   Returns total cost, and stores the restaurant and destination tours.\n// ---------------------------------------------------------------\nint evaluate_selection(\n    const vector<int>& selection,\n    const vector<int>& a, const vector<int>& b,\n    const vector<int>& c, const vector<int>& d,\n    vector<int>& outRtour,\n    vector<int>& outDtour\n) {\n    int m = (int)selection.size(); // 50\n    vector<int> XR(m), YR(m), XD(m), YD(m);\n    for (int i = 0; i < m; ++i) {\n        int idx = selection[i];\n        XR[i] = a[idx];\n        YR[i] = b[idx];\n        XD[i] = c[idx];\n        YD[i] = d[idx];\n    }\n\n    TourResult rRes = solve_tsp_points(XR, YR);\n    TourResult dRes = solve_tsp_points(XD, YD);\n\n    outRtour = move(rRes.tour);\n    outDtour = move(dRes.tour);\n\n    return rRes.cost + dRes.cost;\n}\n\n// ---------------------------------------------------------------\n// Main\n// ---------------------------------------------------------------\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    const int N = 1000;\n    vector<int> a(N), b(N), c(N), d(N);\n    for (int i = 0; i < N; ++i) {\n        if (!(cin >> a[i] >> b[i] >> c[i] >> d[i])) {\n            return 0; // in case of incomplete input\n        }\n    }\n\n    // Precompute single-trip scores for initial selection\n    vector<int> single_trip(N);\n    for (int i = 0; i < N; ++i) {\n        int d0R = manhattan(OFFICE_X, OFFICE_Y, a[i], b[i]);\n        int dRD = manhattan(a[i], b[i], c[i], d[i]);\n        int dD0 = manhattan(c[i], d[i], OFFICE_X, OFFICE_Y);\n        single_trip[i] = d0R + dRD + dD0;\n    }\n\n    // Initial selection: 50 orders with smallest single-trip cost\n    vector<int> idx(N);\n    iota(idx.begin(), idx.end(), 0);\n    sort(idx.begin(), idx.end(), [&](int i, int j) {\n        return single_trip[i] < single_trip[j];\n    });\n\n    const int M = 50;\n    vector<int> currentSel(M);\n    for (int i = 0; i < M; ++i) currentSel[i] = idx[i];\n\n    vector<char> inCurrent(N, 0);\n    for (int i = 0; i < M; ++i) inCurrent[currentSel[i]] = 1;\n\n    // Evaluate initial selection\n    vector<int> bestRtour, bestDtour;\n    vector<int> tmpRtour, tmpDtour;\n    int currentCost = evaluate_selection(currentSel, a, b, c, d, tmpRtour, tmpDtour);\n\n    vector<int> bestSel = currentSel;\n    bestRtour = tmpRtour;\n    bestDtour = tmpDtour;\n    int bestCost = currentCost;\n\n    // Hill-climbing on selection\n    XorShift rng(\n        (uint64_t)chrono::high_resolution_clock::now()\n            .time_since_epoch().count()\n    );\n\n    auto startTime = chrono::steady_clock::now();\n    const double TIME_LIMIT = 1.85; // seconds\n\n    int iter = 0;\n    while (true) {\n        ++iter;\n        // Time check every iteration (TSP is relatively expensive anyway)\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - startTime).count();\n        if (elapsed > TIME_LIMIT) break;\n\n        // Pick a random order to remove\n        int posOut = rng.next_uint(M);\n        int outIdx = currentSel[posOut];\n\n        // Pick a random order to insert (not in currentSel)\n        int inIdx;\n        do {\n            inIdx = rng.next_uint(N);\n        } while (inCurrent[inIdx]);\n\n        vector<int> candidateSel = currentSel;\n        candidateSel[posOut] = inIdx;\n\n        int candCost = evaluate_selection(candidateSel, a, b, c, d, tmpRtour, tmpDtour);\n\n        // Greedy acceptance\n        if (candCost <= currentCost) {\n            // Update current selection\n            currentSel.swap(candidateSel);\n            currentCost = candCost;\n            inCurrent[outIdx] = 0;\n            inCurrent[inIdx] = 1;\n        }\n\n        // Track global best\n        if (candCost < bestCost) {\n            bestCost = candCost;\n            bestSel = candidateSel;\n            bestRtour = tmpRtour;\n            bestDtour = tmpDtour;\n        }\n    }\n\n    // Build final path coordinates from bestSel + best tours\n    // bestRtour / bestDtour: node indices 0..M, starting and ending at 0.\n    // Node 0: office, node k>0: order bestSel[k-1].\n    vector<pair<int,int>> path;\n    path.reserve(1 + (int)bestRtour.size() - 1 + (int)bestDtour.size() - 1);\n\n    // Start at office\n    path.emplace_back(OFFICE_X, OFFICE_Y);\n\n    // Restaurants phase\n    for (int i = 1; i < (int)bestRtour.size(); ++i) {\n        int node = bestRtour[i];\n        if (node == 0) {\n            path.emplace_back(OFFICE_X, OFFICE_Y);\n        } else {\n            int orderIdx = bestSel[node - 1];\n            path.emplace_back(a[orderIdx], b[orderIdx]);\n        }\n    }\n\n    // Destinations phase\n    for (int i = 1; i < (int)bestDtour.size(); ++i) {\n        int node = bestDtour[i];\n        if (node == 0) {\n            path.emplace_back(OFFICE_X, OFFICE_Y);\n        } else {\n            int orderIdx = bestSel[node - 1];\n            path.emplace_back(c[orderIdx], d[orderIdx]);\n        }\n    }\n\n    // Output\n    // First line: m and chosen order indices (1-based)\n    cout << M;\n    for (int i = 0; i < M; ++i) {\n        cout << ' ' << (bestSel[i] + 1);\n    }\n    cout << '\\n';\n\n    // Second line: n and route coordinates\n    int n = (int)path.size();\n    cout << n;\n    for (int i = 0; i < n; ++i) {\n        cout << ' ' << path[i].first << ' ' << path[i].second;\n    }\n    cout << '\\n';\n\n    return 0;\n}","ahc007":"#include <bits/stdc++.h>\nusing namespace std;\n\n// ---------- DSU (Union-Find) ----------\nstruct DSU {\n    int n;\n    vector<int> p, r;\n    DSU() {}\n    DSU(int n_) { init(n_); }\n    void init(int n_) {\n        n = n_;\n        p.resize(n);\n        r.assign(n, 0);\n        iota(p.begin(), p.end(), 0);\n    }\n    int find(int x) {\n        if (p[x] == x) return x;\n        return p[x] = find(p[x]);\n    }\n    bool same(int a, int b) {\n        return find(a) == find(b);\n    }\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\n// ---------- XorShift RNG ----------\nstruct XorShift {\n    uint32_t x = 123456789u;\n    uint32_t y = 362436069u;\n    uint32_t z = 521288629u;\n    uint32_t w = 88675123u;\n    uint32_t next() {\n        uint32_t t = x ^ (x << 11);\n        x = y; y = z; z = w;\n        w = w ^ (w >> 19) ^ (t ^ (t >> 8));\n        return w;\n    }\n    uint32_t nextUInt(uint32_t bound) {\n        return next() % bound;\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    const int N = 400;\n    const int M = 1995;\n\n    // ----- Read coordinates -----\n    vector<int> x(N), y(N);\n    for (int i = 0; i < N; i++) {\n        if (!(cin >> x[i] >> y[i])) return 0;\n    }\n\n    // ----- Read edges -----\n    vector<int> u(M), v(M);\n    for (int i = 0; i < M; i++) {\n        cin >> u[i] >> v[i];\n    }\n\n    // ----- Precompute geometric distances d_i -----\n    vector<int> d(M);\n    for (int i = 0; i < M; i++) {\n        int dx = x[u[i]] - x[v[i]];\n        int dy = y[u[i]] - y[v[i]];\n        double dist = sqrt((double)dx * dx + (double)dy * dy);\n        d[i] = (int)llround(dist);\n    }\n\n    // ----- Compute geometric MST T on d_i -----\n    vector<int> idx(M);\n    iota(idx.begin(), idx.end(), 0);\n    sort(idx.begin(), idx.end(), [&](int a, int b) {\n        if (d[a] != d[b]) return d[a] < d[b];\n        return a < b;\n    });\n\n    vector<char> inTree(M, false);\n    DSU dsu0(N);\n    int used = 0;\n    for (int id : idx) {\n        if (!dsu0.same(u[id], v[id])) {\n            dsu0.unite(u[id], v[id]);\n            inTree[id] = true;\n            used++;\n            if (used == N - 1) break;\n        }\n    }\n\n    // ----- Build adjacency of MST T -----\n    vector<vector<pair<int,int>>> adj(N);\n    for (int i = 0; i < M; i++) {\n        if (!inTree[i]) continue;\n        adj[u[i]].push_back({v[i], d[i]});\n        adj[v[i]].push_back({u[i], d[i]});\n    }\n\n    // ----- LCA precomputation for max edge on path in T -----\n    const int LOG = 9; // 2^9 = 512 > 400\n    vector<int> depth(N, 0);\n    vector<vector<int>> par(LOG, vector<int>(N));\n    vector<vector<int>> mx(LOG, vector<int>(N));\n\n    {\n        queue<int> q;\n        vector<char> vis(N, false);\n        int root = 0;\n        vis[root] = true;\n        depth[root] = 0;\n        par[0][root] = root;\n        mx[0][root] = 0;\n        q.push(root);\n        while (!q.empty()) {\n            int cur = q.front(); q.pop();\n            for (auto [to, w] : adj[cur]) {\n                if (!vis[to]) {\n                    vis[to] = true;\n                    depth[to] = depth[cur] + 1;\n                    par[0][to] = cur;\n                    mx[0][to] = w;\n                    q.push(to);\n                }\n            }\n        }\n        for (int k = 1; k < LOG; k++) {\n            for (int vtx = 0; vtx < N; vtx++) {\n                int p = par[k-1][vtx];\n                par[k][vtx] = par[k-1][p];\n                mx[k][vtx] = max(mx[k-1][vtx], mx[k-1][p]);\n            }\n        }\n    }\n\n    auto getMaxOnPath = [&](int a, int b) -> int {\n        if (a == b) return 0;\n        int res = 0;\n        if (depth[a] < depth[b]) swap(a, b);\n        int diff = depth[a] - depth[b];\n        for (int k = 0; k < LOG; k++) {\n            if (diff & (1 << k)) {\n                res = max(res, mx[k][a]);\n                a = par[k][a];\n            }\n        }\n        if (a == b) return res;\n        for (int k = LOG - 1; k >= 0; k--) {\n            if (par[k][a] != par[k][b]) {\n                res = max(res, mx[k][a]);\n                res = max(res, mx[k][b]);\n                a = par[k][a];\n                b = par[k][b];\n            }\n        }\n        res = max(res, mx[0][a]);\n        res = max(res, mx[0][b]);\n        return res;\n    };\n\n    // ----- Compute H[i] for non-tree edges: max d on path in T between u[i], v[i] -----\n    vector<int> H(M, 0);\n    for (int i = 0; i < M; i++) {\n        if (inTree[i]) continue;\n        H[i] = getMaxOnPath(u[i], v[i]);\n        if (H[i] == 0) H[i] = d[i]; // safety\n    }\n\n    // ----- Monte Carlo: approximate selection probability in MST under true distribution -----\n    XorShift rng;\n    const int S = 700;  // number of simulations\n    vector<int> importance(M, 0);\n    vector<int> perm(M);\n    vector<int> sampleLen(M);\n\n    for (int s = 0; s < S; s++) {\n        for (int i = 0; i < M; i++) {\n            // length in [d[i], 3*d[i]]\n            uint32_t range = (uint32_t)(2 * d[i] + 1); // 3d - d + 1\n            sampleLen[i] = d[i] + (int)rng.nextUInt(range);\n            perm[i] = i;\n        }\n        sort(perm.begin(), perm.end(), [&](int a, int b) {\n            if (sampleLen[a] != sampleLen[b]) return sampleLen[a] < sampleLen[b];\n            return a < b;\n        });\n        DSU dsu(N);\n        int cnt = 0;\n        for (int eid : perm) {\n            if (!dsu.same(u[eid], v[eid])) {\n                dsu.unite(u[eid], v[eid]);\n                importance[eid]++;\n                cnt++;\n                if (cnt == N - 1) break;\n            }\n        }\n    }\n\n    // ----- Compute per-edge score and alpha (for non-tree edges) -----\n    vector<double> alpha(M, 1.0);\n    vector<double> score(M, 0.0);\n    double sMax = 0.0;\n\n    for (int i = 0; i < M; i++) {\n        if (inTree[i]) continue; // only non-tree edges use alpha\n        double pNorm = (double)importance[i] / (double)S; // 0..1\n        int Hi = H[i];\n        if (Hi <= 0) Hi = d[i];\n        double r = (double)d[i] / (double)Hi; // >=1\n        if (r < 1.0) r = 1.0;\n        if (r > 3.0) r = 3.0;\n        double ratioScore = (3.0 - r) / 2.0; // r=1 ->1, r=3 ->0\n        double comb = 0.7 * pNorm + 0.3 * ratioScore;\n        if (comb < 0.0) comb = 0.0;\n        score[i] = comb;\n        if (comb > sMax) sMax = comb;\n    }\n    if (sMax < 1e-9) sMax = 1.0; // avoid division by zero\n\n    const double alphaMin = 1.05;\n    const double alphaMax = 2.30;\n\n    for (int i = 0; i < M; i++) {\n        if (inTree[i]) continue;\n        double t = score[i] / sMax;  // 0..1\n        if (t < 0.0) t = 0.0;\n        if (t > 1.0) t = 1.0;\n        double a = alphaMin + t * (alphaMax - alphaMin);\n        if (a < 1.0) a = 1.0;\n        if (a > 3.0) a = 3.0;\n        alpha[i] = a;\n    }\n\n    // ----- Online phase -----\n    DSU dsuCur(N);\n\n    for (int i = 0; i < M; i++) {\n        long long l;\n        if (!(cin >> l)) return 0;\n\n        bool take = false;\n\n        if (!dsuCur.same(u[i], v[i])) {\n            if (inTree[i]) {\n                // Tree edge: always accept when it connects different components\n                take = true;\n            } else {\n                double a = alpha[i];\n                if (a <= 0.0) a = 1.0;\n                double thr = a * (double)d[i];\n                double maxPossible = 3.0 * (double)d[i];\n                if (thr > maxPossible) thr = maxPossible;\n                if ((double)l <= thr + 1e-9) {\n                    take = true;\n                }\n            }\n        } else {\n            take = false; // would form a cycle\n        }\n\n        if (take) {\n            dsuCur.unite(u[i], v[i]);\n        }\n\n        cout << (take ? 1 : 0) << '\\n';\n        cout.flush();\n    }\n\n    return 0;\n}","ahc008":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Pet {\n    int x, y, t;\n};\n\nstruct Human {\n    int x, y;\n};\n\nstatic const int H = 30;\nstatic const int W = 30;\n\nbool inside(int x, int y) {\n    return 1 <= x && x <= H && 1 <= y && y <= W;\n}\n\n// Check whether we are allowed to place a wall at (x,y)\nbool canWallCell(int x, int y,\n                 const vector<Pet> &pets,\n                 const vector<Human> &humans) {\n    if (!inside(x, y)) return false;\n    // Cannot place on a human\n    for (const auto &h : humans) {\n        if (h.x == x && h.y == y) return false;\n    }\n    // Cannot place on or adjacent (4-neighbor) to a pet\n    for (const auto &p : pets) {\n        int dx = abs(p.x - x);\n        int dy = abs(p.y - y);\n        if (dx + dy == 0) return false; // same cell\n        if (dx + dy == 1) return false; // 4-neighbor\n    }\n    return true;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    if (!(cin >> N)) {\n        return 0;\n    }\n    vector<Pet> pets(N);\n    for (int i = 0; i < N; i++) {\n        cin >> pets[i].x >> pets[i].y >> pets[i].t;\n    }\n    int M;\n    cin >> M;\n    vector<Human> humans(M);\n    for (int i = 0; i < M; i++) {\n        cin >> humans[i].x >> humans[i].y;\n    }\n\n    // Grid of walls: true means impassable\n    static bool wall[H + 1][W + 1];\n    for (int i = 1; i <= H; i++) {\n        for (int j = 1; j <= W; j++) wall[i][j] = false;\n    }\n\n    // We will build a vertical wall at column WALL_COL\n    const int WALL_COL = 16; // 1-indexed\n    const int WALK_COL = 17; // walkway column for the builder (to the right of the wall)\n    const int builder = 0;   // index of the builder human\n\n    // Row completion tracking for the wall\n    vector<bool> rowWalled(H + 1, false);\n    int walledCount = 0;\n\n    const int T_PRE = 50; // preparation phase duration\n\n    for (int turn = 0; turn < 300; turn++) {\n        string actions(M, '.');\n\n        // Decide actions for humans\n        if (M > 0) {\n            Human &hb = humans[builder];\n            int hx = hb.x;\n            int hy = hb.y;\n\n            char act = '.';\n\n            if (turn < T_PRE) {\n                // Preparation: move builder horizontally to walkway column\n                if (hy < WALK_COL) act = 'R';\n                else if (hy > WALK_COL) act = 'L';\n                else act = '.';\n            } else {\n                // Building phase\n                if (hy != WALK_COL) {\n                    // Ensure builder is on walkway column\n                    if (hy < WALK_COL) act = 'R';\n                    else if (hy > WALK_COL) act = 'L';\n                } else {\n                    // On walkway column; move up/down and place walls\n                    if (walledCount >= H) {\n                        act = '.';\n                    } else {\n                        // Determine if we can wall at current row\n                        bool thisRowUnwalled = !rowWalled[hx];\n\n                        bool canWallHere = false;\n                        if (thisRowUnwalled && !wall[hx][WALL_COL]) {\n                            if (canWallCell(hx, WALL_COL, pets, humans)) {\n                                canWallHere = true;\n                            }\n                        }\n                        if (thisRowUnwalled && canWallHere) {\n                            // Place wall to the left from (hx, WALK_COL) to (hx, WALL_COL)\n                            act = (WALK_COL > WALL_COL ? 'l' : 'r');\n                            wall[hx][WALL_COL] = true;\n                            rowWalled[hx] = true;\n                            walledCount++;\n                        } else {\n                            // Move to nearest other row that still needs a wall\n                            int bestRow = -1;\n                            int bestDist = INT_MAX;\n                            for (int r = 1; r <= H; r++) {\n                                if (!rowWalled[r] && r != hx) {\n                                    int d = abs(r - hx);\n                                    if (d < bestDist) {\n                                        bestDist = d;\n                                        bestRow = r;\n                                    }\n                                }\n                            }\n                            if (bestRow != -1) {\n                                if (bestRow > hx) act = 'D';\n                                else act = 'U';\n                            } else {\n                                // This row is the only remaining one; wait until it becomes safe\n                                act = '.';\n                            }\n                        }\n                    }\n                }\n            }\n            actions[builder] = act;\n        }\n\n        // Other humans\n        for (int i = 0; i < M; i++) {\n            if (i == builder) continue;\n            Human &h = humans[i];\n            char act = '.';\n            if (turn < T_PRE) {\n                // Move off the wall column if initially on it\n                if (h.y == WALL_COL) {\n                    // Simple: move left (safe, because WALL_COL=16, so >=2)\n                    act = 'L';\n                }\n            } else {\n                act = '.';\n            }\n            actions[i] = act;\n        }\n\n        // Output actions and flush\n        cout << actions << '\\n' << flush;\n\n        // Apply wall placements\n        for (int i = 0; i < M; i++) {\n            char c = actions[i];\n            if (c == 'u' || c == 'd' || c == 'l' || c == 'r') {\n                int x = humans[i].x;\n                int y = humans[i].y;\n                int nx = x, ny = y;\n                if (c == 'u') nx = x - 1;\n                else if (c == 'd') nx = x + 1;\n                else if (c == 'l') ny = y - 1;\n                else if (c == 'r') ny = y + 1;\n                if (inside(nx, ny)) {\n                    wall[nx][ny] = true;\n                }\n            }\n        }\n\n        // Apply human moves\n        for (int i = 0; i < M; i++) {\n            char c = actions[i];\n            if (c == 'U' || c == 'D' || c == 'L' || c == 'R') {\n                int x = humans[i].x;\n                int y = humans[i].y;\n                int nx = x, ny = y;\n                if (c == 'U') nx = x - 1;\n                else if (c == 'D') nx = x + 1;\n                else if (c == 'L') ny = y - 1;\n                else if (c == 'R') ny = y + 1;\n                if (inside(nx, ny) && !wall[nx][ny]) {\n                    humans[i].x = nx;\n                    humans[i].y = ny;\n                }\n            }\n        }\n\n        // Read pets' moves\n        vector<string> pmoves(N);\n        for (int i = 0; i < N; i++) {\n            cin >> pmoves[i];\n        }\n\n        // Apply pets' moves\n        for (int i = 0; i < N; i++) {\n            for (char c : pmoves[i]) {\n                int x = pets[i].x;\n                int y = pets[i].y;\n                int nx = x, ny = y;\n                if (c == 'U') nx = x - 1;\n                else if (c == 'D') nx = x + 1;\n                else if (c == 'L') ny = y - 1;\n                else if (c == 'R') ny = y + 1;\n                if (inside(nx, ny) && !wall[nx][ny]) {\n                    pets[i].x = nx;\n                    pets[i].y = ny;\n                } else {\n                    // According to rules, pets won't try to move into walls,\n                    // but we keep this check for safety.\n                }\n            }\n        }\n    }\n\n    return 0;\n}","ahc009":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const int H = 20;\nstatic const int W = 20;\nstatic const int N = H * W;\nstatic const int MAXL = 200;\n\n// DP arrays: time t (0..L) and cell id (0..N-1)\nstatic double alpha_dp[MAXL + 1][N];\nstatic double beta_dp [MAXL + 1][N];\nstatic double prefix_score[MAXL + 1];\n\n// Direction mapping\nint dirIdx[256];\nchar dirChar[4] = {'U', 'D', 'L', 'R'};\n\n// Precomputed next cell for each dir and cell\nint nextCell[4][N];\n\n// Globals\nint start_id, goal_id;\nint L = MAXL;\ndouble forget_p;\n\n// RNG for randomized BFS and hill-climb order\nmt19937 rng(1234567);\n\n// Build adjacency list (undirected) from wall information\nvector<vector<int>> build_graph(const vector<string> &h, const vector<string> &v) {\n    vector<vector<int>> g(N);\n    auto cell_id = [](int r, int c) { return r * W + c; };\n\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            int id = cell_id(i, j);\n            if (j + 1 < W && h[i][j] == '0') {\n                int nid = cell_id(i, j + 1);\n                g[id].push_back(nid);\n                g[nid].push_back(id);\n            }\n            if (i + 1 < H && v[i][j] == '0') {\n                int nid = cell_id(i + 1, j);\n                g[id].push_back(nid);\n                g[nid].push_back(id);\n            }\n        }\n    }\n    return g;\n}\n\n// Decode direction from cell 'from' to cell 'to'\nchar decode_dir(int from, int to) {\n    int r1 = from / W, c1 = from % W;\n    int r2 = to   / W, c2 = to   % W;\n    if (r2 == r1 && c2 == c1 + 1) return 'R';\n    if (r2 == r1 && c2 == c1 - 1) return 'L';\n    if (r2 == r1 + 1 && c2 == c1) return 'D';\n    if (r2 == r1 - 1 && c2 == c1) return 'U';\n    // Should not happen in a grid graph\n    return 'U';\n}\n\n// Randomized BFS shortest path using a shuffled adjacency list\nvector<char> bfs_shortest_path_rand(const vector<vector<int>> &g) {\n    vector<vector<int>> g2 = g;\n    for (int u = 0; u < N; ++u) {\n        shuffle(g2[u].begin(), g2[u].end(), rng);\n    }\n\n    vector<int> prev(N, -1);\n    queue<int> q;\n    q.push(start_id);\n    prev[start_id] = start_id;\n\n    while (!q.empty()) {\n        int vtx = q.front(); q.pop();\n        if (vtx == goal_id) break;\n        for (int to : g2[vtx]) {\n            if (prev[to] == -1) {\n                prev[to] = vtx;\n                q.push(to);\n            }\n        }\n    }\n\n    vector<char> path;\n    int cur = goal_id;\n    if (prev[cur] == -1) {\n        // Should not happen due to connectivity, but fallback\n        path.push_back('R');\n        return path;\n    }\n    while (cur != start_id) {\n        int p = prev[cur];\n        path.push_back(decode_dir(p, cur));\n        cur = p;\n    }\n    reverse(path.begin(), path.end());\n    if (path.empty()) path.push_back('R'); // extremely unlikely\n    return path;\n}\n\n// Build a simple \"goal loop\" pattern: for each accessible neighbor of goal,\n// move there and back.\nvector<char> build_goal_loop_pattern() {\n    vector<char> pattern;\n    auto rev_dir = [](char c) {\n        if (c == 'U') return 'D';\n        if (c == 'D') return 'U';\n        if (c == 'L') return 'R';\n        return 'L';  // c == 'R'\n    };\n\n    for (char c : {'U', 'D', 'L', 'R'}) {\n        int d = dirIdx[(unsigned char)c];\n        int dest = nextCell[d][goal_id];\n        if (dest != goal_id) {\n            pattern.push_back(c);\n            pattern.push_back(rev_dir(c));\n        }\n    }\n\n    if (pattern.empty()) {\n        // Should not happen, but safeguard\n        pattern.push_back('U');\n        pattern.push_back('D');\n    }\n    return pattern;\n}\n\n// Evaluate a full route s[1..L]; also fills alpha_dp, beta_dp, prefix_score.\ndouble evaluate_route(const vector<char> &s) {\n    const double p = forget_p;\n    const double q = 1.0 - p;\n\n    // Forward DP: alpha_dp and prefix_score\n    memset(alpha_dp, 0, sizeof(alpha_dp));\n    alpha_dp[0][start_id] = 1.0;\n    prefix_score[0] = 0.0;\n\n    for (int t = 1; t <= L; ++t) {\n        memset(alpha_dp[t], 0, sizeof(alpha_dp[t]));\n        prefix_score[t] = prefix_score[t - 1];\n        int d = dirIdx[(unsigned char)s[t]];\n        double reward_weight = 401.0 - t;\n\n        for (int id = 0; id < N; ++id) {\n            double px = alpha_dp[t - 1][id];\n            if (px == 0.0) continue;\n\n            if (id == goal_id) {\n                // Already at goal: stay\n                alpha_dp[t][id] += px;\n                continue;\n            }\n\n            int dest = nextCell[d][id];\n\n            if (dest == id) {\n                // Blocked by wall/boundary: stay\n                alpha_dp[t][id] += px;\n            } else if (dest == goal_id) {\n                // Might reach goal\n                double moved = px * q;\n                prefix_score[t] += moved * reward_weight;\n                alpha_dp[t][goal_id] += moved;\n                alpha_dp[t][id] += px * p;  // forgetting -> stay\n            } else {\n                // Normal move\n                double moved = px * q;\n                alpha_dp[t][dest] += moved;\n                alpha_dp[t][id]   += px * p;\n            }\n        }\n    }\n\n    double total_score = prefix_score[L];\n\n    // Backward DP: beta_dp\n    memset(beta_dp, 0, sizeof(beta_dp));\n    for (int id = 0; id < N; ++id) beta_dp[L][id] = 0.0;\n\n    for (int t = L - 1; t >= 0; --t) {\n        int d = dirIdx[(unsigned char)s[t + 1]];\n        double reward_weight = 401.0 - (t + 1);\n\n        for (int id = 0; id < N; ++id) {\n            if (id == goal_id) {\n                beta_dp[t][id] = 0.0;\n                continue;\n            }\n            int dest = nextCell[d][id];\n            double immediate = 0.0;\n            double future = 0.0;\n\n            if (dest == id) {\n                // Blocked: always stay\n                future = beta_dp[t + 1][id];\n            } else if (dest == goal_id) {\n                // May reach goal\n                immediate = q * reward_weight;\n                future = p * beta_dp[t + 1][id];\n            } else {\n                future = q * beta_dp[t + 1][dest] + p * beta_dp[t + 1][id];\n            }\n            beta_dp[t][id] = immediate + future;\n        }\n    }\n\n    return total_score;\n}\n\n// Compute E[S] if only step k is changed to newDir (keeping others fixed),\n// using current alpha_dp, beta_dp, prefix_score from the current route.\ndouble score_if_change_step(const vector<char> &s, int k, char newDir) {\n    const double p = forget_p;\n    const double q = 1.0 - p;\n\n    double res = prefix_score[k - 1];\n    int d = dirIdx[(unsigned char)newDir];\n\n    for (int id = 0; id < N; ++id) {\n        double px = alpha_dp[k - 1][id];\n        if (px == 0.0) continue;\n        if (id == goal_id) {\n            // Already at goal\n            continue;\n        }\n        int dest = nextCell[d][id];\n        if (dest == id) {\n            // No move\n            res += px * beta_dp[k][id];\n        } else if (dest == goal_id) {\n            // Reach goal with prob q\n            res += px * q * (401.0 - k);\n            res += px * p * beta_dp[k][id];\n        } else {\n            res += px * (q * beta_dp[k][dest] + p * beta_dp[k][id]);\n        }\n    }\n    return res;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int si, sj, ti, tj;\n    if (!(cin >> si >> sj >> ti >> tj >> forget_p)) {\n        return 0;\n    }\n    vector<string> h(H), v(H - 1);\n    for (int i = 0; i < H; ++i) cin >> h[i];\n    for (int i = 0; i < H - 1; ++i) cin >> v[i];\n\n    start_id = si * W + sj;\n    goal_id  = ti * W + tj;\n\n    // Direction indices\n    dirIdx['U'] = 0;\n    dirIdx['D'] = 1;\n    dirIdx['L'] = 2;\n    dirIdx['R'] = 3;\n\n    // Precompute nextCell for each dir and cell\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            int id = i * W + j;\n            // Up\n            if (i == 0 || v[i - 1][j] == '1') nextCell[0][id] = id;\n            else                              nextCell[0][id] = (i - 1) * W + j;\n            // Down\n            if (i == H - 1 || v[i][j] == '1') nextCell[1][id] = id;\n            else                               nextCell[1][id] = (i + 1) * W + j;\n            // Left\n            if (j == 0 || h[i][j - 1] == '1') nextCell[2][id] = id;\n            else                              nextCell[2][id] = i * W + (j - 1);\n            // Right\n            if (j == W - 1 || h[i][j] == '1') nextCell[3][id] = id;\n            else                              nextCell[3][id] = i * W + (j + 1);\n        }\n    }\n\n    // Build adjacency for BFS\n    vector<vector<int>> graph = build_graph(h, v);\n\n    // Build goal-loop pattern\n    vector<char> goal_pattern = build_goal_loop_pattern();\n    int goal_pat_len = (int)goal_pattern.size();\n\n    // Generate multiple base BFS paths\n    const int BFS_COUNT = 3;\n    vector<vector<char>> basePaths;\n    basePaths.reserve(BFS_COUNT);\n    for (int b = 0; b < BFS_COUNT; ++b) {\n        basePaths.push_back(bfs_shortest_path_rand(graph));\n    }\n\n    // Build candidate routes and pick the best by DP\n    vector<char> bestRoute(L + 1);\n    double bestScore = -1.0;\n\n    for (const auto &path_raw : basePaths) {\n        vector<char> path = path_raw;\n        if (path.empty()) path.push_back('R');\n        int D = (int)path.size();\n        if (D > L) D = L; // in practice unlikely, but just in case\n\n        // Candidate type 0: repeat BFS path\n        {\n            vector<char> route(L + 1);\n            for (int t = 1; t <= L; ++t) {\n                route[t] = path[(t - 1) % D];\n            }\n            double sc = evaluate_route(route);\n            if (sc > bestScore) {\n                bestScore = sc;\n                bestRoute = route;\n            }\n        }\n\n        // Candidate type 1: BFS once, then goal-loop pattern\n        {\n            vector<char> route(L + 1);\n            for (int t = 1; t <= L; ++t) {\n                if (t <= D) {\n                    route[t] = path[t - 1];\n                } else {\n                    route[t] = goal_pattern[(t - D - 1) % goal_pat_len];\n                }\n            }\n            double sc = evaluate_route(route);\n            if (sc > bestScore) {\n                bestScore = sc;\n                bestRoute = route;\n            }\n        }\n    }\n\n    // Re-evaluate bestRoute so that alpha_dp, beta_dp, prefix_score match it\n    bestScore = evaluate_route(bestRoute);\n    vector<char> route = bestRoute;\n\n    // Hill-climbing: DP-based coordinate descent, random step order\n    const int MAX_ITER = 5;\n    const double EPS = 1e-9;\n\n    vector<int> order(L);\n    for (int i = 0; i < L; ++i) order[i] = i + 1;\n\n    for (int iter = 0; iter < MAX_ITER; ++iter) {\n        bool improved_any = false;\n        shuffle(order.begin(), order.end(), rng);\n\n        for (int idx = 0; idx < L; ++idx) {\n            int k = order[idx];\n            char orig = route[k];\n            char bestDir = orig;\n            double currScore = bestScore;\n\n            // Try all 3 alternative directions\n            for (int di = 0; di < 4; ++di) {\n                char c = dirChar[di];\n                if (c == orig) continue;\n                double newScore = score_if_change_step(route, k, c);\n                if (newScore > currScore + EPS) {\n                    currScore = newScore;\n                    bestDir = c;\n                }\n            }\n\n            if (bestDir != orig) {\n                route[k] = bestDir;\n                bestScore = evaluate_route(route);\n                improved_any = true;\n            }\n        }\n\n        if (!improved_any) break;\n    }\n\n    // Output final route as a string\n    string out;\n    out.reserve(L);\n    for (int t = 1; t <= L; ++t) out.push_back(route[t]);\n    cout << out << '\\n';\n\n    return 0;\n}","ahc010":"#include <bits/stdc++.h>\nusing namespace std;\n\nconstexpr int N = 30;\nconstexpr int M = 30;\nconstexpr int TOT_STATES = N * M * 4;\n\n// Input and current board\nint baseTile[N][M];   // initial tile types from input\nint curTile[N][M];    // current effective tile type (0..7) after rotation\nint curRot[N][M];     // current rotation count (0..3) for each tile\n\n// Best rotations found for final answer\nint bestRot[N][M];\n\n// Rotation table: rotTable[t][r] = tile type after rotating t by r times 90deg CCW\nint rotTable[8][4];\n\n// Rail mapping: toTbl[t][d] = exit direction when entering tile type t from direction d\nint toTbl[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// Whether side d of tile type t has a rail\nbool useSide[8][4];\n\n// For loop detection in computeTrueScore\nbool visitedState[TOT_STATES];\nint  pathId[TOT_STATES];\nint  pathStep[TOT_STATES];\n\nint di[4] = {0, -1, 0, 1};  // left, up, right, down\nint dj[4] = {-1, 0, 1, 0};\n\nmt19937_64 rng(20240131);\n\n// Encode (i, j, d) into a single index 0..3599\ninline int encodeState(int i, int j, int d) {\n    return ((i * M + j) << 2) | d;\n}\n\n// Compute local score = number of connected internal edges\nint computeLocalScore() {\n    int connected = 0;\n\n    // Horizontal internal edges: (i,j)-(i,j+1)\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < M - 1; ++j) {\n            int t1 = curTile[i][j];\n            int t2 = curTile[i][j + 1];\n            if (useSide[t1][2] && useSide[t2][0]) connected++;\n        }\n    }\n    // Vertical internal edges: (i,j)-(i+1,j)\n    for (int i = 0; i < N - 1; ++i) {\n        for (int j = 0; j < M; ++j) {\n            int t1 = curTile[i][j];\n            int t2 = curTile[i + 1][j];\n            if (useSide[t1][3] && useSide[t2][1]) connected++;\n        }\n    }\n    return connected;\n}\n\n// Incremental delta of local score when tile (i,j) type changes from oldT to newT\ninline int deltaLocalScoreTile(int i, int j, int oldT, int newT) {\n    int deltaConn = 0;\n\n    // Up neighbor\n    if (i > 0) {\n        int neighbor = curTile[i - 1][j];\n        bool neighborUsedDown = useSide[neighbor][3];\n        bool oldUsedUp = useSide[oldT][1];\n        bool newUsedUp = useSide[newT][1];\n        int before = (oldUsedUp && neighborUsedDown) ? 1 : 0;\n        int after  = (newUsedUp && neighborUsedDown) ? 1 : 0;\n        deltaConn += after - before;\n    }\n\n    // Down neighbor\n    if (i < N - 1) {\n        int neighbor = curTile[i + 1][j];\n        bool neighborUsedUp = useSide[neighbor][1];\n        bool oldUsedDown = useSide[oldT][3];\n        bool newUsedDown = useSide[newT][3];\n        int before = (oldUsedDown && neighborUsedUp) ? 1 : 0;\n        int after  = (newUsedDown && neighborUsedUp) ? 1 : 0;\n        deltaConn += after - before;\n    }\n\n    // Left neighbor\n    if (j > 0) {\n        int neighbor = curTile[i][j - 1];\n        bool neighborUsedRight = useSide[neighbor][2];\n        bool oldUsedLeft = useSide[oldT][0];\n        bool newUsedLeft = useSide[newT][0];\n        int before = (oldUsedLeft && neighborUsedRight) ? 1 : 0;\n        int after  = (newUsedLeft && neighborUsedRight) ? 1 : 0;\n        deltaConn += after - before;\n    }\n\n    // Right neighbor\n    if (j < M - 1) {\n        int neighbor = curTile[i][j + 1];\n        bool neighborUsedLeft = useSide[neighbor][0];\n        bool oldUsedRight = useSide[oldT][2];\n        bool newUsedRight = useSide[newT][2];\n        int before = (oldUsedRight && neighborUsedLeft) ? 1 : 0;\n        int after  = (newUsedRight && neighborUsedLeft) ? 1 : 0;\n        deltaConn += after - before;\n    }\n\n    return deltaConn;\n}\n\n// Compute true score = L1 * L2 (lengths of two longest loops)\nint computeTrueScore() {\n    // Reset visitation info\n    fill(visitedState, visitedState + TOT_STATES, false);\n    fill(pathId, pathId + TOT_STATES, 0);\n\n    int best1 = 0, best2 = 0;\n    int curPathId = 1;\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < M; ++j) {\n            int t = curTile[i][j];\n            for (int d = 0; d < 4; ++d) {\n                int idx0 = encodeState(i, j, d);\n                if (visitedState[idx0]) continue;\n                if (toTbl[t][d] == -1) {\n                    visitedState[idx0] = true;\n                    continue;\n                }\n\n                int x = i, y = j, dir = d;\n                int pathLen = 0;\n                ++curPathId;\n\n                while (true) {\n                    int idx = encodeState(x, y, dir);\n                    visitedState[idx] = true;\n                    pathId[idx] = curPathId;\n                    pathStep[idx] = pathLen;\n\n                    int tt = curTile[x][y];\n                    int d2 = toTbl[tt][dir];\n                    if (d2 == -1) break;\n\n                    int nx = x + di[d2];\n                    int ny = y + dj[d2];\n                    if (nx < 0 || nx >= N || ny < 0 || ny >= M) break;\n\n                    int nd = (d2 + 2) & 3;\n                    ++pathLen;\n                    int idxNext = encodeState(nx, ny, nd);\n\n                    if (pathId[idxNext] == curPathId) {\n                        // Found a cycle\n                        int len = pathLen - pathStep[idxNext];\n                        if (len >= best1) {\n                            best2 = best1;\n                            best1 = len;\n                        } else if (len > best2) {\n                            best2 = len;\n                        }\n                        break;\n                    }\n                    if (visitedState[idxNext]) {\n                        // Merges into a previously explored path/cycle\n                        break;\n                    }\n\n                    x = nx;\n                    y = ny;\n                    dir = nd;\n                }\n            }\n        }\n    }\n\n    if (best2 == 0) return 0;\n    return best1 * best2;\n}\n\ninline double randDouble() {\n    return (double)(rng() >> 11) * (1.0 / (1ULL << 53));\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // Precompute rotation table\n    int rotMap[8] = {1, 2, 3, 0, 5, 4, 7, 6};\n    for (int t = 0; t < 8; ++t) {\n        rotTable[t][0] = t;\n        for (int r = 1; r < 4; ++r) {\n            rotTable[t][r] = rotMap[ rotTable[t][r - 1] ];\n        }\n    }\n\n    // Precompute useSide\n    for (int t = 0; t < 8; ++t) {\n        for (int d = 0; d < 4; ++d) {\n            useSide[t][d] = (toTbl[t][d] != -1);\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 < M; ++j) {\n            baseTile[i][j] = s[j] - '0';\n        }\n    }\n\n    auto timeStart = chrono::steady_clock::now();\n    const double GLOBAL_TIME_LIMIT = 1.8;  // seconds, keep margin under 2.0\n\n    // ===== Stage 1: Multi-start greedy local search on local score =====\n    const int MAX_RUNS = 8;\n    const int MAX_PASS = 10;\n\n    vector<int> order(N * M);\n    iota(order.begin(), order.end(), 0);\n\n    int bestLocalScore = numeric_limits<int>::min();\n\n    for (int run = 0; run < MAX_RUNS; ++run) {\n        // Random initial rotations\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < M; ++j) {\n                int r = (int)(rng() & 3ULL);  // 0..3\n                curRot[i][j] = r;\n                curTile[i][j] = rotTable[ baseTile[i][j] ][r];\n            }\n        }\n\n        int curLocalScore = computeLocalScore();\n\n        for (int pass = 0; pass < MAX_PASS; ++pass) {\n            bool changed = false;\n            shuffle(order.begin(), order.end(), rng);\n\n            for (int idxCell : order) {\n                int i = idxCell / M;\n                int j = idxCell % M;\n\n                int oldRot = curRot[i][j];\n                int oldT = curTile[i][j];\n\n                int bestDelta = 0;\n                int bestR = oldRot;\n                int bestT = oldT;\n\n                // Try all 4 rotations\n                for (int r = 0; r < 4; ++r) {\n                    if (r == oldRot) continue;\n                    int newT = rotTable[ baseTile[i][j] ][r];\n                    if (newT == oldT) continue; // same effective type (for 4/5)\n                    int delta = deltaLocalScoreTile(i, j, oldT, newT);\n                    if (delta > bestDelta) {\n                        bestDelta = delta;\n                        bestR = r;\n                        bestT = newT;\n                    }\n                }\n\n                if (bestDelta > 0) {\n                    curRot[i][j] = bestR;\n                    curTile[i][j] = bestT;\n                    curLocalScore += bestDelta;\n                    changed = true;\n                }\n            }\n\n            if (!changed) break;\n        }\n\n        if (curLocalScore > bestLocalScore) {\n            bestLocalScore = curLocalScore;\n            for (int i = 0; i < N; ++i)\n                for (int j = 0; j < M; ++j)\n                    bestRot[i][j] = curRot[i][j];\n        }\n\n        double elapsed = chrono::duration<double>(chrono::steady_clock::now() - timeStart).count();\n        if (elapsed > GLOBAL_TIME_LIMIT * 0.3) {\n            // Keep enough time for Stage 2\n            break;\n        }\n    }\n\n    // Initialize curRot/curTile from best local configuration\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < M; ++j) {\n            curRot[i][j] = bestRot[i][j];\n            curTile[i][j] = rotTable[ baseTile[i][j] ][curRot[i][j]];\n        }\n    }\n\n    // ===== Stage 2: Simulated annealing on true score over all tiles =====\n    int curScore = computeTrueScore();\n    int bestScore = curScore;\n    // bestRot already holds current rotations\n\n    const double T0 = 1000.0;\n    const double T1 = 2.0;\n\n    while (true) {\n        double elapsed = chrono::duration<double>(chrono::steady_clock::now() - timeStart).count();\n        if (elapsed > GLOBAL_TIME_LIMIT) break;\n        double progress = elapsed / GLOBAL_TIME_LIMIT;\n        if (progress > 1.0) progress = 1.0;\n        double T = T0 + (T1 - T0) * progress;\n\n        // Random tile\n        int idxCell = (int)(rng() % (N * M));\n        int i = idxCell / M;\n        int j = idxCell % M;\n\n        int oldRot = curRot[i][j];\n        int oldT = curTile[i][j];\n\n        int newRot;\n        int newT;\n\n        // Propose a different effective tile type via rotation\n        // Keep sampling until new effective type differs from old\n        do {\n            newRot = (int)(rng() & 3ULL);\n            newT = rotTable[ baseTile[i][j] ][newRot];\n        } while (newT == oldT);\n\n        curRot[i][j] = newRot;\n        curTile[i][j] = newT;\n\n        int newScore = computeTrueScore();\n        int diff = newScore - curScore;\n\n        bool accept = false;\n        if (diff >= 0) {\n            accept = true;\n        } else {\n            double prob = exp((double)diff / T);\n            if (randDouble() < prob) accept = true;\n        }\n\n        if (accept) {\n            curScore = newScore;\n            if (newScore > bestScore) {\n                bestScore = newScore;\n                for (int x = 0; x < N; ++x)\n                    for (int y = 0; y < M; ++y)\n                        bestRot[x][y] = curRot[x][y];\n            }\n        } else {\n            // revert\n            curRot[i][j] = oldRot;\n            curTile[i][j] = oldT;\n        }\n    }\n\n    // ===== Output best rotations =====\n    string out;\n    out.reserve(N * M);\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < M; ++j) {\n            int r = bestRot[i][j] & 3;\n            out.push_back(char('0' + r));\n        }\n    }\n    cout << out << '\\n';\n\n    return 0;\n}","ahc011":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const int MAXN = 10;\n\nint N, T;\n\nstruct Board {\n    unsigned char a[MAXN][MAXN];\n};\n\n// Directions for graph connectivity (Up, Right, Down, Left)\nconst int DX[4]   = {-1, 0, 1, 0};\nconst int DY[4]   = { 0, 1, 0,-1};\n// Bit masks corresponding to U,R,D,L in that order\nconst int MASK[4] = {2, 4, 8, 1};\n// Opposite directions\nconst int OPP[4]  = {2, 3, 0, 1};\n\nstruct EvalRes {\n    int bestTree;    // size of largest tree component\n    int bestConn;    // size of largest connected component\n    int totalTree;   // sum of sizes of all tree components\n};\n\n// Evaluate the board: largest tree, largest connected component,\n// and total vertices in tree components\nEvalRes evaluate(const Board &B) {\n    static bool vis[MAXN][MAXN];\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            vis[i][j] = false;\n\n    int bestTree = 0;\n    int bestConn = 0;\n    int totalTree = 0;\n\n    int qx[MAXN * MAXN];\n    int qy[MAXN * MAXN];\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (B.a[i][j] == 0 || vis[i][j]) continue;\n\n            int v = 0; // vertices in this component\n            int e = 0; // edges in this component\n\n            int head = 0, tail = 0;\n            vis[i][j] = true;\n            qx[tail] = i;\n            qy[tail] = j;\n            ++tail;\n\n            while (head < tail) {\n                int x = qx[head];\n                int y = qy[head];\n                ++head;\n\n                ++v;\n                unsigned char tile = B.a[x][y];\n\n                for (int dir = 0; dir < 4; ++dir) {\n                    if (!(tile & MASK[dir])) continue;\n                    int nx = x + DX[dir];\n                    int ny = y + DY[dir];\n                    if (nx < 0 || nx >= N || ny < 0 || ny >= N) continue;\n                    unsigned char nt = B.a[nx][ny];\n                    if (nt == 0) continue;\n                    if (!(nt & MASK[OPP[dir]])) continue;\n\n                    if (!vis[nx][ny]) {\n                        vis[nx][ny] = true;\n                        qx[tail] = nx;\n                        qy[tail] = ny;\n                        ++tail;\n                    }\n                    // count each undirected edge once\n                    if (x < nx || (x == nx && y < ny)) {\n                        ++e;\n                    }\n                }\n            }\n\n            bestConn = max(bestConn, v);\n            if (e == v - 1) {\n                bestTree = max(bestTree, v);\n                totalTree += v;\n            }\n        }\n    }\n\n    return {bestTree, bestConn, totalTree};\n}\n\n// Convert EvalRes to a scalar score (lexicographic: bestTree > totalTree > bestConn)\ninline long long evalScore(const EvalRes &er) {\n    // With N <= 10, all components sizes <= 99.\n    // 1e6 weight ensures bestTree dominates totalTree (<= 99*1000) and bestConn.\n    return (long long)er.bestTree * 1000000LL\n         + (long long)er.totalTree * 1000LL\n         + (long long)er.bestConn;\n}\n\n// Comparison of two EvalRes according to the same lexicographic priority\ninline bool betterEval(const EvalRes &a, const EvalRes &b) {\n    if (a.bestTree != b.bestTree) return a.bestTree > b.bestTree;\n    if (a.totalTree != b.totalTree) return a.totalTree > b.totalTree;\n    if (a.bestConn != b.bestConn) return a.bestConn > b.bestConn;\n    return false;\n}\n\n// Sliding puzzle move legality\ninline bool legalMove(int r, int c, char mv) {\n    if (mv == 'U') return r > 0;\n    if (mv == 'D') return r + 1 < N;\n    if (mv == 'L') return c > 0;\n    if (mv == 'R') return c + 1 < N;\n    return false;\n}\n\n// Apply move to board and blank position\ninline void applyMove(Board &B, int &r, int &c, char mv) {\n    if (mv == 'U') {\n        swap(B.a[r][c], B.a[r-1][c]);\n        --r;\n    } else if (mv == 'D') {\n        swap(B.a[r][c], B.a[r+1][c]);\n        ++r;\n    } else if (mv == 'L') {\n        swap(B.a[r][c], B.a[r][c-1]);\n        --c;\n    } else if (mv == 'R') {\n        swap(B.a[r][c], B.a[r][c+1]);\n        ++c;\n    }\n}\n\n// Opposite sliding move\ninline char oppositeMove(char mv) {\n    if (mv == 'U') return 'D';\n    if (mv == 'D') return 'U';\n    if (mv == 'L') return 'R';\n    if (mv == 'R') return 'L';\n    return '?';\n}\n\n// Time control\nusing Clock = chrono::steady_clock;\ninline double nowSec(const Clock::time_point &start) {\n    return chrono::duration<double>(Clock::now() - start).count();\n}\n\n// Depth-limited DFS to find best reachable score within given depth\n// starting from board B and blank position (br, bc).\n// lastMove: last move applied to reach this state (to avoid immediate reverse),\n// depth: remaining depth to explore (0 means just evaluate this state).\n//\n// Note: depth here is number of **further** moves to simulate.\nlong long dfsScore(const Board &B, int br, int bc, char lastMove, int depth) {\n    EvalRes er = evaluate(B);\n    long long best = evalScore(er);\n    if (depth == 0) return best;\n\n    static const char allMoves[4] = {'U', 'D', 'L', 'R'};\n    char cand[4];\n    int cnt = 0;\n    for (int k = 0; k < 4; ++k) {\n        char mv = allMoves[k];\n        if (!legalMove(br, bc, mv)) continue;\n        if (lastMove != '?' && mv == oppositeMove(lastMove)) continue;\n        cand[cnt++] = mv;\n    }\n\n    for (int i = 0; i < cnt; ++i) {\n        char mv = cand[i];\n        Board nb = B;\n        int nbr = br, nbc = bc;\n        applyMove(nb, nbr, nbc, mv);\n        long long sc = dfsScore(nb, nbr, nbc, mv, depth - 1);\n        if (sc > best) best = sc;\n    }\n    return best;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    if (!(cin >> N >> T)) {\n        return 0;\n    }\n\n    Board initialBoard;\n    int initialBlankR = -1, initialBlankC = -1;\n\n    for (int i = 0; i < N; ++i) {\n        string row;\n        cin >> row;\n        for (int j = 0; j < N; ++j) {\n            char ch = row[j];\n            int val;\n            if ('0' <= ch && ch <= '9') val = ch - '0';\n            else val = ch - 'a' + 10;\n            initialBoard.a[i][j] = static_cast<unsigned char>(val);\n            if (val == 0) {\n                initialBlankR = i;\n                initialBlankC = j;\n            }\n        }\n    }\n\n    // RNG for tie-breaking\n    mt19937_64 rng(\n        (uint64_t)chrono::high_resolution_clock::now().time_since_epoch().count()\n    );\n\n    auto startTime = Clock::now();\n    const double TIME_LIMIT = 2.8; // seconds, safety margin under 3.0\n\n    EvalRes initialEval = evaluate(initialBoard);\n    EvalRes bestOverallEval = initialEval;\n    int bestOverallStep = 0;\n    string bestOverallOps;\n\n    int totalTiles = N * N - 1;\n\n    // If initial board is already a full tree, output empty sequence.\n    if (initialEval.bestTree == totalTiles) {\n        cout << \"\\n\";\n        return 0;\n    }\n\n    static const char allMoves[4] = {'U', 'D', 'L', 'R'};\n    const int MAX_RUNS = 100; // upper bound; actual runs limited by time\n    const int LOOKAHEAD_DEPTH = 3; // total lookahead moves (including first)\n\n    int run = 0;\n    while (run < MAX_RUNS && nowSec(startTime) < TIME_LIMIT) {\n        ++run;\n\n        Board board = initialBoard;\n        int blankR = initialBlankR;\n        int blankC = initialBlankC;\n\n        string ops;\n        ops.reserve(T);\n\n        EvalRes bestRunEval = initialEval;\n        int bestRunStep = 0;\n        char lastMove = '?';\n\n        for (int step = 0; step < T; ++step) {\n            if (nowSec(startTime) >= TIME_LIMIT) break;\n\n            // Build candidate first moves, avoiding immediate reverse if possible.\n            char cand1[4];\n            int cand1cnt = 0;\n            for (int k = 0; k < 4; ++k) {\n                char mv = allMoves[k];\n                if (!legalMove(blankR, blankC, mv)) continue;\n                if (step > 0 && mv == oppositeMove(lastMove)) continue;\n                cand1[cand1cnt++] = mv;\n            }\n            if (cand1cnt == 0) {\n                // All legal moves are reverse of last; allow them.\n                for (int k = 0; k < 4; ++k) {\n                    char mv = allMoves[k];\n                    if (legalMove(blankR, blankC, mv)) {\n                        cand1[cand1cnt++] = mv;\n                    }\n                }\n                if (cand1cnt == 0) break; // no legal moves (very unlikely)\n            }\n\n            long long bestScoreStep = LLONG_MIN;\n            char chosenMove = cand1[0];\n            int tieCount = 0;\n\n            // For each candidate first move, perform depth-limited search.\n            for (int idx = 0; idx < cand1cnt; ++idx) {\n                char d1 = cand1[idx];\n\n                Board b1 = board;\n                int br1 = blankR, bc1 = blankC;\n                applyMove(b1, br1, bc1, d1);\n\n                // We already performed one move (d1); explore up to LOOKAHEAD_DEPTH-1 more.\n                long long sc = dfsScore(b1, br1, bc1, d1, LOOKAHEAD_DEPTH - 1);\n\n                if (sc > bestScoreStep) {\n                    bestScoreStep = sc;\n                    chosenMove = d1;\n                    tieCount = 1;\n                } else if (sc == bestScoreStep) {\n                    ++tieCount;\n                    if (rng() % tieCount == 0) {\n                        chosenMove = d1;\n                    }\n                }\n            }\n\n            // Commit chosen move\n            applyMove(board, blankR, blankC, chosenMove);\n            ops.push_back(chosenMove);\n            lastMove = chosenMove;\n\n            // Evaluate current board and update run-best prefix\n            EvalRes curEval = evaluate(board);\n            if (betterEval(curEval, bestRunEval)) {\n                bestRunEval = curEval;\n                bestRunStep = (int)ops.size();\n                if (bestRunEval.bestTree == totalTiles) {\n                    // Found a full tree; no need to continue this run.\n                    break;\n                }\n            }\n        }\n\n        // Update global best over all runs\n        if (betterEval(bestRunEval, bestOverallEval)) {\n            bestOverallEval = bestRunEval;\n            bestOverallStep = bestRunStep;\n            bestOverallOps = ops.substr(0, bestRunStep);\n            if (bestOverallEval.bestTree == totalTiles) {\n                // Reached optimal S; further improvements only affect K,\n                // but when S < N^2-1 score ignores K, so we can stop.\n                break;\n            }\n        }\n    }\n\n    if (bestOverallStep == 0) {\n        // best is initial board\n        cout << \"\\n\";\n    } else {\n        cout << bestOverallOps << \"\\n\";\n    }\n\n    return 0;\n}","ahc012":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const int RADIUS = 10000;   // radius of the cake\nstatic const int BIG = 100000;     // endpoints far enough to cross the cake\n\n// Build quantile-based cut positions along one axis.\n//\n// Npoints: number of strawberries\n// Nc: desired number of cuts along this axis\n// sortedCoord: sorted coordinates (x or y) of all strawberries (size Npoints)\n// boundaryCoord: precomputed boundary coordinate for each boundary index 0..Npoints\n// boundaryValid: whether boundary 0..Npoints can be used without hitting any strawberry\n//\n// If we can't pick Nc valid boundaries, we fall back to uniform spacing.\nvector<int> build_quantile_cuts(\n    int Npoints,\n    int Nc,\n    const vector<int> &sortedCoord,\n    const vector<int> &boundaryCoord,\n    const vector<char> &boundaryValid\n) {\n    vector<int> cuts;\n    if (Nc <= 0) return cuts;\n\n    // Count how many valid boundaries we have\n    int validCount = 0;\n    for (int b = 0; b <= Npoints; ++b) {\n        if (boundaryValid[b]) ++validCount;\n    }\n\n    // If not enough valid boundaries, fall back to uniform spacing\n    if (validCount <= Nc) {\n        // Uniform spacing in [-RADIUS, RADIUS]\n        cuts.reserve(Nc);\n        for (int i = 1; i <= Nc; ++i) {\n            long long num = 2LL * RADIUS * i;\n            int c = -RADIUS + (int)(num / (Nc + 1)); // floor\n            cuts.push_back(c);\n        }\n        return cuts;\n    }\n\n    cuts.reserve(Nc);\n    int prevB = -1;\n    bool success = true;\n    for (int i = 1; i <= Nc; ++i) {\n        long long target = 1LL * i * Npoints / (Nc + 1); // in [0, Npoints]\n        int bestB = -1;\n        long long bestDist = (1LL << 60);\n\n        // Choose next valid boundary index b > prevB minimizing |b - target|\n        for (int b = prevB + 1; b <= Npoints; ++b) {\n            if (!boundaryValid[b]) continue;\n            long long dist = llabs((long long)b - target);\n            if (dist < bestDist) {\n                bestDist = dist;\n                bestB = b;\n            }\n        }\n        if (bestB == -1) {\n            success = false;\n            break;\n        }\n        prevB = bestB;\n        cuts.push_back(boundaryCoord[bestB]);\n    }\n\n    if (!success || (int)cuts.size() != Nc) {\n        // Fallback: uniform spacing\n        cuts.clear();\n        cuts.reserve(Nc);\n        for (int i = 1; i <= Nc; ++i) {\n            long long num = 2LL * RADIUS * i;\n            int c = -RADIUS + (int)(num / (Nc + 1)); // floor\n            cuts.push_back(c);\n        }\n    }\n\n    return cuts;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, K;\n    if (!(cin >> N >> K)) return 0;\n    vector<int> a(11);\n    long long sumA = 0;\n    for (int d = 1; d <= 10; ++d) {\n        cin >> a[d];\n        sumA += a[d];\n    }\n    vector<pair<int,int>> pts(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> pts[i].first >> pts[i].second;\n    }\n\n    if (sumA == 0 || K == 0) {\n        cout << 0 << '\\n';\n        return 0;\n    }\n\n    // Compute average desired piece size\n    double avgD = (double)N / (double)sumA;\n\n    // Use a simple Poisson-fit to attendee distribution to tweak target lambda.\n    vector<double> w(11, 0.0);\n    for (int d = 1; d <= 10; ++d) {\n        w[d] = (double)a[d] / (double)sumA;\n    }\n\n    double bestLambda = avgD;\n    double bestErr = 1e100;\n\n    // Search lambda in [1.0, 8.0] with step 0.1\n    for (double lambda = 1.0; lambda <= 8.0001; lambda += 0.1) {\n        double P[11];\n        P[0] = exp(-lambda);\n        double sum1to10 = 0.0;\n        for (int k = 1; k <= 10; ++k) {\n            P[k] = P[k-1] * lambda / k;\n            sum1to10 += P[k];\n        }\n        if (sum1to10 <= 0.0) continue;\n        double err = 0.0;\n        for (int d = 1; d <= 10; ++d) {\n            double q = P[d] / sum1to10; // distribution restricted to sizes 1..10\n            double diff = q - w[d];\n            err += diff * diff;\n        }\n        if (err < bestErr) {\n            bestErr = err;\n            bestLambda = lambda;\n        }\n    }\n\n    // Blend avgD and bestLambda, then clamp to [2, 8]\n    double lambdaTarget = 0.5 * avgD + 0.5 * bestLambda;\n    lambdaTarget = max(2.0, min(8.0, lambdaTarget));\n\n    // Target number of cells\n    int cellsTarget = (int)llround((double)N / lambdaTarget);\n    if (cellsTarget < 1) cellsTarget = 1;\n\n    // Maximum cells achievable with at most K lines (axis-aligned grid)\n    long long maxCellsPossible = 0;\n    for (int Nx = 0; Nx <= K; ++Nx) {\n        int Ny = K - Nx;\n        long long cells = 1LL * (Nx + 1) * (Ny + 1);\n        if (cells > maxCellsPossible) maxCellsPossible = cells;\n    }\n    if (cellsTarget > (int)maxCellsPossible) cellsTarget = (int)maxCellsPossible;\n\n    // Choose Nx, Ny to make (Nx+1)*(Ny+1) close to cellsTarget, preferring square-like grids\n    int bestNx = 0, bestNy = 0;\n    long long bestCellErr = (1LL << 60);\n    int bestSquarePenalty = (1 << 30);\n    for (int Nx = 0; Nx <= K; ++Nx) {\n        for (int Ny = 0; Ny <= K - Nx; ++Ny) {\n            long long cells = 1LL * (Nx + 1) * (Ny + 1);\n            long long err = llabs(cells - (long long)cellsTarget);\n            int squarePenalty = abs(Nx - Ny);\n            if (err < bestCellErr ||\n                (err == bestCellErr && squarePenalty < bestSquarePenalty)) {\n                bestCellErr = err;\n                bestSquarePenalty = squarePenalty;\n                bestNx = Nx;\n                bestNy = Ny;\n            }\n        }\n    }\n\n    int Nx = bestNx;\n    int Ny = bestNy;\n\n    // Prepare sorted x and y coordinates and boundary info\n    vector<int> xs(N), ys(N);\n    for (int i = 0; i < N; ++i) {\n        xs[i] = pts[i].first;\n        ys[i] = pts[i].second;\n    }\n    sort(xs.begin(), xs.end());\n    sort(ys.begin(), ys.end());\n\n    // X boundaries: indices 0..N\n    // boundary 0: before xs[0], at xs[0]-1 (>= -RADIUS)\n    // boundary N: after xs[N-1], at xs[N-1]+1 (<= RADIUS)\n    // internal b: between xs[b-1] and xs[b]; valid if gap >= 2, coord = floor((xs[b-1]+xs[b])/2)\n    vector<int> xBoundaryCoord(N + 1);\n    vector<char> xBoundaryValid(N + 1, 0);\n    if (N > 0) {\n        // boundary 0\n        int c0 = xs[0] - 1;\n        if (c0 < -RADIUS) c0 = -RADIUS; // should be exactly -RADIUS only if xs[0]==-9999\n        xBoundaryCoord[0] = c0;\n        xBoundaryValid[0] = 1;  // safe: no strawberry has x == c0\n\n        // internal boundaries\n        for (int b = 1; b <= N - 1; ++b) {\n            int left = xs[b-1];\n            int right = xs[b];\n            if (right - left >= 2) {\n                int c = (left + right) / 2; // strictly between left and right\n                xBoundaryCoord[b] = c;\n                xBoundaryValid[b] = 1;\n            } else {\n                xBoundaryValid[b] = 0;\n            }\n        }\n\n        // boundary N\n        int cN = xs[N-1] + 1;\n        if (cN > RADIUS) cN = RADIUS;\n        xBoundaryCoord[N] = cN;\n        xBoundaryValid[N] = 1; // safe: no strawberry has x == cN\n    }\n\n    // Y boundaries: similar\n    vector<int> yBoundaryCoord(N + 1);\n    vector<char> yBoundaryValid(N + 1, 0);\n    if (N > 0) {\n        int c0 = ys[0] - 1;\n        if (c0 < -RADIUS) c0 = -RADIUS;\n        yBoundaryCoord[0] = c0;\n        yBoundaryValid[0] = 1;\n\n        for (int b = 1; b <= N - 1; ++b) {\n            int down = ys[b-1];\n            int up   = ys[b];\n            if (up - down >= 2) {\n                int c = (down + up) / 2;\n                yBoundaryCoord[b] = c;\n                yBoundaryValid[b] = 1;\n            } else {\n                yBoundaryValid[b] = 0;\n            }\n        }\n\n        int cN = ys[N-1] + 1;\n        if (cN > RADIUS) cN = RADIUS;\n        yBoundaryCoord[N] = cN;\n        yBoundaryValid[N] = 1;\n    }\n\n    // Build quantile-based vertical and horizontal cuts\n    vector<int> xCuts = build_quantile_cuts(N, Nx, xs, xBoundaryCoord, xBoundaryValid);\n    vector<int> yCuts = build_quantile_cuts(N, Ny, ys, yBoundaryCoord, yBoundaryValid);\n\n    int totalCuts = (int)xCuts.size() + (int)yCuts.size();\n    if (totalCuts > K) {\n        // Should not happen, but guard just in case\n        // Trim extra horizontal cuts first\n        int excess = totalCuts - K;\n        while (excess > 0 && !yCuts.empty()) {\n            yCuts.pop_back();\n            --excess;\n        }\n        while (excess > 0 && !xCuts.empty()) {\n            xCuts.pop_back();\n            --excess;\n        }\n        totalCuts = (int)xCuts.size() + (int)yCuts.size();\n    }\n\n    cout << totalCuts << '\\n';\n\n    // Output vertical cuts: x = c\n    for (int c : xCuts) {\n        int px = c, py = -BIG;\n        int qx = c, qy =  BIG;\n        cout << px << ' ' << py << ' ' << qx << ' ' << qy << '\\n';\n    }\n    // Output horizontal cuts: y = c\n    for (int c : yCuts) {\n        int px = -BIG, py = c;\n        int qx =  BIG, qy = c;\n        cout << px << ' ' << py << ' ' << qx << ' ' << qy << '\\n';\n    }\n\n    return 0;\n}","ahc014":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int MAXN = 65;  // N <= 61\n\nint N, M;\n\n// Board state\nstatic bool hasDot[MAXN][MAXN];      // [x][y]\nstatic bool horUsed[MAXN][MAXN];     // [y][x] edge from (x,y) to (x+1,y)\nstatic bool verUsed[MAXN][MAXN];     // [x][y] edge from (x,y) to (x,y+1)\nstatic bool diagUpUsed[MAXN][MAXN];  // [x][y] edge from (x,y) to (x+1,y+1)\nstatic bool diagDownUsed[MAXN][MAXN];// [x][y] edge from (x,y+1) to (x+1,y)\n\nstatic int rowPrefix[MAXN][MAXN+1];  // [y][i]: dots with x < i\nstatic int colPrefix[MAXN][MAXN+1];  // [x][i]: dots with y < i\nstatic int cellWeight[MAXN][MAXN];   // w(x,y)\n\nconstexpr uint8_t TYPE_AXIS = 0;\nconstexpr uint8_t TYPE_ROT  = 1;\n\n// Candidate rectangle\nstruct Candidate {\n    int weight;\n    uint8_t type;    // 0: axis-aligned, 1: rotated (45\u00b0 square)\n    uint8_t px, py;  // new dot position\n    uint8_t pad;     // padding/alignment\n    union {\n        struct { uint8_t xL, yB, xR, yT; } axis;\n        struct {\n            uint8_t vx[4];  // vertices in cyclic order (Up, Right, Down, Left)\n            uint8_t vy[4];\n        } rot;\n    } u;\n};\n\nbool operator<(const Candidate &a, const Candidate &b) {\n    // priority_queue is max-heap by default; larger weight first\n    return a.weight < b.weight;\n}\n\npriority_queue<Candidate> pq;\n\n// Move record\nstruct Move {\n    int x1, y1, x2, y2, x3, y3, x4, y4;\n};\n\n// Add a dot at (x,y): update hasDot and 1D prefix sums\ninline void addDot(int x, int y) {\n    if (hasDot[x][y]) return;\n    hasDot[x][y] = true;\n    for (int i = x + 1; i <= N; ++i) rowPrefix[y][i] += 1;\n    for (int i = y + 1; i <= N; ++i) colPrefix[x][i] += 1;\n}\n\n// Generate all axis-aligned rectangles where the newly added dot is a vertex\n// and exactly three corners have dots (so the fourth is a candidate new dot).\ninline void updateAxisForNewDot(int x, int y) {\n    for (int x2 = 0; x2 < N; ++x2) {\n        if (x2 == x) continue;\n        int xL = (x2 < x) ? x2 : x;\n        int xR = (x2 < x) ? x : x2;\n        for (int y2 = 0; y2 < N; ++y2) {\n            if (y2 == y) continue;\n            int yB = (y2 < y) ? y2 : y;\n            int yT = (y2 < y) ? y : y2;\n\n            bool BL = hasDot[xL][yB];\n            bool BR = hasDot[xR][yB];\n            bool TR = hasDot[xR][yT];\n            bool TL = hasDot[xL][yT];\n            int cnt = BL + BR + TR + TL;\n            if (cnt != 3) continue;\n\n            int px, py;\n            if (!BL) { px = xL; py = yB; }\n            else if (!BR) { px = xR; py = yB; }\n            else if (!TR) { px = xR; py = yT; }\n            else { px = xL; py = yT; }\n\n            Candidate c;\n            c.weight = cellWeight[px][py];\n            c.type   = TYPE_AXIS;\n            c.px = (uint8_t)px;\n            c.py = (uint8_t)py;\n            c.pad = 0;\n            c.u.axis.xL = (uint8_t)xL;\n            c.u.axis.yB = (uint8_t)yB;\n            c.u.axis.xR = (uint8_t)xR;\n            c.u.axis.yT = (uint8_t)yT;\n            pq.push(c);\n        }\n    }\n}\n\n// Generate rotated (45\u00b0) square rectangles for a newly added dot at (x,y).\n// We consider squares whose vertices are Up, Right, Down, Left around an\n// integer center, and treat (x,y) as each of these four roles in turn.\ninline void updateRotatedForNewDot(int x, int y) {\n    // Orientation 0: new dot is Up\n    {\n        // Up = (x, y)\n        for (int k = 1;; ++k) {\n            int rx = x + k;\n            int ry = y - k;\n            int dx = x;\n            int dy = y - 2 * k;\n            int lx = x - k;\n            int ly = y - k;\n            if (rx >= N || lx < 0 || dy < 0) break;\n\n            int vx[4] = {x, rx, dx, lx};\n            int vy[4] = {y, ry, dy, ly};\n            bool s[4];\n            s[0] = true; // new dot at Up\n            s[1] = hasDot[rx][ry];\n            s[2] = hasDot[dx][dy];\n            s[3] = hasDot[lx][ly];\n\n            int cnt = 0;\n            for (int i = 0; i < 4; ++i) cnt += s[i];\n            if (cnt != 3) continue;\n\n            int miss = -1;\n            for (int i = 0; i < 4; ++i) if (!s[i]) { miss = i; break; }\n            int px = vx[miss], py = vy[miss];\n\n            Candidate c;\n            c.weight = cellWeight[px][py];\n            c.type   = TYPE_ROT;\n            c.px = (uint8_t)px;\n            c.py = (uint8_t)py;\n            c.pad = 0;\n            for (int i = 0; i < 4; ++i) {\n                c.u.rot.vx[i] = (uint8_t)vx[i];\n                c.u.rot.vy[i] = (uint8_t)vy[i];\n            }\n            pq.push(c);\n        }\n    }\n    // Orientation 1: new dot is Right\n    {\n        // Right = (x, y)\n        for (int k = 1;; ++k) {\n            int ux = x - k;\n            int uy = y + k;\n            int dx = x - k;\n            int dy = y - k;\n            int lx = x - 2 * k;\n            int ly = y;\n            if (lx < 0 || ux < 0 || uy >= N || dy < 0) break;\n\n            int vx[4] = {ux, x, dx, lx};\n            int vy[4] = {uy, y, dy, ly};\n            bool s[4];\n            s[1] = true; // new dot at Right\n            s[0] = hasDot[ux][uy];\n            s[2] = hasDot[dx][dy];\n            s[3] = hasDot[lx][ly];\n\n            int cnt = 0;\n            for (int i = 0; i < 4; ++i) cnt += s[i];\n            if (cnt != 3) continue;\n\n            int miss = -1;\n            for (int i = 0; i < 4; ++i) if (!s[i]) { miss = i; break; }\n            int px = vx[miss], py = vy[miss];\n\n            Candidate c;\n            c.weight = cellWeight[px][py];\n            c.type   = TYPE_ROT;\n            c.px = (uint8_t)px;\n            c.py = (uint8_t)py;\n            c.pad = 0;\n            for (int i = 0; i < 4; ++i) {\n                c.u.rot.vx[i] = (uint8_t)vx[i];\n                c.u.rot.vy[i] = (uint8_t)vy[i];\n            }\n            pq.push(c);\n        }\n    }\n    // Orientation 2: new dot is Down\n    {\n        // Down = (x, y)\n        for (int k = 1;; ++k) {\n            int ux = x;\n            int uy = y + 2 * k;\n            int rx = x + k;\n            int ry = y + k;\n            int lx = x - k;\n            int ly = y + k;\n            if (uy >= N || rx >= N || lx < 0) break;\n\n            int vx[4] = {ux, rx, x, lx};\n            int vy[4] = {uy, ry, y, ly};\n            bool s[4];\n            s[2] = true; // new dot at Down\n            s[0] = hasDot[ux][uy];\n            s[1] = hasDot[rx][ry];\n            s[3] = hasDot[lx][ly];\n\n            int cnt = 0;\n            for (int i = 0; i < 4; ++i) cnt += s[i];\n            if (cnt != 3) continue;\n\n            int miss = -1;\n            for (int i = 0; i < 4; ++i) if (!s[i]) { miss = i; break; }\n            int px = vx[miss], py = vy[miss];\n\n            Candidate c;\n            c.weight = cellWeight[px][py];\n            c.type   = TYPE_ROT;\n            c.px = (uint8_t)px;\n            c.py = (uint8_t)py;\n            c.pad = 0;\n            for (int i = 0; i < 4; ++i) {\n                c.u.rot.vx[i] = (uint8_t)vx[i];\n                c.u.rot.vy[i] = (uint8_t)vy[i];\n            }\n            pq.push(c);\n        }\n    }\n    // Orientation 3: new dot is Left\n    {\n        // Left = (x, y)\n        for (int k = 1;; ++k) {\n            int ux = x + k;\n            int uy = y + k;\n            int rx = x + 2 * k;\n            int ry = y;\n            int dx = x + k;\n            int dy = y - k;\n            if (rx >= N || uy >= N || dy < 0) break;\n\n            int vx[4] = {ux, rx, dx, x};\n            int vy[4] = {uy, ry, dy, y};\n            bool s[4];\n            s[3] = true; // new dot at Left\n            s[0] = hasDot[ux][uy];\n            s[1] = hasDot[rx][ry];\n            s[2] = hasDot[dx][dy];\n\n            int cnt = 0;\n            for (int i = 0; i < 4; ++i) cnt += s[i];\n            if (cnt != 3) continue;\n\n            int miss = -1;\n            for (int i = 0; i < 4; ++i) if (!s[i]) { miss = i; break; }\n            int px = vx[miss], py = vy[miss];\n\n            Candidate c;\n            c.weight = cellWeight[px][py];\n            c.type   = TYPE_ROT;\n            c.px = (uint8_t)px;\n            c.py = (uint8_t)py;\n            c.pad = 0;\n            for (int i = 0; i < 4; ++i) {\n                c.u.rot.vx[i] = (uint8_t)vx[i];\n                c.u.rot.vy[i] = (uint8_t)vy[i];\n            }\n            pq.push(c);\n        }\n    }\n}\n\n// Validate an axis-aligned candidate rectangle\ninline bool validateAxis(const Candidate &c) {\n    int px = c.px, py = c.py;\n    if (hasDot[px][py]) return false;\n\n    const auto &ax = c.u.axis;\n    int xL = ax.xL, xR = ax.xR;\n    int yB = ax.yB, yT = ax.yT;\n\n    bool isCorner =\n        (px == xL && py == yB) ||\n        (px == xR && py == yB) ||\n        (px == xR && py == yT) ||\n        (px == xL && py == yT);\n    if (!isCorner) return false;\n\n    if (!(px == xL && py == yB) && !hasDot[xL][yB]) return false;\n    if (!(px == xR && py == yB) && !hasDot[xR][yB]) return false;\n    if (!(px == xR && py == yT) && !hasDot[xR][yT]) return false;\n    if (!(px == xL && py == yT) && !hasDot[xL][yT]) return false;\n\n    // No extra dots on perimeter interior (horizontal/vertical edges)\n    if (xR - xL > 1) {\n        int sumBottom = rowPrefix[yB][xR] - rowPrefix[yB][xL + 1];\n        if (sumBottom > 0) return false;\n        int sumTop = rowPrefix[yT][xR] - rowPrefix[yT][xL + 1];\n        if (sumTop > 0) return false;\n    }\n    if (yT - yB > 1) {\n        int sumLeft  = colPrefix[xL][yT] - colPrefix[xL][yB + 1];\n        if (sumLeft > 0) return false;\n        int sumRight = colPrefix[xR][yT] - colPrefix[xR][yB + 1];\n        if (sumRight > 0) return false;\n    }\n\n    // No edges already used\n    for (int x = xL; x < xR; ++x) {\n        if (horUsed[yB][x]) return false;\n        if (horUsed[yT][x]) return false;\n    }\n    for (int y = yB; y < yT; ++y) {\n        if (verUsed[xL][y]) return false;\n        if (verUsed[xR][y]) return false;\n    }\n\n    return true;\n}\n\n// Mark edges of an axis-aligned rectangle as used\ninline void markEdgesAxis(const Candidate &c) {\n    const auto &ax = c.u.axis;\n    int xL = ax.xL, xR = ax.xR;\n    int yB = ax.yB, yT = ax.yT;\n    for (int x = xL; x < xR; ++x) {\n        horUsed[yB][x] = true;\n        horUsed[yT][x] = true;\n    }\n    for (int y = yB; y < yT; ++y) {\n        verUsed[xL][y] = true;\n        verUsed[xR][y] = true;\n    }\n}\n\n// Validate a rotated (45\u00b0 square) candidate rectangle\ninline bool validateRot(const Candidate &c) {\n    int px = c.px, py = c.py;\n    if (hasDot[px][py]) return false;\n\n    const auto &rt = c.u.rot;\n\n    // New point must be one of the four vertices\n    int idx = -1;\n    for (int i = 0; i < 4; ++i) {\n        if (rt.vx[i] == px && rt.vy[i] == py) {\n            idx = i;\n            break;\n        }\n    }\n    if (idx == -1) return false;\n\n    // Other three vertices must currently have dots\n    for (int i = 0; i < 4; ++i) {\n        if (i == idx) continue;\n        int vx = rt.vx[i], vy = rt.vy[i];\n        if (!hasDot[vx][vy]) return false;\n    }\n\n    // Check edges: no extra dots on interior points and no used diagonal segments\n    for (int e = 0; e < 4; ++e) {\n        int x1 = rt.vx[e];\n        int y1 = rt.vy[e];\n        int x2 = rt.vx[(e + 1) & 3];\n        int y2 = rt.vy[(e + 1) & 3];\n\n        int dx = x2 - x1;\n        int dy = y2 - y1;\n        int steps = abs(dx);\n        if (steps == 0) return false; // degenerate, shouldn't happen\n\n        int sxStep = (dx > 0) ? 1 : -1;\n        int syStep = (dy > 0) ? 1 : -1;\n\n        // Interior dots\n        for (int i = 1; i < steps; ++i) {\n            int qx = x1 + sxStep * i;\n            int qy = y1 + syStep * i;\n            if (hasDot[qx][qy]) return false;\n        }\n\n        bool slopeUp = ((long long)dx * dy > 0); // slope +1 if dx,dy same sign\n        if (slopeUp) {\n            int sx = min(x1, x2);\n            int sy = min(y1, y2);\n            for (int i = 0; i < steps; ++i) {\n                if (diagUpUsed[sx + i][sy + i]) return false;\n            }\n        } else {\n            int sx = min(x1, x2);\n            int sy = max(y1, y2);\n            for (int i = 0; i < steps; ++i) {\n                int bx = sx + i;\n                int by = sy - 1 - i; // segment from (bx,by+1) to (bx+1,by)\n                if (diagDownUsed[bx][by]) return false;\n            }\n        }\n    }\n\n    return true;\n}\n\n// Mark edges of a rotated (45\u00b0 square) rectangle as used\ninline void markEdgesRot(const Candidate &c) {\n    const auto &rt = c.u.rot;\n\n    for (int e = 0; e < 4; ++e) {\n        int x1 = rt.vx[e];\n        int y1 = rt.vy[e];\n        int x2 = rt.vx[(e + 1) & 3];\n        int y2 = rt.vy[(e + 1) & 3];\n\n        int dx = x2 - x1;\n        int dy = y2 - y1;\n        int steps = abs(dx);\n        bool slopeUp = ((long long)dx * dy > 0);\n\n        if (slopeUp) {\n            int sx = min(x1, x2);\n            int sy = min(y1, y2);\n            for (int i = 0; i < steps; ++i) {\n                diagUpUsed[sx + i][sy + i] = true;\n            }\n        } else {\n            int sx = min(x1, x2);\n            int sy = max(y1, y2);\n            for (int i = 0; i < steps; ++i) {\n                int bx = sx + i;\n                int by = sy - 1 - i;\n                diagDownUsed[bx][by] = true;\n            }\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> M;\n    vector<pair<int,int>> initial(M);\n    for (int i = 0; i < M; ++i) {\n        int x, y;\n        cin >> x >> y;\n        initial[i] = {x, y};\n    }\n\n    // Precompute weights\n    int c = (N - 1) / 2;\n    for (int x = 0; x < N; ++x) {\n        for (int y = 0; y < N; ++y) {\n            int dx = x - c;\n            int dy = y - c;\n            cellWeight[x][y] = dx * dx + dy * dy + 1;\n        }\n    }\n\n    // Add initial dots and generate initial candidates\n    for (int i = 0; i < M; ++i) {\n        int x = initial[i].first;\n        int y = initial[i].second;\n        addDot(x, y);\n        updateAxisForNewDot(x, y);\n        updateRotatedForNewDot(x, y);\n    }\n\n    vector<Move> moves;\n\n    auto start_time = chrono::steady_clock::now();\n    const double TIME_LIMIT = 4.8; // safety margin\n\n    int iter = 0;\n    while (!pq.empty()) {\n        if ((iter & 0xFF) == 0) {\n            auto now = chrono::steady_clock::now();\n            double elapsed = chrono::duration<double>(now - start_time).count();\n            if (elapsed > TIME_LIMIT) break;\n        }\n        ++iter;\n\n        Candidate cand = pq.top();\n        pq.pop();\n\n        if (cand.type == TYPE_AXIS) {\n            if (!validateAxis(cand)) continue;\n\n            // Commit axis-aligned rectangle\n            markEdgesAxis(cand);\n            int px = cand.px;\n            int py = cand.py;\n            addDot(px, py);\n            updateAxisForNewDot(px, py);\n            updateRotatedForNewDot(px, py);\n\n            const auto &ax = cand.u.axis;\n            int xL = ax.xL, xR = ax.xR;\n            int yB = ax.yB, yT = ax.yT;\n\n            int ax0 = xL, ay0 = yB;\n            int bx0 = xR, by0 = yB;\n            int cx0 = xR, cy0 = yT;\n            int dx0 = xL, dy0 = yT;\n\n            Move m;\n            if (px == ax0 && py == ay0) {\n                m = {ax0, ay0, bx0, by0, cx0, cy0, dx0, dy0};\n            } else if (px == bx0 && py == by0) {\n                m = {bx0, by0, cx0, cy0, dx0, dy0, ax0, ay0};\n            } else if (px == cx0 && py == cy0) {\n                m = {cx0, cy0, dx0, dy0, ax0, ay0, bx0, by0};\n            } else {\n                m = {dx0, dy0, ax0, ay0, bx0, by0, cx0, cy0};\n            }\n            moves.push_back(m);\n\n        } else { // TYPE_ROT\n            if (!validateRot(cand)) continue;\n\n            // Commit rotated rectangle\n            markEdgesRot(cand);\n            int px = cand.px;\n            int py = cand.py;\n            addDot(px, py);\n            updateAxisForNewDot(px, py);\n            updateRotatedForNewDot(px, py);\n\n            const auto &rt = cand.u.rot;\n            int idx = 0;\n            for (; idx < 4; ++idx) {\n                if (rt.vx[idx] == px && rt.vy[idx] == py) break;\n            }\n            if (idx == 4) idx = 0; // fallback, shouldn't happen\n\n            int x1 = rt.vx[idx],           y1 = rt.vy[idx];\n            int x2 = rt.vx[(idx + 1) & 3], y2 = rt.vy[(idx + 1) & 3];\n            int x3 = rt.vx[(idx + 2) & 3], y3 = rt.vy[(idx + 2) & 3];\n            int x4 = rt.vx[(idx + 3) & 3], y4 = rt.vy[(idx + 3) & 3];\n            moves.push_back({x1, y1, x2, y2, x3, y3, x4, y4});\n        }\n    }\n\n    // Output\n    cout << moves.size() << '\\n';\n    for (const auto &m : moves) {\n        cout << m.x1 << ' ' << m.y1 << ' '\n             << m.x2 << ' ' << m.y2 << ' '\n             << m.x3 << ' ' << m.y3 << ' '\n             << m.x4 << ' ' << m.y4 << '\\n';\n    }\n\n    return 0;\n}","ahc015":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const int N = 10;\nstatic const int MONTE_K = 4; // number of Monte Carlo samples for lookahead\n\nstruct Board {\n    int a[N][N];\n    Board() { memset(a, 0, sizeof(a)); }\n};\n\n// Tilt directions: 0 = F, 1 = B, 2 = L, 3 = R\nvoid tilt(Board &b, int dir) {\n    if (dir == 0) { // F: move toward row 0\n        for (int c = 0; c < N; c++) {\n            int pos = 0;\n            for (int r = 0; r < N; r++) {\n                if (b.a[r][c]) {\n                    if (pos != r) b.a[pos][c] = b.a[r][c];\n                    pos++;\n                }\n            }\n            for (int r = pos; r < N; r++) b.a[r][c] = 0;\n        }\n    } else if (dir == 1) { // B: move toward row 9\n        for (int c = 0; c < N; c++) {\n            int pos = N - 1;\n            for (int r = N - 1; r >= 0; r--) {\n                if (b.a[r][c]) {\n                    if (pos != r) b.a[pos][c] = b.a[r][c];\n                    pos--;\n                }\n            }\n            for (int r = pos; r >= 0; r--) b.a[r][c] = 0;\n        }\n    } else if (dir == 2) { // L: move toward col 0\n        for (int r = 0; r < N; r++) {\n            int pos = 0;\n            for (int c = 0; c < N; c++) {\n                if (b.a[r][c]) {\n                    if (pos != c) b.a[r][pos] = b.a[r][c];\n                    pos++;\n                }\n            }\n            for (int c = pos; c < N; c++) b.a[r][c] = 0;\n        }\n    } else { // R: move toward col 9\n        for (int r = 0; r < N; r++) {\n            int pos = N - 1;\n            for (int c = N - 1; c >= 0; c--) {\n                if (b.a[r][c]) {\n                    if (pos != c) b.a[r][pos] = b.a[r][c];\n                    pos--;\n                }\n            }\n            for (int c = pos; c >= 0; c--) b.a[r][c] = 0;\n        }\n    }\n}\n\n// Sum of squared sizes of same-color connected components (4-neighbor)\nlong long evaluate(const Board &b) {\n    bool vis[N][N] = {};\n    static const int dr[4] = {1, -1, 0, 0};\n    static const int dc[4] = {0, 0, 1, -1};\n    int qx[100], qy[100];\n    long long score = 0;\n\n    for (int r = 0; r < N; r++) {\n        for (int c = 0; c < N; c++) {\n            if (b.a[r][c] != 0 && !vis[r][c]) {\n                int color = b.a[r][c];\n                int head = 0, tail = 0;\n                qx[tail] = r;\n                qy[tail] = c;\n                tail++;\n                vis[r][c] = true;\n                int cnt = 0;\n                while (head < tail) {\n                    int x = qx[head];\n                    int y = qy[head];\n                    head++;\n                    cnt++;\n                    for (int k = 0; k < 4; k++) {\n                        int nx = x + dr[k];\n                        int ny = y + dc[k];\n                        if (0 <= nx && nx < N && 0 <= ny && ny < N &&\n                            !vis[nx][ny] && b.a[nx][ny] == color) {\n                            vis[nx][ny] = true;\n                            qx[tail] = nx;\n                            qy[tail] = ny;\n                            tail++;\n                        }\n                    }\n                }\n                score += 1LL * cnt * cnt;\n            }\n        }\n    }\n    return score;\n}\n\n// Find p-th empty cell (1-based) in front-to-back, left-to-right order\npair<int,int> findPos(const Board &b, int p) {\n    int cnt = 0;\n    for (int r = 0; r < N; r++) {\n        for (int c = 0; c < N; c++) {\n            if (b.a[r][c] == 0) {\n                cnt++;\n                if (cnt == p) return {r, c};\n            }\n        }\n    }\n    return {-1, -1}; // should not happen\n}\n\n// Choose a random empty cell uniformly from current board\npair<int,int> randomEmptyCell(const Board &b, mt19937_64 &rng) {\n    int empties = 0;\n    for (int r = 0; r < N; r++) {\n        for (int c = 0; c < N; c++) {\n            if (b.a[r][c] == 0) empties++;\n        }\n    }\n    // Should never be called with empties == 0\n    uint64_t x = rng();\n    int k = (int)(x % empties); // 0..empties-1\n    int cnt = 0;\n    for (int r = 0; r < N; r++) {\n        for (int c = 0; c < N; c++) {\n            if (b.a[r][c] == 0) {\n                if (cnt == k) return {r, c};\n                cnt++;\n            }\n        }\n    }\n    return {0, 0}; // fallback, should not occur\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // Read flavor sequence\n    vector<int> f(100);\n    for (int i = 0; i < 100; i++) {\n        if (!(cin >> f[i])) return 0;\n    }\n\n    Board cur;\n    const char DIR_CH[4] = {'F', 'B', 'L', 'R'};\n    mt19937_64 rng(712367821ull); // fixed seed for deterministic behavior\n\n    for (int t = 0; t < 100; t++) {\n        int p;\n        if (!(cin >> p)) return 0;\n\n        // Place current candy\n        auto [r, c] = findPos(cur, p);\n        if (r == -1) return 0; // safety\n        cur.a[r][c] = f[t];\n\n        long long bestScore = LLONG_MIN;\n        int bestDir = 0;\n        Board bestBoard;\n\n        for (int dir0 = 0; dir0 < 4; dir0++) {\n            Board b1 = cur;\n            tilt(b1, dir0);\n            long long S0 = evaluate(b1);\n            long long scoreValue;\n\n            if (t <= 98) { // we can look one step ahead using f[t+1]\n                long long futureSum = 0;\n                int nextColor = f[t + 1];\n\n                for (int s = 0; s < MONTE_K; s++) {\n                    Board sim = b1;\n                    // simulate random placement of next candy\n                    auto [nr, nc] = randomEmptyCell(sim, rng);\n                    sim.a[nr][nc] = nextColor;\n\n                    // choose best next tilt by immediate score\n                    long long bestNext = LLONG_MIN;\n                    for (int dir1 = 0; dir1 < 4; dir1++) {\n                        Board tmp2 = sim;\n                        tilt(tmp2, dir1);\n                        long long sc1 = evaluate(tmp2);\n                        if (sc1 > bestNext) bestNext = sc1;\n                    }\n                    futureSum += bestNext;\n                }\n\n                // Score \u2248 S0 + 0.5 * E[nextScore]\n                // Compare using: Score' = 2 * S0 * MONTE_K + futureSum\n                scoreValue = 2LL * S0 * MONTE_K + futureSum;\n            } else {\n                // Last step: just immediate score is enough\n                scoreValue = S0;\n            }\n\n            if (scoreValue > bestScore) {\n                bestScore = scoreValue;\n                bestDir = dir0;\n                bestBoard = b1;\n            }\n        }\n\n        cur = bestBoard;\n        cout << DIR_CH[bestDir] << '\\n' << flush;\n    }\n\n    return 0;\n}","ahc016":"#include <bits/stdc++.h>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int M;\n    double eps;\n    if (!(cin >> M >> eps)) return 0;\n\n    bool noNoise = (eps < 0.0005);  // eps is multiple of 0.01; treat 0 as noiseless\n\n    int N = 4;\n    int L = 0;\n\n    if (noNoise) {\n        // Choose minimal N such that total edges L >= M\n        while (N < 100) {\n            L = N * (N - 1) / 2;\n            if (L >= M) break;\n            ++N;\n        }\n        L = N * (N - 1) / 2;\n    } else {\n        // Keep the previous heuristic: L >= (10 + 80*eps) * M\n        double baseFactor = 10.0 + 80.0 * eps;\n        double targetL = baseFactor * M;\n        while (N < 100) {\n            L = N * (N - 1) / 2;\n            if (L >= targetL) break;\n            ++N;\n        }\n        L = N * (N - 1) / 2;\n    }\n\n    // Edge counts for each graph\n    vector<int> mEdges(M);\n\n    if (noNoise) {\n        // Assign edge counts 0..M-1 (all distinct, <= L since L >= M)\n        for (int k = 0; k < M; ++k) {\n            mEdges[k] = k;\n        }\n    } else {\n        // For eps > 0, spread edge counts approximately evenly between 1 and L-1\n        for (int k = 0; k < M; ++k) {\n            long long num = 1LL * (k + 1) * L;\n            int mk = (int)(num / (M + 1));  // floor\n            if (mk <= 0) mk = 1;\n            if (mk >= L) mk = L - 1;\n            mEdges[k] = mk;\n        }\n        // Ensure strictly increasing counts (safe given L is large vs M)\n        mEdges[0] = max(mEdges[0], 1);\n        for (int k = 1; k < M; ++k) {\n            if (mEdges[k] <= mEdges[k - 1]) {\n                mEdges[k] = mEdges[k - 1] + 1;\n                if (mEdges[k] >= L) mEdges[k] = L - 1;\n            }\n        }\n    }\n\n    // Precompute expected noisy edge counts for eps > 0\n    vector<double> mu;\n    double a = 1.0 - 2.0 * eps;\n    double b = eps * L;\n    if (!noNoise) {\n        mu.resize(M);\n        for (int k = 0; k < M; ++k) {\n            mu[k] = a * (double)mEdges[k] + b;\n        }\n    }\n\n    // Output N and the M graphs G_0..G_{M-1}\n    cout << N << '\\n';\n    for (int k = 0; k < M; ++k) {\n        int mk = mEdges[k];\n        string s(L, '0');\n        for (int i = 0; i < mk; ++i) s[i] = '1';\n        cout << s << '\\n';\n    }\n    cout.flush();\n\n    // For eps = 0, build direct map from edge count to graph index\n    vector<int> edgeToIndex;\n    if (noNoise) {\n        edgeToIndex.assign(L + 1, -1);\n        for (int k = 0; k < M; ++k) {\n            int mk = mEdges[k];\n            if (0 <= mk && mk <= L) edgeToIndex[mk] = k;\n        }\n    }\n\n    // Handle 100 queries\n    for (int q = 0; q < 100; ++q) {\n        string H;\n        if (!(cin >> H)) return 0;\n        // Count edges in H\n        int mPrime = 0;\n        for (char c : H) if (c == '1') ++mPrime;\n\n        int bestK = 0;\n\n        if (noNoise) {\n            // Exact decoding by edge count\n            if (mPrime >= 0 && mPrime <= L && edgeToIndex[mPrime] != -1) {\n                bestK = edgeToIndex[mPrime];\n            } else {\n                // Fallback (should not happen): choose nearest mEdges[k]\n                int bestDiff = INT_MAX;\n                for (int k = 0; k < M; ++k) {\n                    int diff = abs(mPrime - mEdges[k]);\n                    if (diff < bestDiff) {\n                        bestDiff = diff;\n                        bestK = k;\n                    }\n                }\n            }\n        } else {\n            // Choose k whose expected noisy edge count mu_k is closest to observed mPrime\n            double bestDiff = fabs((double)mPrime - mu[0]);\n            bestK = 0;\n            for (int k = 1; k < M; ++k) {\n                double diff = fabs((double)mPrime - mu[k]);\n                if (diff < bestDiff) {\n                    bestDiff = diff;\n                    bestK = k;\n                }\n            }\n        }\n\n        cout << bestK << '\\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 id;\n    int w;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, D, K;\n    if (!(cin >> N >> M >> D >> K)) return 0;\n\n    vector<int> U(M), V(M), W(M);\n    for (int i = 0; i < M; i++) {\n        cin >> U[i] >> V[i] >> W[i];\n        --U[i];\n        --V[i];\n    }\n    // Coordinates (unused)\n    for (int i = 0; i < N; i++) {\n        int x, y;\n        cin >> x >> y;\n    }\n\n    // Build adjacency list\n    vector<vector<AdjEdge>> g(N);\n    g.assign(N, {});\n    for (int i = 0; i < M; i++) {\n        int u = U[i], v = V[i], w = W[i];\n        g[u].push_back({v, i, w});\n        g[v].push_back({u, i, w});\n    }\n\n    mt19937_64 rng(123456789);\n\n    // ----------------- Step 1: Edge centrality (sampled shortest-path trees) -----------------\n    int S = min(N, 100); // number of sampled sources\n    vector<int> perm(N);\n    iota(perm.begin(), perm.end(), 0);\n    shuffle(perm.begin(), perm.end(), rng);\n\n    vector<int> sources(S);\n    for (int i = 0; i < S; i++) sources[i] = perm[i];\n\n    vector<double> central(M, 0.0);\n\n    const long long INFLL = (1LL << 60);\n    vector<long long> dist(N);\n    vector<int> parent_v(N), parent_e(N);\n    vector<int> order;\n    order.reserve(N);\n\n    using PQItem = pair<long long,int>;\n\n    for (int s : sources) {\n        fill(dist.begin(), dist.end(), INFLL);\n        fill(parent_v.begin(), parent_v.end(), -1);\n        fill(parent_e.begin(), parent_e.end(), -1);\n        order.clear();\n\n        priority_queue<PQItem, vector<PQItem>, greater<PQItem>> pq;\n        dist[s] = 0;\n        pq.emplace(0, s);\n\n        while (!pq.empty()) {\n            auto [d, v] = pq.top();\n            pq.pop();\n            if (d != dist[v]) continue;\n            order.push_back(v);\n            for (const auto &e : g[v]) {\n                int to = e.to;\n                long long nd = d + e.w;\n                if (nd < dist[to]) {\n                    dist[to] = nd;\n                    parent_v[to] = v;\n                    parent_e[to] = e.id;\n                    pq.emplace(nd, to);\n                }\n            }\n        }\n\n        // Tree DP to accumulate centrality\n        vector<int> sz(N, 1);\n        for (int i = (int)order.size() - 1; i >= 0; --i) {\n            int v = order[i];\n            int pv = parent_v[v];\n            if (pv == -1) continue;\n            int eid = parent_e[v];\n            central[eid] += sz[v];\n            sz[pv] += sz[v];\n        }\n    }\n\n    // ----------------- Step 2: Edge detour length (alternative path without the edge) --------\n    vector<long long> altDiff(M, 1); // altDist - W[e], at least 1\n    for (int eid = 0; eid < M; eid++) {\n        int src = U[eid];\n        int tgt = V[eid];\n\n        fill(dist.begin(), dist.end(), INFLL);\n        priority_queue<PQItem, vector<PQItem>, greater<PQItem>> pq;\n        dist[src] = 0;\n        pq.emplace(0, src);\n\n        while (!pq.empty()) {\n            auto [d, v] = pq.top();\n            pq.pop();\n            if (d != dist[v]) continue;\n            if (v == tgt) break; // reached target with minimal distance\n            for (const auto &ed : g[v]) {\n                if (ed.id == eid) continue; // skip current edge in both directions\n                int to = ed.to;\n                long long nd = d + ed.w;\n                if (nd < dist[to]) {\n                    dist[to] = nd;\n                    pq.emplace(nd, to);\n                }\n            }\n        }\n\n        long long alt = dist[tgt];\n        if (alt == INFLL) {\n            // Graph is guaranteed 2-edge-connected; this should not happen.\n            // Fallback: treat as very large detour.\n            alt = (long long)1e9;\n        }\n        long long delta = alt - (long long)W[eid];\n        if (delta < 1) delta = 1; // keep some importance even if equal alternative exists\n        altDiff[eid] = delta;\n    }\n\n    // ----------------- Step 3: Combine into edge importance weights -------------------------\n    vector<double> impRaw(M);\n    double maxImp = 0.0;\n    for (int i = 0; i < M; i++) {\n        // Approximate #pairs using edge by centrality, and cost per pair by altDiff\n        double v = (central[i] + 1.0) * (double)altDiff[i];\n        impRaw[i] = v;\n        if (v > maxImp) maxImp = v;\n    }\n    if (maxImp <= 0.0) maxImp = 1.0;\n\n    // Scale importance into [0, 1000]\n    vector<double> weight(M);\n    double scale = maxImp / 1000.0;\n    for (int i = 0; i < M; i++) {\n        weight[i] = impRaw[i] / scale;\n    }\n\n    // ----------------- Step 4: Initial greedy assignment of edges to days -------------------\n    // Balanced edge counts per day; ensures cap[d] <= ceil(M/D) <= K\n    vector<int> cap(D);\n    int base = M / D;\n    int rem = M % D;\n    for (int d = 0; d < D; d++) {\n        cap[d] = base + (d < rem ? 1 : 0);\n    }\n\n    vector<int> day_cnt(D, 0);\n    vector<double> day_sum(D, 0.0); // sum of weights per day\n\n    // vds[v][d] = sum of weights of edges incident to vertex v on day d\n    vector<vector<double>> vds(N, vector<double>(D, 0.0));\n\n    vector<int> r(M, -1); // day assignment (0-based) for each edge\n\n    // Sort edges by descending importance\n    vector<int> ids(M);\n    iota(ids.begin(), ids.end(), 0);\n    sort(ids.begin(), ids.end(), [&](int a, int b) {\n        return weight[a] > weight[b];\n    });\n\n    const double INIT_ALPHA = 10.0; // vertex-local importance for initial placement\n    const double INIT_BETA  = 1.0;  // per-day balance weight\n\n    for (int idx = 0; idx < M; idx++) {\n        int e = ids[idx];\n        int u = U[e], v = V[e];\n\n        int bestD = -1;\n        double bestScore = 1e300;\n\n        for (int d = 0; d < D; d++) {\n            if (day_cnt[d] >= cap[d]) continue;\n            double localConcur = vds[u][d] + vds[v][d];\n            double score = INIT_ALPHA * localConcur + INIT_BETA * day_sum[d];\n            if (score < bestScore) {\n                bestScore = score;\n                bestD = d;\n            }\n        }\n\n        if (bestD == -1) {\n            // Fallback (should not happen): put to any day with remaining capacity\n            for (int d = 0; d < D; d++) {\n                if (day_cnt[d] < cap[d]) {\n                    bestD = d;\n                    break;\n                }\n            }\n        }\n\n        r[e] = bestD;\n        day_cnt[bestD]++;\n        day_sum[bestD] += weight[e];\n        vds[u][bestD] += weight[e];\n        vds[v][bestD] += weight[e];\n    }\n\n    // ----------------- Step 5: Local search (hill climbing on combined objective) ----------\n    // Objective: sum_{v,d} (vds[v][d]^2) * ALPHA + sum_d (day_sum[d]^2) * BETA\n    const double ALPHA = 1.0;   // vertex-day component\n    const double BETA  = 0.1;   // per-day balance component (smaller => concurrency more important)\n\n    int ITER = min(1500000, 500 * M);\n\n    for (int it = 0; it < ITER; ++it) {\n        int e1 = (int)(rng() % (unsigned long long)M);\n        int e2 = (int)(rng() % (unsigned long long)M);\n        if (e1 == e2) continue;\n        int d1 = r[e1], d2 = r[e2];\n        if (d1 == d2) continue;\n\n        int u1 = U[e1], v1 = V[e1];\n        int u2 = U[e2], v2 = V[e2];\n        double w1 = weight[e1], w2 = weight[e2];\n\n        // Day-sum part\n        double S1 = day_sum[d1], S2 = day_sum[d2];\n        double nS1 = S1 - w1 + w2;\n        double nS2 = S2 - w2 + w1;\n        double deltaDay = BETA * ((nS1 * nS1 + nS2 * nS2) - (S1 * S1 + S2 * S2));\n\n        // Vertex-day part\n        // Collect changes in (vertex, day) pairs\n        int vs[8];\n        int ds[8];\n        double dW[8];\n        int cnt = 0;\n\n        auto addChange = [&](int v, int d, double delta) {\n            for (int i = 0; i < cnt; i++) {\n                if (vs[i] == v && ds[i] == d) {\n                    dW[i] += delta;\n                    return;\n                }\n            }\n            vs[cnt] = v;\n            ds[cnt] = d;\n            dW[cnt] = delta;\n            cnt++;\n        };\n\n        // e1 moves d1 -> d2\n        addChange(u1, d1, -w1);\n        addChange(u1, d2, +w1);\n        addChange(v1, d1, -w1);\n        addChange(v1, d2, +w1);\n        // e2 moves d2 -> d1\n        addChange(u2, d2, -w2);\n        addChange(u2, d1, +w2);\n        addChange(v2, d2, -w2);\n        addChange(v2, d1, +w2);\n\n        double deltaVertex = 0.0;\n        double newVals[8];\n        for (int i = 0; i < cnt; i++) {\n            int v = vs[i];\n            int d = ds[i];\n            double oldS = vds[v][d];\n            double newS = oldS + dW[i];\n            newVals[i] = newS;\n            deltaVertex += ALPHA * (newS * newS - oldS * oldS);\n        }\n\n        double deltaScore = deltaVertex + deltaDay;\n\n        if (deltaScore < -1e-9) {\n            // Accept swap\n            day_sum[d1] = nS1;\n            day_sum[d2] = nS2;\n            for (int i = 0; i < cnt; i++) {\n                vds[vs[i]][ds[i]] = newVals[i];\n            }\n            swap(r[e1], r[e2]);\n        }\n    }\n\n    // ----------------- Output -----------------\n    for (int i = 0; i < M; i++) {\n        cout << (r[i] + 1);\n        if (i + 1 != M) cout << ' ';\n    }\n    cout << '\\n';\n\n    return 0;\n}","ahc019":"#include <bits/stdc++.h>\nusing namespace std;\n\n// ----------------------------\n// Basic structures\n// ----------------------------\nstruct Coord {\n    int x, y, z;\n};\n\nstruct Rot {\n    int p[3]; // permutation of axes: 0=x,1=y,2=z\n    int s[3]; // sign for each axis: +1 or -1\n};\n\nconst int MAXS = 250; // upper bound for number of shared cubes (safe for D<=14)\n\n// adjacency presence for shared cubes (index 0..S-1)\nstatic bool adjSmall[MAXS][MAXS];\nstatic bool adjBig[MAXS][MAXS];\n\n// ----------------------------\n// Generate all 24 proper rotations (determinant +1) of the cube\n// ----------------------------\nvector<Rot> generate_rotations() {\n    vector<Rot> rots;\n    vector<int> perm = {0, 1, 2};\n    auto parity = [](const vector<int>& p) -> int {\n        int inv = 0;\n        for (int i = 0; i < 3; i++) {\n            for (int j = i + 1; j < 3; j++) {\n                if (p[i] > p[j]) inv++;\n            }\n        }\n        return (inv % 2 == 0) ? 1 : -1; // +1 for even, -1 for odd\n    };\n\n    do {\n        int ps = parity(perm);\n        for (int mask = 0; mask < 8; mask++) {\n            int s0 = (mask & 1) ? -1 : 1;\n            int s1 = (mask & 2) ? -1 : 1;\n            int s2 = (mask & 4) ? -1 : 1;\n            int det = ps * s0 * s1 * s2;\n            if (det == 1) {\n                Rot r;\n                r.p[0] = perm[0]; r.p[1] = perm[1]; r.p[2] = perm[2];\n                r.s[0] = s0;      r.s[1] = s1;      r.s[2] = s2;\n                rots.push_back(r);\n            }\n        }\n    } while (next_permutation(perm.begin(), perm.end()));\n    // Should be 24 rotations\n    // cerr << \"rots=\" << rots.size() << \"\\n\";\n    return rots;\n}\n\n// ----------------------------\n// Canonical shape representation\n// coords are given as cell IDs in [0, D^3)\n// preRot[r][id] = rotated (x,y,z) for rotation r\n// ----------------------------\nvector<array<int,3>> canonical_from_ids(\n    const vector<int>& ids,\n    const vector<vector<array<int,3>>>& preRot\n) {\n    vector<array<int,3>> best;\n    bool first = true;\n    int R = (int)preRot.size();\n    for (int r = 0; r < R; r++) {\n        const auto& tab = preRot[r];\n        vector<array<int,3>> coords;\n        coords.reserve(ids.size());\n        int minx = INT_MAX, miny = INT_MAX, minz = INT_MAX;\n        for (int id : ids) {\n            const auto& q = tab[id];\n            coords.push_back(q);\n            minx = min(minx, q[0]);\n            miny = min(miny, q[1]);\n            minz = min(minz, q[2]);\n        }\n        for (auto &q : coords) {\n            q[0] -= minx;\n            q[1] -= miny;\n            q[2] -= minz;\n        }\n        sort(coords.begin(), coords.end());\n        if (first || coords < best) {\n            best = coords;\n            first = false;\n        }\n    }\n    return best;\n}\n\n// ----------------------------\n// Main\n// ----------------------------\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int D;\n    if (!(cin >> D)) return 0;\n\n    // Read silhouettes: f[t][z][x], r[t][z][y]\n    vector<string> f[2], r[2];\n    for (int t = 0; t < 2; t++) {\n        f[t].resize(D);\n        r[t].resize(D);\n        for (int z = 0; z < D; z++) cin >> f[t][z];\n        for (int z = 0; z < D; z++) cin >> r[t][z];\n    }\n\n    // Build minimal-volume occupancy for each puzzle\n    vector<Coord> cells[2]; // occupied cells per puzzle\n\n    for (int t = 0; t < 2; t++) {\n        for (int z = 0; z < D; z++) {\n            vector<int> rows, cols;\n            for (int x = 0; x < D; x++) if (f[t][z][x] == '1') rows.push_back(x);\n            for (int y = 0; y < D; y++) if (r[t][z][y] == '1') cols.push_back(y);\n            int Rcnt = (int)rows.size();\n            int Ccnt = (int)cols.size();\n            if (Rcnt == 0 || Ccnt == 0) continue; // shouldn't happen\n\n            if (Rcnt <= Ccnt) {\n                for (int j = 0; j < Ccnt; j++) {\n                    int x = rows[j % Rcnt];\n                    int y = cols[j];\n                    cells[t].push_back({x, y, z});\n                }\n            } else {\n                for (int i = 0; i < Rcnt; i++) {\n                    int x = rows[i];\n                    int y = cols[i % Ccnt];\n                    cells[t].push_back({x, y, z});\n                }\n            }\n        }\n    }\n\n    int V0 = (int)cells[0].size();\n    int V1 = (int)cells[1].size();\n\n    // Decide which puzzle is \"small\" and \"big\"\n    int small = 0, big = 1;\n    if (V0 > V1) {\n        small = 1;\n        big = 0;\n        swap(V0, V1); // now V0 <= V1 logically (but not used later)\n    }\n    int S = (int)cells[small].size();\n    int T = (int)cells[big].size();\n\n    // Greedy nearest-neighbor assignment: match each cell in small to a unique cell in big\n    vector<int> matchSmallToBig(S, -1);\n    vector<char> usedBig(T, false);\n\n    for (int i = 0; i < S; i++) {\n        const Coord &cs = cells[small][i];\n        int bestJ = -1;\n        int bestDist = INT_MAX;\n        for (int j = 0; j < T; j++) {\n            if (usedBig[j]) continue;\n            const Coord &cb = cells[big][j];\n            int dist = abs(cs.x - cb.x) + abs(cs.y - cb.y) + abs(cs.z - cb.z);\n            if (dist < bestDist) {\n                bestDist = dist;\n                bestJ = j;\n            }\n        }\n        if (bestJ == -1) {\n            // Should not happen\n            bestJ = 0;\n            while (usedBig[bestJ]) bestJ++;\n        }\n        matchSmallToBig[i] = bestJ;\n        usedBig[bestJ] = true;\n    }\n\n    // Prepare shared cube data\n    vector<Coord> posSmall(S), posBig(S);\n    vector<int> cellIdSmall(S), cellIdBig(S);\n\n    auto encode = [D](int x, int y, int z) {\n        return x * D * D + y * D + z;\n    };\n\n    for (int k = 0; k < S; k++) {\n        Coord cs = cells[small][k];\n        Coord cb = cells[big][ matchSmallToBig[k] ];\n        posSmall[k] = cs;\n        posBig[k] = cb;\n        cellIdSmall[k] = encode(cs.x, cs.y, cs.z);\n        cellIdBig[k] = encode(cb.x, cb.y, cb.z);\n    }\n\n    int D3 = D * D * D;\n\n    // Build index maps for shared cubes in each puzzle (for adjacency)\n    vector<int> idxSmall(D3, -1), idxBig(D3, -1);\n    for (int k = 0; k < S; k++) {\n        idxSmall[ cellIdSmall[k] ] = k;\n        idxBig[ cellIdBig[k] ] = k;\n    }\n\n    // Clear adjacency matrices\n    for (int i = 0; i < S; i++) {\n        for (int j = 0; j < S; j++) {\n            adjSmall[i][j] = false;\n            adjBig[i][j] = false;\n        }\n    }\n\n    // Directions for 6-neighborhood\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    // Build adjacency in small puzzle\n    for (int k = 0; k < S; k++) {\n        int x = posSmall[k].x;\n        int y = posSmall[k].y;\n        int z = posSmall[k].z;\n        for (int d = 0; d < 6; d++) {\n            int nx = x + dx[d];\n            int ny = y + dy[d];\n            int nz = z + dz[d];\n            if (nx < 0 || nx >= D || ny < 0 || ny >= D || nz < 0 || nz >= D) continue;\n            int nid = encode(nx, ny, nz);\n            int j = idxSmall[nid];\n            if (j >= 0) {\n                adjSmall[k][j] = adjSmall[j][k] = true;\n            }\n        }\n    }\n\n    // Build adjacency in big puzzle\n    for (int k = 0; k < S; k++) {\n        int x = posBig[k].x;\n        int y = posBig[k].y;\n        int z = posBig[k].z;\n        for (int d = 0; d < 6; d++) {\n            int nx = x + dx[d];\n            int ny = y + dy[d];\n            int nz = z + dz[d];\n            if (nx < 0 || nx >= D || ny < 0 || ny >= D || nz < 0 || nz >= D) continue;\n            int nid = encode(nx, ny, nz);\n            int j = idxBig[nid];\n            if (j >= 0) {\n                adjBig[k][j] = adjBig[j][k] = true;\n            }\n        }\n    }\n\n    // Build adjacencyInBoth as neighbor lists\n    vector<vector<int>> neighbors(S);\n    for (int i = 0; i < S; i++) {\n        for (int j = i + 1; j < S; j++) {\n            if (adjSmall[i][j] && adjBig[i][j]) {\n                neighbors[i].push_back(j);\n                neighbors[j].push_back(i);\n            }\n        }\n    }\n\n    // Precompute all rotations and rotated coordinates for each cell ID\n    vector<Rot> rots = generate_rotations();\n    int R = (int)rots.size(); // should be 24\n    vector<vector<array<int,3>>> preRot(R, vector<array<int,3>>(D3));\n\n    for (int id = 0; id < D3; id++) {\n        int x = id / (D * D);\n        int rem = id % (D * D);\n        int y = rem / D;\n        int z = rem % D;\n        int src[3] = {x, y, z};\n        for (int rIdx = 0; rIdx < R; rIdx++) {\n            const Rot &rt = rots[rIdx];\n            array<int,3> q;\n            q[0] = rt.s[0] * src[ rt.p[0] ];\n            q[1] = rt.s[1] * src[ rt.p[1] ];\n            q[2] = rt.s[2] * src[ rt.p[2] ];\n            preRot[rIdx][id] = q;\n        }\n    }\n\n    // Helper: check if shapes for given node set are congruent between small and big\n    auto shapesMatch = [&](const vector<int>& nodes) -> bool {\n        vector<int> idsSmall, idsBig;\n        idsSmall.reserve(nodes.size());\n        idsBig.reserve(nodes.size());\n        for (int idx : nodes) {\n            idsSmall.push_back(cellIdSmall[idx]);\n            idsBig.push_back(cellIdBig[idx]);\n        }\n        auto repSmall = canonical_from_ids(idsSmall, preRot);\n        auto repBig = canonical_from_ids(idsBig, preRot);\n        return repSmall == repBig;\n    };\n\n    // Cluster shared cubes into blocks using adjacencyInBoth and shape checks\n    vector<char> visited(S, false);\n    vector<int> blockIdForShared(S, -1);\n    vector<vector<int>> clusters;\n    clusters.reserve(S);\n\n    for (int i = 0; i < S; i++) {\n        if (visited[i]) continue;\n\n        vector<int> cluster;\n        cluster.push_back(i);\n        visited[i] = true;\n\n        bool changed = true;\n        vector<char> attempted(S, false); // per cluster, avoid retrying same candidate multiple times\n\n        while (changed) {\n            changed = false;\n            vector<int> cand;\n            for (int u : cluster) {\n                for (int v : neighbors[u]) {\n                    if (!visited[v] && !attempted[v]) {\n                        cand.push_back(v);\n                        attempted[v] = true;\n                    }\n                }\n            }\n            sort(cand.begin(), cand.end());\n            cand.erase(unique(cand.begin(), cand.end()), cand.end());\n            for (int v : cand) {\n                vector<int> candidate = cluster;\n                candidate.push_back(v);\n                if (shapesMatch(candidate)) {\n                    cluster.push_back(v);\n                    visited[v] = true;\n                    changed = true;\n                }\n            }\n        }\n\n        clusters.push_back(cluster);\n    }\n\n    // Now build block assignments\n    // Total blocks = number of shared clusters + number of big-only cubes\n    int blockCount = 0;\n    vector<int> clusterBlockId; // for clusters\n    clusterBlockId.reserve(clusters.size());\n\n    // Prepare output grids\n    vector<vector<vector<int>>> b(2,\n        vector<vector<int>>(D, vector<int>(D * D, 0)));\n    // We'll use index [t][x][y*D+z] to avoid 3D vector overhead\n\n    auto setCell = [&](int puzzle, const Coord& c, int id) {\n        b[puzzle][c.x][c.y * D + c.z] = id;\n    };\n\n    // Assign block IDs to shared clusters\n    for (const auto& cluster : clusters) {\n        ++blockCount;\n        clusterBlockId.push_back(blockCount);\n        for (int idx : cluster) {\n            Coord cs = posSmall[idx];\n            Coord cb = posBig[idx];\n            setCell(small, cs, blockCount);\n            setCell(big,  cb, blockCount);\n        }\n    }\n\n    // Assign block IDs for big-only cubes (used only in big puzzle)\n    for (int j = 0; j < T; j++) {\n        if (!usedBig[j]) continue; // usedBig[j] indicates matched to some shared cube\n    }\n    // Actually, usedBig[j] == true means \"shared\"; we want j where usedBig[j] == false.\n    for (int j = 0; j < T; j++) {\n        if (usedBig[j]) continue; // skip shared; only big-only\n        ++blockCount;\n        Coord cb = cells[big][j];\n        setCell(big, cb, blockCount);\n    }\n\n    // Output result\n    cout << blockCount << '\\n';\n\n    // Flattened output order: (x,y,z) => index x*D^2 + y*D + z\n    for (int t = 0; t < 2; t++) {\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                    if (!first) cout << ' ';\n                    first = false;\n                    cout << b[t][x][y * D + z];\n                }\n            }\n        }\n        cout << '\\n';\n    }\n\n    return 0;\n}","ahc020":"#include <bits/stdc++.h>\nusing namespace std;\nusing ll = long long;\n\nconst int MAXN = 105;   // N <= 100\nconst int MAXM = 305;   // M <= 300\nconst int MAXK = 5005;  // K <= 5000\nconst ll INFLL = (1LL << 60);\n\nstruct Edge {\n    int u, v;\n    ll w;\n};\n\nint N, M, K;\nll vx[MAXN], vy[MAXN];\nll ax_arr[MAXK], ay_arr[MAXK];\nEdge edges[MAXM];\nvector<pair<int,int>> adj[MAXN];              // (to, edgeIndex)\nll distAll[MAXN][MAXN];                       // shortest path cost\nint parEdge[MAXN][MAXN];                      // parent edge index for shortest path tree from source s\n\n// Residents' candidate stations sorted by squared distance\nvector<pair<ll,int>> residentCand[MAXK];\n\n// Working buffers for evaluation\nll maxd2_arr[MAXN];\nbool used_arr[MAXN];\nbool isReq[MAXN];\nbool usedEdgeUnion[MAXM];\nbool aliveEdge[MAXM];\n\nll keyArr[MAXN];\nint prArr[MAXN];\nbool inArr[MAXN];\nint reqNodesArr[MAXN];\nint metricU[MAXN], metricV[MAXN];\n\nint dsu_p[MAXN], dsu_rnk[MAXN];\n\nvector<int> ordEdges; // edges sorted by weight for MST on union graph\n\nint eval_count = 0;\n\ninline void dsu_reset(int n) {\n    for (int i = 1; i <= n; ++i) {\n        dsu_p[i] = i;\n        dsu_rnk[i] = 0;\n    }\n}\nint dsu_find(int x) {\n    return dsu_p[x] == x ? x : dsu_p[x] = dsu_find(dsu_p[x]);\n}\nbool dsu_unite(int a, int b) {\n    a = dsu_find(a);\n    b = dsu_find(b);\n    if (a == b) return false;\n    if (dsu_rnk[a] < dsu_rnk[b]) swap(a, b);\n    dsu_p[b] = a;\n    if (dsu_rnk[a] == dsu_rnk[b]) ++dsu_rnk[a];\n    return true;\n}\n\n// Evaluate solution for given openFlag[1..N].\n// Returns true iff all residents are covered (each within 5000 of some open station).\n// On success, fills P_out[1..N], B_out[0..M-1], and cost_out.\nbool evaluate_solution(const char openFlag[], ll &cost_out, int P_out[], char B_out[]) {\n    ++eval_count;\n    const ll R2max = 5000LL * 5000LL;\n\n    // Residents -> nearest open station within radius 5000\n    for (int i = 1; i <= N; ++i) {\n        maxd2_arr[i] = 0;\n        used_arr[i] = false;\n    }\n\n    for (int k = 0; k < K; ++k) {\n        bool assigned = false;\n        const auto &cand = residentCand[k];\n        for (size_t idx = 0; idx < cand.size(); ++idx) {\n            ll d2 = cand[idx].first;\n            if (d2 > R2max) break;\n            int v = cand[idx].second;\n            if (openFlag[v]) {\n                assigned = true;\n                used_arr[v] = true;\n                if (maxd2_arr[v] < d2) maxd2_arr[v] = d2;\n                break;\n            }\n        }\n        if (!assigned) {\n            // Some resident cannot be covered\n            return false;\n        }\n    }\n\n    // Compute P_i and broadcasting cost\n    ll broadcastCost = 0;\n    for (int i = 1; i <= N; ++i) {\n        if (maxd2_arr[i] > 0) {\n            long double sr = sqrtl((long double)maxd2_arr[i]);\n            ll r = (ll)sr;\n            if (r * r < maxd2_arr[i]) ++r;\n            if (r > 5000) r = 5000;\n            P_out[i] = (int)r;\n            broadcastCost += r * r;\n        } else {\n            P_out[i] = 0;\n        }\n    }\n\n    // Build required node set: station 1 + all stations with assigned residents\n    for (int i = 1; i <= N; ++i) isReq[i] = false;\n    int R = 0;\n    isReq[1] = true;\n    reqNodesArr[R++] = 1;\n    for (int i = 2; i <= N; ++i) {\n        if (used_arr[i]) {\n            isReq[i] = true;\n            reqNodesArr[R++] = i;\n        }\n    }\n\n    // No edges if only root is required\n    for (int j = 0; j < M; ++j) B_out[j] = 0;\n    if (R <= 1) {\n        cost_out = broadcastCost;\n        return true;\n    }\n\n    // Metric MST on required nodes using Prim\n    for (int i = 0; i < R; ++i) {\n        keyArr[i] = INFLL;\n        prArr[i] = -1;\n        inArr[i] = false;\n    }\n    keyArr[0] = 0;\n    int metricCnt = 0;\n    for (int it = 0; it < R; ++it) {\n        int u = -1;\n        ll best = INFLL;\n        for (int i = 0; i < R; ++i) if (!inArr[i] && keyArr[i] < best) {\n            best = keyArr[i];\n            u = i;\n        }\n        if (u == -1) break; // should not happen\n        inArr[u] = true;\n        if (prArr[u] != -1) {\n            metricU[metricCnt] = u;\n            metricV[metricCnt] = prArr[u];\n            ++metricCnt;\n        }\n        int vu = reqNodesArr[u];\n        for (int i = 0; i < R; ++i) if (!inArr[i]) {\n            int vv = reqNodesArr[i];\n            ll w = distAll[vu][vv];\n            if (w < keyArr[i]) {\n                keyArr[i] = w;\n                prArr[i] = u;\n            }\n        }\n    }\n\n    // Union of shortest paths for metric MST edges\n    for (int j = 0; j < M; ++j) usedEdgeUnion[j] = false;\n    for (int idx = 0; idx < metricCnt; ++idx) {\n        int a = reqNodesArr[metricU[idx]];\n        int b = reqNodesArr[metricV[idx]];\n        int cur = b;\n        while (cur != a) {\n            int eid = parEdge[a][cur];\n            if (eid < 0) {\n                // Should not happen; break to avoid infinite loop\n                break;\n            }\n            usedEdgeUnion[eid] = true;\n            const Edge &E = edges[eid];\n            cur = E.u ^ E.v ^ cur;\n        }\n    }\n\n    // MST over union edges (Steiner tree approximation)\n    for (int j = 0; j < M; ++j) aliveEdge[j] = false;\n    dsu_reset(N);\n    ll edgeCost = 0;\n    for (int idx = 0; idx < M; ++idx) {\n        int e = ordEdges[idx];\n        if (!usedEdgeUnion[e]) continue;\n        int u = edges[e].u;\n        int v = edges[e].v;\n        if (dsu_unite(u, v)) {\n            aliveEdge[e] = true;\n            edgeCost += edges[e].w;\n        }\n    }\n\n    for (int j = 0; j < M; ++j) {\n        B_out[j] = aliveEdge[j] ? 1 : 0;\n    }\n\n    cost_out = broadcastCost + edgeCost;\n    return true;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> M >> K;\n    for (int i = 1; i <= N; ++i) {\n        cin >> vx[i] >> vy[i];\n    }\n    for (int j = 0; j < M; ++j) {\n        int u, v;\n        ll w;\n        cin >> u >> v >> w;\n        edges[j] = {u, v, w};\n    }\n    for (int k = 0; k < K; ++k) {\n        cin >> ax_arr[k] >> ay_arr[k];\n    }\n\n    // Build adjacency\n    for (int i = 1; i <= N; ++i) adj[i].clear();\n    for (int j = 0; j < M; ++j) {\n        int u = edges[j].u;\n        int v = edges[j].v;\n        adj[u].push_back({v, j});\n        adj[v].push_back({u, j});\n    }\n\n    // All-pairs shortest paths (Dijkstra from each vertex)\n    for (int s = 1; s <= N; ++s) {\n        for (int i = 1; i <= N; ++i) {\n            distAll[s][i] = INFLL;\n            parEdge[s][i] = -1;\n        }\n        distAll[s][s] = 0;\n        priority_queue<pair<ll,int>, vector<pair<ll,int>>, greater<pair<ll,int>>> pq;\n        pq.push({0, s});\n        while (!pq.empty()) {\n            auto [d, v] = pq.top();\n            pq.pop();\n            if (d != distAll[s][v]) continue;\n            for (auto &pr : adj[v]) {\n                int to = pr.first;\n                int eidx = pr.second;\n                ll nd = d + edges[eidx].w;\n                if (nd < distAll[s][to]) {\n                    distAll[s][to] = nd;\n                    parEdge[s][to] = eidx;\n                    pq.push({nd, to});\n                }\n            }\n        }\n    }\n\n    // Distance from 1 in the original graph (shortest path)\n    ll distFrom1[MAXN];\n    for (int i = 1; i <= N; ++i) {\n        distFrom1[i] = distAll[1][i];\n    }\n\n    // Precompute resident candidate lists\n    const ll R2max = 5000LL * 5000LL;\n    for (int k = 0; k < K; ++k) {\n        auto &cand = residentCand[k];\n        cand.clear();\n        cand.reserve(N);\n        for (int v = 1; v <= N; ++v) {\n            ll dx = vx[v] - ax_arr[k];\n            ll dy = vy[v] - ay_arr[k];\n            ll d2 = dx * dx + dy * dy;\n            cand.emplace_back(d2, v);\n        }\n        sort(cand.begin(), cand.end(),\n             [](const pair<ll,int> &a, const pair<ll,int> &b){ return a.first < b.first; });\n        // Optional: trim candidates beyond 5000 (not strictly necessary)\n        while (!cand.empty() && cand.back().first > R2max) cand.pop_back();\n    }\n\n    // Precompute global edge order by weight\n    ordEdges.resize(M);\n    iota(ordEdges.begin(), ordEdges.end(), 0);\n    sort(ordEdges.begin(), ordEdges.end(),\n         [&](int a, int b){ return edges[a].w < edges[b].w; });\n\n    // Solution buffers\n    char openNow[MAXN], openBest[MAXN];\n    int P_tmp[MAXN], P_best[MAXN];\n    char B_tmp[MAXM], B_best[MAXM];\n\n    for (int i = 1; i <= N; ++i) openNow[i] = 1;\n\n    eval_count = 0;\n    ll curCost, bestCost;\n    bool ok = evaluate_solution(openNow, curCost, P_tmp, B_tmp);\n    if (!ok) {\n        // Fallback (very unlikely): turn on all edges, broadcast with max power\n        for (int i = 1; i <= N; ++i) P_best[i] = 5000;\n        for (int j = 0; j < M; ++j) B_best[j] = 1;\n\n        cout << P_best[1];\n        for (int i = 2; i <= N; ++i) cout << ' ' << P_best[i];\n        cout << '\\n';\n        if (M > 0) {\n            cout << (int)B_best[0];\n            for (int j = 1; j < M; ++j) cout << ' ' << (int)B_best[j];\n        }\n        cout << '\\n';\n        return 0;\n    }\n\n    bestCost = curCost;\n    for (int i = 1; i <= N; ++i) {\n        P_best[i] = P_tmp[i];\n        openBest[i] = openNow[i];\n    }\n    for (int j = 0; j < M; ++j) B_best[j] = B_tmp[j];\n\n    // Greedy removal of stations (except we start from 2..N, farthest from 1 first)\n    vector<int> order;\n    order.reserve(N - 1);\n    for (int i = 2; i <= N; ++i) order.push_back(i);\n    sort(order.begin(), order.end(),\n         [&](int a, int b){ return distFrom1[a] > distFrom1[b]; });\n\n    for (int idx = 0; idx < (int)order.size(); ++idx) {\n        int v = order[idx];\n        if (!openNow[v]) continue;\n        char old = openNow[v];\n        openNow[v] = 0;\n        ll cost2;\n        if (!evaluate_solution(openNow, cost2, P_tmp, B_tmp)) {\n            openNow[v] = old;\n            continue;\n        }\n        if (cost2 <= curCost) {\n            curCost = cost2;\n            if (cost2 < bestCost) {\n                bestCost = cost2;\n                for (int i = 1; i <= N; ++i) {\n                    P_best[i] = P_tmp[i];\n                    openBest[i] = openNow[i];\n                }\n                for (int j = 0; j < M; ++j) B_best[j] = B_tmp[j];\n            }\n        } else {\n            openNow[v] = old;\n        }\n    }\n\n    // Simulated annealing on open/closed stations\n    const int EVAL_LIMIT = 2200;\n    const double T0 = 1e7;\n    const double T1 = 1e4;\n\n    std::mt19937_64 rng((uint64_t)chrono::steady_clock::now().time_since_epoch().count());\n    uniform_int_distribution<int> distV(1, N);\n    uniform_real_distribution<double> distReal(0.0, 1.0);\n\n    while (eval_count < EVAL_LIMIT) {\n        double t = (double)eval_count / (double)EVAL_LIMIT;\n        double T = T0 * pow(T1 / T0, t);\n\n        int v = distV(rng);\n        char old = openNow[v];\n        openNow[v] ^= 1;\n\n        ll newCost;\n        if (!evaluate_solution(openNow, newCost, P_tmp, B_tmp)) {\n            openNow[v] = old;\n            continue;\n        }\n        ll delta = newCost - curCost;\n        if (delta <= 0) {\n            curCost = newCost;\n            if (newCost < bestCost) {\n                bestCost = newCost;\n                for (int i = 1; i <= N; ++i) {\n                    P_best[i] = P_tmp[i];\n                    openBest[i] = openNow[i];\n                }\n                for (int j = 0; j < M; ++j) B_best[j] = B_tmp[j];\n            }\n        } else {\n            double prob = exp(- (double)delta / T);\n            double r = distReal(rng);\n            if (r < prob) {\n                curCost = newCost;\n            } else {\n                openNow[v] = old;\n            }\n        }\n    }\n\n    // Output best solution found\n    cout << P_best[1];\n    for (int i = 2; i <= N; ++i) {\n        cout << ' ' << P_best[i];\n    }\n    cout << '\\n';\n\n    if (M > 0) {\n        cout << (int)B_best[0];\n        for (int j = 1; j < M; ++j) {\n            cout << ' ' << (int)B_best[j];\n        }\n    }\n    cout << '\\n';\n\n    return 0;\n}","ahc021":"#include <bits/stdc++.h>\nusing namespace std;\n\n// ---------------- Structures ----------------\n\nstruct Edge {\n    int u, v; // indices of nodes\n};\n\nstruct Op {\n    short x1, y1, x2, y2; // coordinates of swapped cells\n};\n\n// ---------------- Simple RNG (xorshift) ----------------\n\nstruct XorShift {\n    uint64_t x;\n    XorShift(uint64_t seed = 123456789) : x(seed) {}\n    uint64_t operator()() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return x;\n    }\n    int next_int(int n) { // 0..n-1\n        return (int)(operator()() % (uint64_t)n);\n    }\n};\n\n// ---------------- Violation computation ----------------\n\n// Compute total number of violations E\nint computeE(const vector<int> &a, const vector<Edge> &dEdges) {\n    int E = 0;\n    for (const auto &e : dEdges) {\n        if (a[e.u] > a[e.v]) ++E;\n    }\n    return E;\n}\n\n// Delta E for swapping two neighboring nodes u, v\nint deltaE_for_swap(const vector<int> &a, int u, int v,\n                    const vector<Edge> &dEdges,\n                    const vector<vector<int>> &nodeEdgeIds) {\n    int valU = a[u];\n    int valV = a[v];\n\n    int edges[16];\n    int cnt = 0;\n\n    // collect incident edges of u\n    for (int id : nodeEdgeIds[u]) {\n        edges[cnt++] = id;\n    }\n    // add incident edges of v, avoiding duplicates\n    for (int id : nodeEdgeIds[v]) {\n        bool dup = false;\n        for (int i = 0; i < cnt; ++i) {\n            if (edges[i] == id) {\n                dup = true;\n                break;\n            }\n        }\n        if (!dup) edges[cnt++] = id;\n    }\n\n    int delta = 0;\n    for (int i = 0; i < cnt; ++i) {\n        const Edge &e = dEdges[edges[i]];\n        int aIdx = e.u;\n        int bIdx = e.v;\n\n        int beforeA = a[aIdx];\n        int beforeB = a[bIdx];\n        bool before = (beforeA > beforeB);\n\n        int afterA = (aIdx == u ? valV : (aIdx == v ? valU : beforeA));\n        int afterB = (bIdx == u ? valV : (bIdx == v ? valU : beforeB));\n        bool after = (afterA > afterB);\n\n        delta += (int)after - (int)before;\n    }\n    return delta;\n}\n\n// ---------------- One heuristic run ----------------\n\n// Performs one run (starting from \"initial\"); returns operations and final E.\nvoid run_single(const vector<int> &initial,\n                const vector<Edge> &dEdges,\n                const vector<Edge> &adjEdges,\n                const vector<vector<int>> &nodeEdgeIds,\n                const vector<int> &posX,\n                const vector<int> &posY,\n                XorShift &rng,\n                vector<Op> &opsOut,\n                int &EOut) {\n    const int maxK = 10000;\n    vector<int> a = initial;\n\n    vector<Op> ops;\n    ops.reserve(maxK);\n\n    int K = 0;\n    int E = computeE(a, dEdges);\n\n    // ---------- Stage 1: bubble along parent-child edges ----------\n    const int limitStage1 = maxK * 8 / 10; // up to 8000 swaps\n    const int E_threshold = 30;            // stop Stage1 early if already low\n    const int recalc_interval = 256;\n\n    if (E > 0) {\n        int dM = (int)dEdges.size();\n        bool done = false;\n        while (K < limitStage1 && !done) {\n            bool swappedPass = false;\n            int start = rng.next_int(dM); // random starting position\n\n            for (int t = 0; t < dM && K < limitStage1; ++t) {\n                const Edge &ed = dEdges[(start + t) % dM];\n                int u = ed.u;\n                int v = ed.v;\n                if (a[u] > a[v]) {\n                    swap(a[u], a[v]);\n                    ops.push_back(Op{(short)posX[u], (short)posY[u],\n                                     (short)posX[v], (short)posY[v]});\n                    ++K;\n                    swappedPass = true;\n\n                    if ((K % recalc_interval == 0) || K >= limitStage1) {\n                        E = computeE(a, dEdges);\n                        if (E == 0 || E <= E_threshold || K >= limitStage1) {\n                            done = true;\n                            break;\n                        }\n                    }\n                }\n            }\n            if (!swappedPass) {\n                // No violating parent-child edge => E = 0\n                E = 0;\n                done = true;\n                break;\n            }\n        }\n    }\n\n    // ---------- Stage 2: greedy + small random kicks ----------\n    if (E != 0 && K < maxK) {\n        E = computeE(a, dEdges); // ensure E is up-to-date\n        int M = (int)adjEdges.size();\n\n        const int maxKickMoves  = 25; // maximum number of uphill moves\n        const int maxKickDelta  = 4;  // allow \u0394E up to +4 in kicks\n        const int maxKickTrials = 80; // trials to find a candidate edge per kick\n\n        int kicksUsed = 0;\n\n        while (K < maxK && E > 0) {\n            bool improved = false;\n            int start = rng.next_int(M);\n\n            // Greedy step: find any swap with delta < 0\n            for (int t = 0; t < M && K < maxK; ++t) {\n                const Edge &edge = adjEdges[(start + t) % M];\n                int u = edge.u;\n                int v = edge.v;\n\n                int delta = deltaE_for_swap(a, u, v, dEdges, nodeEdgeIds);\n                if (delta < 0) {\n                    swap(a[u], a[v]);\n                    ops.push_back(Op{(short)posX[u], (short)posY[u],\n                                     (short)posX[v], (short)posY[v]});\n                    ++K;\n                    E += delta;\n                    improved = true;\n                    break;\n                }\n            }\n\n            if (improved) continue;\n\n            // Local minimum w.r.t. single-swap E-improvement\n            if (kicksUsed >= maxKickMoves) break;\n\n            bool kicked = false;\n            for (int trials = 0; trials < maxKickTrials && K < maxK; ++trials) {\n                int idx = rng.next_int(M);\n                const Edge &edge = adjEdges[idx];\n                int u = edge.u;\n                int v = edge.v;\n\n                int delta = deltaE_for_swap(a, u, v, dEdges, nodeEdgeIds);\n\n                // Allow small uphill/neutral moves to escape local minima\n                if (delta <= maxKickDelta) {\n                    swap(a[u], a[v]);\n                    ops.push_back(Op{(short)posX[u], (short)posY[u],\n                                     (short)posX[v], (short)posY[v]});\n                    ++K;\n                    E += delta;\n                    if (delta > 0) ++kicksUsed;\n                    kicked = true;\n                    break;\n                }\n            }\n\n            if (!kicked) break; // couldn't find a reasonable kick move\n        }\n    }\n\n    opsOut.swap(ops);\n    EOut = E;\n}\n\n// ---------------- Main ----------------\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    const int N = 30;\n    const int numNodes = N * (N + 1) / 2;\n\n    // Read input and build id / coordinate mapping\n    vector<int> a0(numNodes);\n    vector<int> posX(numNodes), posY(numNodes);\n    vector<vector<int>> id(N);\n    int cur = 0;\n    for (int x = 0; x < N; ++x) {\n        id[x].resize(x + 1);\n        for (int y = 0; y <= x; ++y) {\n            id[x][y] = cur;\n            posX[cur] = x;\n            posY[cur] = y;\n            int v;\n            cin >> v;\n            a0[cur] = v;\n            ++cur;\n        }\n    }\n\n    // Build DAG edges (parent -> child)\n    vector<Edge> dEdges;\n    dEdges.reserve(2 * (N - 1) * N / 2);\n    for (int x = 0; x < N - 1; ++x) {\n        for (int y = 0; y <= x; ++y) {\n            int p = id[x][y];\n            int c1 = id[x + 1][y];\n            int c2 = id[x + 1][y + 1];\n            dEdges.push_back(Edge{p, c1});\n            dEdges.push_back(Edge{p, c2});\n        }\n    }\n\n    // For each node, list incident DAG edges (indices into dEdges)\n    vector<vector<int>> nodeEdgeIds(numNodes);\n    for (int ei = 0; ei < (int)dEdges.size(); ++ei) {\n        int u = dEdges[ei].u;\n        int v = dEdges[ei].v;\n        nodeEdgeIds[u].push_back(ei);\n        nodeEdgeIds[v].push_back(ei);\n    }\n\n    // Build adjacency edges of triangular grid (undirected)\n    const int dx[6] = {-1, -1, 0, 0, 1, 1};\n    const int dy[6] = {-1, 0, -1, 1, 0, 1};\n    vector<Edge> adjEdges;\n    adjEdges.reserve(3 * numNodes); // rough upper bound\n\n    for (int x = 0; x < N; ++x) {\n        for (int y = 0; y <= x; ++y) {\n            int u = id[x][y];\n            for (int dir = 0; dir < 6; ++dir) {\n                int nx = x + dx[dir];\n                int ny = y + dy[dir];\n                if (nx < 0 || nx >= N) continue;\n                if (ny < 0 || ny > nx) continue;\n                int v = id[nx][ny];\n                if (v > u) { // avoid duplicates (treat undirected)\n                    adjEdges.push_back(Edge{u, v});\n                }\n            }\n        }\n    }\n\n    // Seed RNG with time-based seed\n    uint64_t seed = chrono::high_resolution_clock::now().time_since_epoch().count();\n    XorShift rng(seed);\n\n    // Multiple restarts; keep the best result\n    const int MAX_RESTARTS = 6;\n    vector<Op> bestOps;\n    int bestE = INT_MAX;\n    int bestK = INT_MAX;\n\n    for (int iter = 0; iter < MAX_RESTARTS; ++iter) {\n        vector<Op> curOps;\n        int curE;\n        run_single(a0, dEdges, adjEdges, nodeEdgeIds, posX, posY,\n                   rng, curOps, curE);\n        int curK = (int)curOps.size();\n\n        if (curE < bestE || (curE == bestE && curK < bestK)) {\n            bestE = curE;\n            bestK = curK;\n            bestOps = std::move(curOps);\n        }\n    }\n\n    // Output\n    cout << bestOps.size() << '\\n';\n    for (const auto &op : bestOps) {\n        cout << op.x1 << ' ' << op.y1 << ' '\n             << op.x2 << ' ' << op.y2 << '\\n';\n    }\n\n    return 0;\n}","toyota2023summer-final":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Cell {\n    int r, c, dist;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int D, N;\n    if (!(cin >> D >> N)) return 0;\n\n    const int er = 0;\n    const int ec = (D - 1) / 2;\n\n    vector<vector<bool>> isObstacle(D, vector<bool>(D, false));\n    for (int k = 0; k < N; ++k) {\n        int r, c;\n        cin >> r >> c;\n        isObstacle[r][c] = true;\n    }\n\n    // 1. Static BFS distances from entrance (obstacles only)\n    vector<vector<int>> dist(D, vector<int>(D, -1));\n    {\n        queue<pair<int,int>> q;\n        dist[er][ec] = 0;\n        q.push({er, ec});\n        const int dr[4] = {1, -1, 0, 0};\n        const int dc[4] = {0, 0, 1, -1};\n        while (!q.empty()) {\n            auto [r, c] = q.front(); q.pop();\n            for (int d = 0; d < 4; ++d) {\n                int nr = r + dr[d], nc = c + dc[d];\n                if (nr < 0 || nr >= D || nc < 0 || nc >= D) continue;\n                if (isObstacle[nr][nc]) continue;\n                if (dist[nr][nc] != -1) continue;\n                dist[nr][nc] = dist[r][c] + 1;\n                q.push({nr, nc});\n            }\n        }\n    }\n\n    // 2. Collect storeable cells (non-entrance, non-obstacle) with distances\n    vector<Cell> cells;\n    cells.reserve(D * D);\n    for (int r = 0; r < D; ++r) {\n        for (int c = 0; c < D; ++c) {\n            if (r == er && c == ec) continue;\n            if (isObstacle[r][c]) continue;\n            cells.push_back({r, c, dist[r][c]});\n        }\n    }\n    int M = (int)cells.size(); // = D^2 - 1 - N\n\n    // 3. Sort cells by distance, then row, then column\n    sort(cells.begin(), cells.end(), [](const Cell &a, const Cell &b) {\n        if (a.dist != b.dist) return a.dist < b.dist;\n        if (a.r != b.r) return a.r < b.r;\n        return a.c < b.c;\n    });\n\n    // 4. Rank mapping from (r,c) to index in cells[]\n    vector<vector<int>> rankIdx(D, vector<int>(D, -1));\n    for (int i = 0; i < M; ++i) {\n        rankIdx[cells[i].r][cells[i].c] = i;\n    }\n\n    // Occupancy and labels\n    vector<vector<bool>> hasContainer(D, vector<bool>(D, false));\n    vector<vector<int>> labelGrid(D, vector<int>(D, -1));\n    vector<bool> usedRank(M, false);\n\n    auto bfs_count_reachable_empty = [&](void) -> int {\n        // BFS over empty cells (no obstacles, no containers)\n        vector<vector<char>> vis(D, vector<char>(D, 0));\n        queue<pair<int,int>> q;\n        vis[er][ec] = 1;\n        q.push({er, ec});\n        const int dr[4] = {1, -1, 0, 0};\n        const int dc[4] = {0, 0, 1, -1};\n        while (!q.empty()) {\n            auto [r, c] = q.front(); q.pop();\n            for (int d = 0; d < 4; ++d) {\n                int nr = r + dr[d], nc = c + dc[d];\n                if (nr < 0 || nr >= D || nc < 0 || nc >= D) continue;\n                if (vis[nr][nc]) continue;\n                if (isObstacle[nr][nc]) continue;\n                if (hasContainer[nr][nc]) continue;\n                vis[nr][nc] = 1;\n                q.push({nr, nc});\n            }\n        }\n        int cnt = 0;\n        for (int r = 0; r < D; ++r) {\n            for (int c = 0; c < D; ++c) {\n                if (r == er && c == ec) continue;\n                if (isObstacle[r][c]) continue;\n                if (hasContainer[r][c]) continue;\n                if (vis[r][c]) ++cnt;\n            }\n        }\n        return cnt;\n    };\n\n    auto is_safe_index = [&](int idx, int placed) -> bool {\n        const Cell &cell = cells[idx];\n        int r = cell.r, c = cell.c;\n        // temporarily place container\n        hasContainer[r][c] = true;\n        int reachableEmpty = bfs_count_reachable_empty();\n        hasContainer[r][c] = false;\n\n        int emptiesAfter = M - (placed + 1);\n        return reachableEmpty == emptiesAfter;\n    };\n\n    // 5. Storage phase\n    for (int step = 0; step < M; ++step) {\n        int t;\n        cin >> t;\n        int targetIdx = t; // ideal position index\n\n        int chosenIdx = -1;\n\n        // Try ideal index first if unused\n        if (0 <= targetIdx && targetIdx < M && !usedRank[targetIdx]) {\n            if (is_safe_index(targetIdx, step)) {\n                chosenIdx = targetIdx;\n            }\n        }\n\n        if (chosenIdx == -1) {\n            int bestCost = INT_MAX;\n            // Scan all unused cells and pick safe one closest to targetIdx\n            for (int i = 0; i < M; ++i) {\n                if (usedRank[i]) continue;\n                if (!is_safe_index(i, step)) continue;\n                int cost = (0 <= targetIdx && targetIdx < M) ? abs(i - targetIdx) : 0;\n                if (cost < bestCost) {\n                    bestCost = cost;\n                    chosenIdx = i;\n                }\n            }\n            // In theory chosenIdx should always be set; fallback just in case.\n            if (chosenIdx == -1) {\n                for (int i = 0; i < M; ++i) {\n                    if (!usedRank[i]) {\n                        chosenIdx = i;\n                        break;\n                    }\n                }\n            }\n        }\n\n        usedRank[chosenIdx] = true;\n        int r = cells[chosenIdx].r;\n        int c = cells[chosenIdx].c;\n        hasContainer[r][c] = true;\n        labelGrid[r][c] = t;\n\n        cout << r << ' ' << c << '\\n' << flush;\n    }\n\n    // 6. Retrieval phase\n\n    auto bfs_reachable_empty = [&](vector<vector<char>> &vis) {\n        vis.assign(D, vector<char>(D, 0));\n        queue<pair<int,int>> q;\n        vis[er][ec] = 1;\n        q.push({er, ec});\n        const int dr[4] = {1, -1, 0, 0};\n        const int dc[4] = {0, 0, 1, -1};\n        while (!q.empty()) {\n            auto [r, c] = q.front(); q.pop();\n            for (int d = 0; d < 4; ++d) {\n                int nr = r + dr[d], nc = c + dc[d];\n                if (nr < 0 || nr >= D || nc < 0 || nc >= D) continue;\n                if (vis[nr][nc]) continue;\n                if (isObstacle[nr][nc]) continue;\n                if (hasContainer[nr][nc]) continue;\n                vis[nr][nc] = 1;\n                q.push({nr, nc});\n            }\n        }\n    };\n\n    const int dr[4] = {1, -1, 0, 0};\n    const int dc[4] = {0, 0, 1, -1};\n\n    vector<vector<char>> vis;\n    for (int step = 0; step < M; ++step) {\n        bfs_reachable_empty(vis);\n\n        int bestLabel = INT_MAX;\n        int bestR = -1, bestC = -1;\n\n        for (int r = 0; r < D; ++r) {\n            for (int c = 0; c < D; ++c) {\n                if (!hasContainer[r][c]) continue;\n                bool accessible = false;\n                for (int d = 0; d < 4; ++d) {\n                    int nr = r + dr[d], nc = c + dc[d];\n                    if (nr < 0 || nr >= D || nc < 0 || nc >= D) continue;\n                    if (isObstacle[nr][nc]) continue;\n                    if (hasContainer[nr][nc]) continue; // neighbor must be empty\n                    if (vis[nr][nc]) {\n                        accessible = true;\n                        break;\n                    }\n                }\n                if (!accessible) continue;\n                int lbl = labelGrid[r][c];\n                if (lbl < bestLabel) {\n                    bestLabel = lbl;\n                    bestR = r;\n                    bestC = c;\n                }\n            }\n        }\n\n        // Fallback (should not happen if storage kept empties connected)\n        if (bestR == -1) {\n            for (int r = 0; r < D && bestR == -1; ++r)\n                for (int c = 0; c < D && bestR == -1; ++c)\n                    if (hasContainer[r][c]) {\n                        bestR = r;\n                        bestC = c;\n                    }\n        }\n\n        cout << bestR << ' ' << bestC << '\\n';\n        hasContainer[bestR][bestC] = false;\n        labelGrid[bestR][bestC] = -1;\n    }\n\n    cout.flush();\n    return 0;\n}","ahc024":"#include <bits/stdc++.h>\nusing namespace std;\n\n// Global parameters (read from input)\nint n, m;\n\n// Original and current grids\nvector<vector<int>> orig_grid;\nvector<vector<int>> cur_grid;\n\n// Original adjacency matrix, and a temporary one for checks\n// adj[c][d] = true iff colors c and d are adjacent somewhere (0..m)\nbool adj_orig[101][101];\nbool adj_tmp[101][101];\n\n// Which colors may be adjacent to 0 (i.e., touched the boundary originally)\nbool allowedZeroAdj[101];\n\n// Directions for 4-neighbor moves\nconst int DX[4] = {1, -1, 0, 0};\nconst int DY[4] = {0, 0, 1, -1};\n\n// Compute adjacency matrix for a given grid\nvoid computeAdj(const vector<vector<int>> &g, bool adj[101][101]) {\n    for (int i = 0; i <= m; i++) {\n        for (int j = 0; j <= m; j++) {\n            adj[i][j] = false;\n        }\n    }\n\n    // Internal adjacency\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            int a = g[i][j];\n            if (i + 1 < n) {\n                int b = g[i + 1][j];\n                if (a != b) {\n                    adj[a][b] = adj[b][a] = true;\n                }\n            }\n            if (j + 1 < n) {\n                int b = g[i][j + 1];\n                if (a != b) {\n                    adj[a][b] = adj[b][a] = true;\n                }\n            }\n        }\n    }\n\n    // Adjacency with outside (color 0) via boundary cells\n    for (int i = 0; i < n; i++) {\n        int c1 = g[i][0];\n        if (c1 != 0) adj[0][c1] = adj[c1][0] = true;\n        int c2 = g[i][n - 1];\n        if (c2 != 0) adj[0][c2] = adj[c2][0] = true;\n    }\n    for (int j = 1; j < n - 1; j++) {\n        int c1 = g[0][j];\n        if (c1 != 0) adj[0][c1] = adj[c1][0] = true;\n        int c2 = g[n - 1][j];\n        if (c2 != 0) adj[0][c2] = adj[c2][0] = true;\n    }\n}\n\n// BFS to check connectivity of a given color in the grid\nbool isConnectedColor(int color, const vector<vector<int>> &g) {\n    int N = n * n;\n    static vector<char> vis;\n    if ((int)vis.size() != N) vis.assign(N, 0);\n    else fill(vis.begin(), vis.end(), 0);\n\n    int start = -1;\n    for (int i = 0; i < n && start == -1; i++) {\n        for (int j = 0; j < n; j++) {\n            if (g[i][j] == color) {\n                start = i * n + j;\n                break;\n            }\n        }\n    }\n    if (start == -1) {\n        // Should not happen because we ensure countColor[color] >= 1 when calling\n        return false;\n    }\n\n    queue<int> q;\n    vis[start] = 1;\n    q.push(start);\n\n    while (!q.empty()) {\n        int v = q.front(); q.pop();\n        int x = v / n;\n        int y = v % n;\n        for (int dir = 0; dir < 4; dir++) {\n            int nx = x + DX[dir];\n            int ny = y + DY[dir];\n            if (nx < 0 || nx >= n || ny < 0 || ny >= n) continue;\n            if (g[nx][ny] == color) {\n                int idx = nx * n + ny;\n                if (!vis[idx]) {\n                    vis[idx] = 1;\n                    q.push(idx);\n                }\n            }\n        }\n    }\n\n    // Verify all cells of this color were visited\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            if (g[i][j] == color && !vis[i * n + j]) {\n                return false;\n            }\n        }\n    }\n    return true;\n}\n\n// Compare current adjacency with original\nbool sameAdj() {\n    for (int c = 0; c <= m; c++) {\n        for (int d = c + 1; d <= m; d++) {\n            if (adj_orig[c][d] != adj_tmp[c][d]) return false;\n        }\n    }\n    return true;\n}\n\n// Try to change cell (x, y) to color 0\nbool tryChange(int x, int y, vector<vector<int>> &cur, vector<int> &countColor) {\n    int col = cur[x][y];\n    if (col == 0) return false;\n    if (countColor[col] <= 1) return false; // keep at least one cell per color\n\n    // Ensure this cell is on boundary or adjacent to an existing 0 (for 0-connectivity)\n    bool boundaryCell = (x == 0 || x == n - 1 || y == 0 || y == n - 1);\n    bool adjacentZero = false;\n    for (int dir = 0; dir < 4; dir++) {\n        int nx = x + DX[dir];\n        int ny = y + DY[dir];\n        if (nx < 0 || nx >= n || ny < 0 || ny >= n) continue;\n        if (cur[nx][ny] == 0) {\n            adjacentZero = true;\n            break;\n        }\n    }\n    if (!boundaryCell && !adjacentZero) return false;\n\n    // Ensure we don't create new 0\u2013d adjacencies\n    for (int dir = 0; dir < 4; dir++) {\n        int nx = x + DX[dir];\n        int ny = y + DY[dir];\n        if (nx < 0 || nx >= n || ny < 0 || ny >= n) continue;\n        int neighborColor = cur[nx][ny];\n        if (!allowedZeroAdj[neighborColor]) {\n            return false;\n        }\n    }\n\n    // Degree of this cell in its color's component\n    int sameNei = 0;\n    for (int dir = 0; dir < 4; dir++) {\n        int nx = x + DX[dir];\n        int ny = y + DY[dir];\n        if (nx < 0 || nx >= n || ny < 0 || ny >= n) continue;\n        if (cur[nx][ny] == col) sameNei++;\n    }\n    bool needBFS = (sameNei >= 2);\n\n    // Apply tentative change\n    cur[x][y] = 0;\n    countColor[col]--;\n    countColor[0]++;\n\n    bool ok = true;\n\n    // Check connectivity of the original color if needed\n    if (needBFS) {\n        if (!isConnectedColor(col, cur)) ok = false;\n    }\n\n    // Check adjacency graph\n    if (ok) {\n        computeAdj(cur, adj_tmp);\n        if (!sameAdj()) ok = false;\n    }\n\n    // Revert if invalid\n    if (!ok) {\n        cur[x][y] = col;\n        countColor[col]++;\n        countColor[0]--;\n        return false;\n    }\n    return true;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> n >> m;\n    orig_grid.assign(n, vector<int>(n));\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            cin >> orig_grid[i][j];\n        }\n    }\n\n    // Compute original adjacency\n    computeAdj(orig_grid, adj_orig);\n\n    // Colors allowed to touch 0\n    for (int c = 0; c <= m; c++) {\n        allowedZeroAdj[c] = adj_orig[0][c];\n    }\n    allowedZeroAdj[0] = true; // 0 can touch itself\n\n    // Initialize current grid and color counts\n    cur_grid = orig_grid;\n    vector<int> countColor(m + 1, 0);\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            countColor[cur_grid[i][j]]++;\n        }\n    }\n    // countColor[0] is initially zero inside the grid\n\n    // Queue-based expansion from boundary\n    int N = n * n;\n    vector<char> inQueue(N, false);\n    deque<int> q;\n\n    // Initialize queue with all boundary cells\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            if (i == 0 || i == n - 1 || j == 0 || j == n - 1) {\n                int idx = i * n + j;\n                if (!inQueue[idx]) {\n                    inQueue[idx] = true;\n                    q.push_back(idx);\n                }\n            }\n        }\n    }\n\n    // Deterministic RNG to slightly randomize neighbor processing order\n    std::mt19937_64 rng(123456789);\n\n    while (!q.empty()) {\n        int idx = q.front();\n        q.pop_front();\n        inQueue[idx] = false;\n\n        int x = idx / n;\n        int y = idx % n;\n\n        if (cur_grid[x][y] == 0) continue; // already turned to 0\n\n        if (tryChange(x, y, cur_grid, countColor)) {\n            // If successful, its neighbors may now be removable\n            for (int dir = 0; dir < 4; dir++) {\n                int nx = x + DX[dir];\n                int ny = y + DY[dir];\n                if (nx < 0 || nx >= n || ny < 0 || ny >= n) continue;\n                if (cur_grid[nx][ny] == 0) continue; // no need to revisit zeros\n                int idx2 = nx * n + ny;\n                if (!inQueue[idx2]) {\n                    inQueue[idx2] = true;\n                    // Randomly push front or back to add some variation\n                    if (rng() & 1) q.push_back(idx2);\n                    else q.push_front(idx2);\n                }\n            }\n        }\n    }\n\n    // Output final grid\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            if (j) cout << ' ';\n            cout << cur_grid[i][j];\n        }\n        cout << '\\n';\n    }\n\n    return 0;\n}","ahc025":"#include <bits/stdc++.h>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, D, Q;\n    if (!(cin >> N >> D >> Q)) return 0;\n\n    // Store pairwise queries and results\n    vector<int> A(Q), B(Q);   // items in each query\n    vector<int> Y(Q);         // label: +1 if A[q] heavier, -1 if B[q] heavier, 0 if '='\n\n    vector<int> matchCount(N, 0);\n    static bool used[100][100];  // N <= 100, symmetric\n\n    mt19937 rng(712367821);\n\n    vector<int> order(N);\n    iota(order.begin(), order.end(), 0);\n\n    // ---- Query phase: perform exactly Q pairwise comparisons ----\n    for (int q = 0; q < Q; ++q) {\n        // Choose a pair (a, b) that keeps match counts balanced and avoids repeats\n        sort(order.begin(), order.end(), [&](int i, int j) {\n            if (matchCount[i] != matchCount[j]) return matchCount[i] < matchCount[j];\n            return i < j;\n        });\n\n        int a = -1, b = -1;\n        bool found = false;\n        int K = min(N, 10);\n\n        // Try to find a new pair among the K least-used items\n        for (int attempt = 0; attempt < K * 5 && !found; ++attempt) {\n            int ui = rng() % K;\n            int vi = rng() % K;\n            if (ui == vi) continue;\n            int i = order[ui];\n            int j = order[vi];\n            if (i > j) swap(i, j);\n            if (!used[i][j]) {\n                a = i;\n                b = j;\n                found = true;\n            }\n        }\n\n        // Fallback: random pairs avoiding used ones if possible\n        if (!found) {\n            for (int attempt = 0; attempt < N * N && !found; ++attempt) {\n                int i = rng() % N;\n                int j = rng() % N;\n                if (i == j) continue;\n                if (i > j) swap(i, j);\n                if (!used[i][j]) {\n                    a = i;\n                    b = j;\n                    found = true;\n                }\n            }\n        }\n\n        // If all pairs are used (very unlikely since Q < N(N-1)/2), just pick any pair\n        if (!found) {\n            do {\n                a = rng() % N;\n                b = rng() % N;\n            } while (a == b);\n            if (a > b) swap(a, b);\n        }\n\n        used[a][b] = used[b][a] = true;\n        matchCount[a]++;\n        matchCount[b]++;\n        A[q] = a;\n        B[q] = b;\n\n        // Output the query: 1 item on each side\n        cout << 1 << ' ' << 1 << ' ' << a << ' ' << b << '\\n';\n        cout.flush();\n\n        // Read the result\n        string res;\n        if (!(cin >> res)) return 0;\n        if (res[0] == '>') {\n            Y[q] = +1;  // A heavier than B\n        } else if (res[0] == '<') {\n            Y[q] = -1;  // B heavier than A\n        } else {\n            Y[q] = 0;   // '=' (very rare)\n        }\n    }\n\n    // ---- Offline rating (Bradley\u2013Terry style logistic regression) ----\n    vector<double> r(N, 0.0);  // ratings\n\n    const int ITER = 80;\n    const double base_eta = 0.5;\n\n    bool hasInfo = false;\n    for (int q = 0; q < Q; ++q) if (Y[q] != 0) { hasInfo = true; break; }\n\n    if (hasInfo) {\n        for (int iter = 0; iter < ITER; ++iter) {\n            double eta = base_eta / (1.0 + 0.1 * iter);\n            for (int q = 0; q < Q; ++q) {\n                int y = Y[q];\n                if (y == 0) continue;  // skip ties\n                int a = A[q], b = B[q];\n                double s = r[a] - r[b];\n                double z = (double) y * s;\n\n                // Avoid overflow; if z is large positive, gradient ~ 0\n                if (z > 40.0) continue;\n\n                double g;\n                if (z < -40.0) {\n                    g = (double) y;  // ~ y / (1 + 0) = y\n                } else {\n                    g = (double) y / (1.0 + std::exp(z));\n                }\n                double step = eta * g;\n                r[a] += step;\n                r[b] -= step;\n            }\n        }\n    }\n\n    // ---- Map ratings to approximate weights using exponential order statistics ----\n    vector<int> idx(N);\n    iota(idx.begin(), idx.end(), 0);\n    // Larger rating => heavier\n    sort(idx.begin(), idx.end(), [&](int i, int j) {\n        if (r[i] != r[j]) return r[i] > r[j];\n        return i < j;\n    });\n\n    vector<double> wAsc(N);  // expected Exp(lambda) order statistics, ascending\n    const double lambda = 1e-5;\n    double acc = 0.0;\n    for (int k = 1; k <= N; ++k) {\n        acc += 1.0 / (lambda * (N - k + 1));  // increment for kth smallest\n        wAsc[k - 1] = acc;\n    }\n    // Clamp to generation max (not strictly necessary, but harmless)\n    double wmax = 1e5 * (double) N / (double) D;\n    for (int i = 0; i < N; ++i) {\n        if (wAsc[i] > wmax) wAsc[i] = wmax;\n    }\n\n    vector<double> weight(N);\n    if (hasInfo) {\n        // Assign heaviest rating to largest expected weight\n        for (int pos = 0; pos < N; ++pos) {\n            int item = idx[pos];\n            double w_est = wAsc[N - 1 - pos];\n            weight[item] = w_est;\n        }\n    } else {\n        // Degenerate case: no information (almost impossible); use equal weights\n        for (int i = 0; i < N; ++i) weight[i] = 1.0;\n    }\n\n    // ---- Partitioning: greedy + local search ----\n\n    // Greedy initialization (largest weight first)\n    vector<int> assign(N, -1);\n    vector<double> binSum(D, 0.0);\n\n    vector<int> ord(N);\n    iota(ord.begin(), ord.end(), 0);\n    sort(ord.begin(), ord.end(), [&](int i, int j) {\n        if (weight[i] != weight[j]) return weight[i] > weight[j];\n        return i < j;\n    });\n\n    for (int id : ord) {\n        int bestBin = 0;\n        double bestSum = binSum[0];\n        for (int k = 1; k < D; ++k) {\n            if (binSum[k] < bestSum) {\n                bestSum = binSum[k];\n                bestBin = k;\n            }\n        }\n        assign[id] = bestBin;\n        binSum[bestBin] += weight[id];\n    }\n\n    // Local search (moves + swaps) on approximate objective\n    double totalW = 0.0;\n    for (double x : weight) totalW += x;\n    double target = totalW / D;\n    const double EPS = 1e-9;\n    const int MAX_ITERS_LS = 10000;\n\n    int guard = 0;\n    while (true) {\n        bool improved = false;\n\n        // Single-item moves\n        for (int i = 0; i < N && !improved; ++i) {\n            int ai = assign[i];\n            double wi = weight[i];\n            double sa = binSum[ai];\n            double oldA = (sa - target) * (sa - target);\n            for (int k = 0; k < D; ++k) {\n                if (k == ai) continue;\n                double sb = binSum[k];\n                double oldB = (sb - target) * (sb - target);\n                double newSa = sa - wi;\n                double newSb = sb + wi;\n                double newCost = (newSa - target) * (newSa - target)\n                               + (newSb - target) * (newSb - target);\n                double oldCost = oldA + oldB;\n                if (newCost + EPS < oldCost) {\n                    // Apply move\n                    binSum[ai] -= wi;\n                    binSum[k] += wi;\n                    assign[i] = k;\n                    improved = true;\n                    break;\n                }\n            }\n        }\n\n        // Pair swaps\n        if (!improved) {\n            for (int i = 0; i < N && !improved; ++i) {\n                for (int j = i + 1; j < N; ++j) {\n                    int ai = assign[i];\n                    int aj = assign[j];\n                    if (ai == aj) continue;\n                    double wi = weight[i];\n                    double wj = weight[j];\n                    double sa = binSum[ai];\n                    double sb = binSum[aj];\n                    double oldCost = (sa - target) * (sa - target)\n                                   + (sb - target) * (sb - target);\n                    double newSa = sa - wi + wj;\n                    double newSb = sb - wj + wi;\n                    double newCost = (newSa - target) * (newSa - target)\n                                   + (newSb - target) * (newSb - target);\n                    if (newCost + EPS < oldCost) {\n                        binSum[ai] = newSa;\n                        binSum[aj] = newSb;\n                        swap(assign[i], assign[j]);\n                        improved = true;\n                        break;\n                    }\n                }\n            }\n        }\n\n        if (!improved) break;\n        if (++guard > MAX_ITERS_LS) break;\n    }\n\n    // ---- Final output: assignments d_0 ... d_{N-1} ----\n    for (int i = 0; i < N; ++i) {\n        if (i) cout << ' ';\n        cout << assign[i];\n    }\n    cout << '\\n';\n    cout.flush();\n\n    return 0;\n}","ahc026":"#include <bits/stdc++.h>\nusing namespace std;\n\n// Simple xorshift RNG\nstruct XorShift {\n    unsigned long long x;\n    XorShift(unsigned long long seed = 88172645463325252ULL) : x(seed) {}\n    unsigned long long next() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return x;\n    }\n};\n\nstatic const int MAXV = 205;\n\n// Fenwick tree / BIT for counting values in a stack\nstruct BIT {\n    int n;\n    int bit[MAXV];\n\n    void init(int n_) {\n        n = n_;\n        memset(bit, 0, sizeof(bit));\n    }\n\n    void add(int idx, int delta) {\n        // values are in [1..n]\n        for (int i = idx; i <= n; i += i & -i) {\n            bit[i] += delta;\n        }\n    }\n\n    int sumPrefix(int idx) const {\n        if (idx > n) idx = n;\n        int s = 0;\n        for (int i = idx; i > 0; i -= i & -i) {\n            s += bit[i];\n        }\n        return s;\n    }\n};\n\n// One simulation run with given weights\nstatic pair<long long, vector<pair<int,int>>>\nrunOnce(const vector<vector<int>>& initStacks,\n        const vector<int>& initStackOf,\n        const vector<int>& initPosInStack,\n        const vector<BIT>& initBits,\n        int n, int m,\n        int wPairs, int wSize,\n        XorShift& rng)\n{\n    // Local copies of state\n    vector<vector<int>> stacks = initStacks;\n    vector<int> stackOf = initStackOf;\n    vector<int> posInStack = initPosInStack;\n    vector<BIT> bits = initBits;\n\n    vector<pair<int,int>> ops;\n    ops.reserve(2 * n + 10);\n    long long energy = 0;\n\n    vector<int> groupVals;\n    groupVals.reserve(n);\n\n    for (int v = 1; v <= n; v++) {\n        int s = stackOf[v];\n        int idx = posInStack[v];\n\n        // If v is not at the top, move the suffix above it\n        if (idx != (int)stacks[s].size() - 1) {\n            int startIdx = idx + 1;\n            int len = (int)stacks[s].size() - startIdx;\n\n            groupVals.clear();\n            groupVals.reserve(len);\n            for (int i = startIdx; i < (int)stacks[s].size(); i++) {\n                groupVals.push_back(stacks[s][i]);\n            }\n\n            // Choose destination stack using pair-count heuristic\n            int dest = -1;\n            long long bestScore = (1LL << 60);\n\n            for (int t = 0; t < m; t++) {\n                if (t == s) continue;\n                long long pairs = 0;\n                const BIT &bt = bits[t];\n                for (int x : groupVals) {\n                    pairs += bt.sumPrefix(x - 1);  // #u in T with u < x\n                }\n\n                long long score = (long long)wPairs * pairs\n                                  + (long long)wSize * (int)stacks[t].size();\n                // Small random noise for tie-breaking\n                score = score * 16 + (rng.next() & 15);\n\n                if (score < bestScore) {\n                    bestScore = score;\n                    dest = t;\n                }\n            }\n            if (dest == -1) {\n                // Fallback (should not happen as m >= 2)\n                dest = (s + 1) % m;\n            }\n\n            int pivot = stacks[s][startIdx];\n            ops.emplace_back(pivot, dest + 1);  // operation 1\n            energy += len + 1;\n\n            // Perform move: update stacks, positions, and BITs\n            auto &Ss = stacks[s];\n            auto &Dt = stacks[dest];\n            int oldSize = (int)Ss.size();\n            for (int i = startIdx; i < oldSize; i++) {\n                int box = Ss[i];\n                bits[s].add(box, -1);\n                bits[dest].add(box, 1);\n                stackOf[box] = dest;\n                posInStack[box] = (int)Dt.size();\n                Dt.push_back(box);\n            }\n            Ss.resize(startIdx);\n        }\n\n        // Now v should be on top; remove it\n        s = stackOf[v];\n        auto &S = stacks[s];\n        // S.back() should be v\n        ops.emplace_back(v, 0);  // operation 2\n        bits[s].add(v, -1);\n        S.pop_back();\n        stackOf[v] = -1;\n        posInStack[v] = -1;\n    }\n\n    return {energy, std::move(ops)};\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int n, m;\n    if (!(cin >> n >> m)) return 0;\n\n    vector<vector<int>> initStacks(m);\n    vector<int> initStackOf(n + 1);\n    vector<int> initPosInStack(n + 1);\n    vector<BIT> initBits(m);\n\n    int perStack = n / m;\n    for (int i = 0; i < m; i++) {\n        initStacks[i].resize(perStack);\n        initBits[i].init(n);\n        for (int j = 0; j < perStack; j++) {\n            int x;\n            cin >> x;\n            initStacks[i][j] = x;\n            initStackOf[x] = i;\n            initPosInStack[x] = j;\n            initBits[i].add(x, 1);\n        }\n    }\n\n    XorShift rng((unsigned long long)chrono::steady_clock::now()\n                     .time_since_epoch().count());\n\n    auto start = chrono::steady_clock::now();\n    auto endTime = start + chrono::milliseconds(1900);  // time guard\n\n    long long bestEnergy = (1LL << 60);\n    vector<pair<int,int>> bestOps;\n\n    int runId = 0;\n    while (true) {\n        int wPairs, wSize;\n\n        if (runId == 0) {\n            // Baseline deterministic-ish params\n            wPairs = 3;\n            wSize  = 1;\n        } else {\n            // Randomize weights for diversity\n            wPairs = 1 + (int)(rng.next() % 6);        // 1..6\n            wSize  = (int)(rng.next() % 7) - 2;        // -2..4\n        }\n\n        auto res = runOnce(initStacks, initStackOf, initPosInStack,\n                           initBits, n, m, wPairs, wSize, rng);\n        if (res.first < bestEnergy) {\n            bestEnergy = res.first;\n            bestOps = std::move(res.second);\n        }\n\n        runId++;\n        if (chrono::steady_clock::now() > endTime) break;\n    }\n\n    // Output best sequence of operations\n    for (auto &op : bestOps) {\n        cout << op.first << ' ' << op.second << '\\n';\n    }\n\n    return 0;\n}","ahc027":"#include <bits/stdc++.h>\nusing namespace std;\n\n// ---------- RNG (xorshift) ----------\nstatic uint64_t rng_state = 123456789ULL;\nstatic inline uint64_t xorshift64() {\n    uint64_t x = rng_state;\n    x ^= x << 7;\n    x ^= x >> 9;\n    rng_state = x;\n    return x;\n}\nstatic inline double rand_double() {\n    // [0,1)\n    return (xorshift64() & ((1ULL << 53) - 1)) * (1.0 / (1ULL << 53));\n}\n\n// ---------- Global structures ----------\nstruct Edge {\n    int to;\n    char dir; // U, D, L, R\n};\n\nint N;\nvector<string> hgrid; // (N-1) x N, between (i,j) and (i+1,j)\nvector<string> vgrid; // N x (N-1), between (i,j) and (i,j+1)\nvector<int> dflat;    // N*N\nvector<vector<Edge>> adj;\nint V; // N*N\n\nvector<int> dist_bfs;\nvector<int> parent_bfs;\nvector<char> pdir_bfs;       // direction from parent -> node in BFS tree\nvector<vector<int>> children; // BFS tree children for DFS cover\n\nstring coverMoves;\n\n// ---------- Utility ----------\ninline char revdir(char c) {\n    if (c == 'U') return 'D';\n    if (c == 'D') return 'U';\n    if (c == 'L') return 'R';\n    return 'L'; // 'R'\n}\n\n// ---------- DFS on BFS tree to build covering tour ----------\nvoid dfs_cover(int u) {\n    for (int v : children[u]) {\n        char dir = pdir_bfs[v]; // parent -> child\n        coverMoves.push_back(dir);\n        dfs_cover(v);\n        coverMoves.push_back(revdir(dir)); // back to parent\n    }\n}\n\n// ---------- Build path from root to given vertex (using BFS tree) ----------\nvoid append_path_root_to(int v, string &route) {\n    const int root = 0;\n    if (v == root) return;\n    vector<char> tmp;\n    int cur = v;\n    while (cur != root) {\n        tmp.push_back(pdir_bfs[cur]); // parent -> cur\n        cur = parent_bfs[cur];\n    }\n    // reverse: root -> v\n    for (int i = (int)tmp.size() - 1; i >= 0; --i) {\n        route.push_back(tmp[i]);\n    }\n}\n\n// ---------- Append path from current vertex to root ----------\nvoid append_path_to_root(int cur, string &route) {\n    const int root = 0;\n    while (cur != root) {\n        char c = revdir(pdir_bfs[cur]); // cur -> parent\n        route.push_back(c);\n        cur = parent_bfs[cur];\n    }\n}\n\n// ---------- Evaluate a route: exact average dirtiness ----------\nlong double evaluate_route(const string &route) {\n    int L = (int)route.size();\n    if (L == 0) return 0.0L;\n\n    // Collect visit times for each cell\n    vector<vector<int>> visits(V);\n    int ci = 0, cj = 0; // start at (0,0)\n    for (int t = 0; t < L; ++t) {\n        char mv = route[t];\n        if (mv == 'U')      --ci;\n        else if (mv == 'D') ++ci;\n        else if (mv == 'L') --cj;\n        else                ++cj; // 'R'\n        int id = ci * N + cj;\n        visits[id].push_back(t + 1); // 1-based time\n    }\n\n    unsigned long long totalScore = 0;\n\n    for (int id = 0; id < V; ++id) {\n        auto &vt = visits[id];\n        if (vt.empty()) {\n            // Should not happen because covering tour visits all cells\n            continue;\n        }\n        int m = (int)vt.size();\n        unsigned __int128 cellSum = 0; // sum of (ell-1)*ell\n\n        // Consecutive visits\n        for (int k = 0; k < m - 1; ++k) {\n            long long len = vt[k + 1] - vt[k];\n            long long lm1 = len - 1;\n            cellSum += (unsigned __int128)lm1 * (unsigned __int128)len;\n        }\n        // Wrap-around interval\n        long long len = (vt[0] + L) - vt[m - 1];\n        long long lm1 = len - 1;\n        cellSum += (unsigned __int128)lm1 * (unsigned __int128)len;\n\n        // cost_i = d_i * cellSum / 2\n        unsigned __int128 c = cellSum * (unsigned __int128)dflat[id];\n        c >>= 1; // divide by 2; (len-1)*len is always even\n        totalScore += (unsigned long long)c;\n    }\n\n    return (long double)totalScore / (long double)L;\n}\n\n// ---------- Build one candidate route under a given policy ----------\nstring build_candidate_route(\n    int startCell,          // where the random walk starts\n    double exponent_p,      // weight exponent for d\n    int Dmax                // max dist from root (for safety budget)\n) {\n    const int root = 0;\n    const int L_MAX = 100000;\n\n    // Precompute weights w[i] = d_i^p\n    vector<double> weight(V);\n    if (fabs(exponent_p) < 1e-9) {\n        for (int i = 0; i < V; ++i) weight[i] = 1.0;\n    } else {\n        for (int i = 0; i < V; ++i) {\n            weight[i] = pow((double)dflat[i], exponent_p);\n        }\n    }\n\n    // Start with covering tour (ends at root)\n    string route = coverMoves;\n\n    // Move from root to startCell if needed\n    if (startCell != root) {\n        append_path_root_to(startCell, route);\n    }\n\n    int prefixLen = (int)route.size();\n    int S = L_MAX - prefixLen - Dmax; // steps reserved for random walk\n    if (S < 0) S = 0;\n\n    // Biased random walk\n    int pos = startCell;\n    for (int step = 0; step < S; ++step) {\n        auto &nb = adj[pos];\n        int deg = (int)nb.size();\n        if (deg == 0) break; // should not happen (connected grid)\n\n        double sumw = 0.0;\n        for (const auto &e : nb) {\n            sumw += weight[e.to];\n        }\n        double r = rand_double() * sumw;\n        double acc = 0.0;\n        int chosen = deg - 1;\n        for (int k = 0; k < deg; ++k) {\n            acc += weight[nb[k].to];\n            if (acc >= r) {\n                chosen = k;\n                break;\n            }\n        }\n        const auto &e = nb[chosen];\n        route.push_back(e.dir);\n        pos = e.to;\n    }\n\n    // Return to root along BFS tree\n    append_path_to_root(pos, route);\n\n    // By construction route length <= L_MAX\n    if ((int)route.size() > L_MAX) {\n        // Should not happen, but truncate defensively (may break closed-loop)\n        route.resize(L_MAX);\n    }\n\n    return route;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N;\n    hgrid.resize(N - 1);\n    for (int i = 0; i < N - 1; ++i) cin >> hgrid[i];\n    vgrid.resize(N);\n    for (int i = 0; i < N; ++i) cin >> vgrid[i];\n\n    V = N * N;\n    dflat.assign(V, 0);\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int x;\n            cin >> x;\n            dflat[i * N + j] = x;\n        }\n    }\n\n    // Build adjacency\n    adj.assign(V, {});\n    auto in_bounds = [&](int i, int j) {\n        return (0 <= i && i < N && 0 <= j && j < N);\n    };\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int id = i * N + j;\n            // Up\n            if (i > 0 && hgrid[i - 1][j] == '0') {\n                int to = (i - 1) * N + j;\n                adj[id].push_back({to, 'U'});\n            }\n            // Down\n            if (i < N - 1 && hgrid[i][j] == '0') {\n                int to = (i + 1) * N + j;\n                adj[id].push_back({to, 'D'});\n            }\n            // Left\n            if (j > 0 && vgrid[i][j - 1] == '0') {\n                int to = i * N + (j - 1);\n                adj[id].push_back({to, 'L'});\n            }\n            // Right\n            if (j < N - 1 && vgrid[i][j] == '0') {\n                int to = i * N + (j + 1);\n                adj[id].push_back({to, 'R'});\n            }\n        }\n    }\n\n    // Sort adjacency so neighbors with larger d come first.\n    for (int u = 0; u < V; ++u) {\n        sort(adj[u].begin(), adj[u].end(),\n             [&](const Edge &a, const Edge &b) {\n                 return dflat[a.to] > dflat[b.to];\n             });\n    }\n\n    // BFS from root to build BFS tree and distances\n    const int root = 0;\n    dist_bfs.assign(V, -1);\n    parent_bfs.assign(V, -1);\n    pdir_bfs.assign(V, 0);\n    queue<int> q;\n    dist_bfs[root] = 0;\n    parent_bfs[root] = root;\n    q.push(root);\n    while (!q.empty()) {\n        int u = q.front();\n        q.pop();\n        for (const auto &e : adj[u]) {\n            int v = e.to;\n            if (dist_bfs[v] == -1) {\n                dist_bfs[v] = dist_bfs[u] + 1;\n                parent_bfs[v] = u;\n                pdir_bfs[v] = e.dir; // parent -> v\n                q.push(v);\n            }\n        }\n    }\n\n    int Dmax = 0;\n    for (int i = 0; i < V; ++i) {\n        Dmax = max(Dmax, dist_bfs[i]);\n    }\n\n    // Build children list for BFS tree\n    children.assign(V, {});\n    for (int v = 0; v < V; ++v) {\n        if (v == root) continue;\n        int p = parent_bfs[v];\n        if (p >= 0 && p < V) children[p].push_back(v);\n    }\n    // Sort children by descending d for DFS order\n    for (int u = 0; u < V; ++u) {\n        sort(children[u].begin(), children[u].end(),\n             [&](int a, int b) {\n                 return dflat[a] > dflat[b];\n             });\n    }\n\n    // Build covering tour (edge-doubling DFS)\n    coverMoves.clear();\n    dfs_cover(root);\n\n    // Find global best-d cell\n    int bestCell = 0;\n    for (int i = 1; i < V; ++i) {\n        if (dflat[i] > dflat[bestCell]) bestCell = i;\n    }\n\n    // Define policies: (start_at_best?, exponent_p)\n    struct Policy {\n        bool start_best;\n        double p;\n    };\n    vector<Policy> policies = {\n        {false, 0.5}, // original-like\n        {true,  0.5},\n        {true,  0.75},\n        {true,  1.0},\n        {true,  0.25},\n        {true,  0.0},\n        {false, 0.25},\n        {false, 1.0},\n    };\n\n    string bestRoute;\n    long double bestScore = numeric_limits<long double>::infinity();\n\n    for (const auto &pol : policies) {\n        int startCell = pol.start_best ? bestCell : root;\n        string route = build_candidate_route(startCell, pol.p, Dmax);\n        long double score = evaluate_route(route);\n        if (score < bestScore) {\n            bestScore = score;\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\n// Large enough INF for costs\nconst int INF = 1e9;\n\n// Compute overlap length: max k in [0..4] such that\n// suffix of a of length k == prefix of b of length k.\nint compute_overlap(const string &a, const string &b) {\n    const int L = 5;\n    for (int k = L - 1; k >= 1; --k) { // k=4..1\n        bool ok = true;\n        for (int i = 0; i < k; ++i) {\n            if (a[L - k + i] != b[i]) {\n                ok = false;\n                break;\n            }\n        }\n        if (ok) return k;\n    }\n    return 0;\n}\n\n// Local search: adjacent swaps to improve total overlap\nint local_search_adjacent_swaps(vector<int> &path, const vector<vector<int>> &ov) {\n    int M = (int)path.size();\n    if (M <= 1) return 0;\n\n    vector<int> edgeOv(max(0, M - 1));\n    int totalOv = 0;\n    for (int i = 0; i + 1 < M; ++i) {\n        int val = ov[path[i]][path[i + 1]];\n        edgeOv[i] = val;\n        totalOv += val;\n    }\n\n    if (M <= 2) {\n        return totalOv; // nothing to improve\n    }\n\n    bool improved = true;\n    while (improved) {\n        improved = false;\n        for (int i = 0; i < M - 1; ++i) {\n            int delta = 0;\n            if (i == 0) {\n                int A = path[0];\n                int B = path[1];\n                int C = path[2];\n\n                int old1 = ov[A][B];\n                int old2 = ov[B][C];\n\n                int new1 = ov[B][A];\n                int new2 = ov[A][C];\n\n                delta = (new1 + new2) - (old1 + old2);\n                if (delta > 0) {\n                    swap(path[0], path[1]);\n                    edgeOv[0] = new1;\n                    edgeOv[1] = new2;\n                    totalOv += delta;\n                    improved = true;\n                }\n            } else if (i == M - 2) {\n                int D = path[M - 3];\n                int A = path[M - 2];\n                int B = path[M - 1];\n\n                int old1 = ov[D][A];\n                int old2 = ov[A][B];\n\n                int new1 = ov[D][B];\n                int new2 = ov[B][A];\n\n                delta = (new1 + new2) - (old1 + old2);\n                if (delta > 0) {\n                    swap(path[M - 2], path[M - 1]);\n                    edgeOv[M - 3] = new1;\n                    edgeOv[M - 2] = new2;\n                    totalOv += delta;\n                    improved = true;\n                }\n            } else {\n                int D = path[i - 1];\n                int A = path[i];\n                int B = path[i + 1];\n                int C = path[i + 2];\n\n                int old1 = ov[D][A];\n                int old2 = ov[A][B];\n                int old3 = ov[B][C];\n\n                int new1 = ov[D][B];\n                int new2 = ov[B][A];\n                int new3 = ov[A][C];\n\n                delta = (new1 + new2 + new3) - (old1 + old2 + old3);\n                if (delta > 0) {\n                    swap(path[i], path[i + 1]);\n                    edgeOv[i - 1] = new1;\n                    edgeOv[i] = new2;\n                    edgeOv[i + 1] = new3;\n                    totalOv += delta;\n                    improved = true;\n                }\n            }\n        }\n    }\n    return totalOv;\n}\n\n// DP cost computation without parent reconstruction\nint compute_cost_no_parent(\n    const string &S,\n    const vector<vector<int>> &dist,\n    const vector<vector<int>> &cellsByLetter,\n    int startIdx\n) {\n    int L = (int)S.size();\n    if (L == 0) return 0;\n    int G = (int)dist.size();\n\n    vector<int> dpPrev(G, INF), dpCur(G, INF);\n    vector<int> prevCells, curCells;\n    prevCells.reserve(G);\n    curCells.reserve(G);\n\n    int c0 = S[0] - 'A';\n    const auto &cand0 = cellsByLetter[c0];\n    prevCells.clear();\n    for (int cell : cand0) {\n        dpPrev[cell] = dist[startIdx][cell];\n        prevCells.push_back(cell);\n    }\n\n    for (int pos = 1; pos < L; ++pos) {\n        int c = S[pos] - 'A';\n        const auto &cand = cellsByLetter[c];\n        curCells.clear();\n\n        for (int b : cand) {\n            int best = INF;\n            for (int a : prevCells) {\n                int val = dpPrev[a] + dist[a][b];\n                if (val < best) best = val;\n            }\n            dpCur[b] = best;\n            curCells.push_back(b);\n        }\n\n        dpPrev.swap(dpCur);\n        prevCells.swap(curCells);\n    }\n\n    int bestCost = INF;\n    for (int a : prevCells) {\n        if (dpPrev[a] < bestCost) bestCost = dpPrev[a];\n    }\n    return bestCost;\n}\n\n// DP with parent reconstruction: returns sequence of cell indices\nvector<int> compute_path_with_parent(\n    const string &S,\n    const vector<vector<int>> &dist,\n    const vector<vector<int>> &cellsByLetter,\n    int startIdx\n) {\n    int L = (int)S.size();\n    int G = (int)dist.size();\n    vector<int> result(L);\n    if (L == 0) return result;\n\n    vector<vector<int>> parent(L, vector<int>(G, -1));\n    vector<int> dpPrev(G, INF), dpCur(G, INF);\n    vector<int> prevCells, curCells;\n    prevCells.reserve(G);\n    curCells.reserve(G);\n\n    int c0 = S[0] - 'A';\n    const auto &cand0 = cellsByLetter[c0];\n    prevCells.clear();\n    for (int cell : cand0) {\n        dpPrev[cell] = dist[startIdx][cell];\n        parent[0][cell] = startIdx;\n        prevCells.push_back(cell);\n    }\n\n    for (int pos = 1; pos < L; ++pos) {\n        int c = S[pos] - 'A';\n        const auto &cand = cellsByLetter[c];\n        curCells.clear();\n\n        for (int b : cand) {\n            int best = INF;\n            int bestPrevCell = -1;\n            for (int a : prevCells) {\n                int val = dpPrev[a] + dist[a][b];\n                if (val < best) {\n                    best = val;\n                    bestPrevCell = a;\n                }\n            }\n            dpCur[b] = best;\n            parent[pos][b] = bestPrevCell;\n            curCells.push_back(b);\n        }\n\n        dpPrev.swap(dpCur);\n        prevCells.swap(curCells);\n    }\n\n    int bestCost = INF;\n    int bestLastCell = -1;\n    for (int a : prevCells) {\n        if (dpPrev[a] < bestCost) {\n            bestCost = dpPrev[a];\n            bestLastCell = a;\n        }\n    }\n\n    int cell = bestLastCell;\n    for (int pos = L - 1; pos >= 0; --pos) {\n        result[pos] = cell;\n        cell = parent[pos][cell]; // for pos=0 this becomes startIdx; we ignore it\n    }\n\n    return result;\n}\n\n// Build superstring S from path and overlap matrix\nstring build_superstring(const vector<int> &path, const vector<string> &words, const vector<vector<int>> &ov) {\n    int M = (int)path.size();\n    string S = words[path[0]];\n    for (int i = 1; i < M; ++i) {\n        int prev = path[i - 1];\n        int cur = path[i];\n        int k = ov[prev][cur];\n        S.append(words[cur].begin() + k, words[cur].end());\n    }\n    return S;\n}\n\n// Relocation local search (on a copy of path) guided by overlap,\n// but evaluated by full DP; updates global best string and cost.\nvoid relocate_local_search_T(\n    vector<int> path,                 // copy\n    const vector<vector<int>> &ov,\n    const vector<string> &words,\n    const vector<vector<int>> &dist,\n    const vector<vector<int>> &cellsByLetter,\n    int startIdx,\n    int &globalBestT,\n    string &globalBestS\n) {\n    int M = (int)path.size();\n    if (M <= 2) return;\n\n    // Compute initial total overlap\n    int totalOv = 0;\n    for (int i = 0; i + 1 < M; ++i) {\n        totalOv += ov[path[i]][path[i + 1]];\n    }\n\n    bool improved = true;\n    while (improved) {\n        improved = false;\n        for (int i = 0; i < M; ++i) {\n            int Xi = path[i];\n            int Li = (i > 0 ? path[i - 1] : -1);\n            int Ri = (i + 1 < M ? path[i + 1] : -1);\n\n            int wLiX = (i > 0 ? ov[Li][Xi] : 0);\n            int wXRi = (i + 1 < M ? ov[Xi][Ri] : 0);\n            int wLiRi = (i > 0 && i + 1 < M ? ov[Li][Ri] : 0);\n\n            for (int j = 0; j < M; ++j) {\n                if (j == i || j == i - 1) continue;\n                int Aj = path[j];\n                int Bj = (j + 1 < M ? path[j + 1] : -1);\n\n                int wAjBj = (j + 1 < M ? ov[Aj][Bj] : 0);\n                int wAjX = ov[Aj][Xi];\n                int wXBj = (j + 1 < M ? ov[Xi][Bj] : 0);\n\n                int delta = 0;\n                // remove X from its position\n                if (i > 0) delta -= wLiX;\n                if (i + 1 < M) delta -= wXRi;\n                if (i > 0 && i + 1 < M) delta += wLiRi;\n                // break insertion edge\n                if (j + 1 < M) delta -= wAjBj;\n                // add new edges\n                delta += wAjX;\n                if (j + 1 < M) delta += wXBj;\n\n                if (delta > 0) {\n                    totalOv += delta;\n\n                    // Apply relocation (careful with indices)\n                    int from = i;\n                    int to = j + 1;\n                    if (from < to) {\n                        // Removing earlier shifts target left by 1\n                        path.erase(path.begin() + from);\n                        to--;\n                        path.insert(path.begin() + to, Xi);\n                    } else {\n                        path.erase(path.begin() + from);\n                        path.insert(path.begin() + to, Xi);\n                    }\n\n                    // Evaluate this new path with DP\n                    string S = build_superstring(path, words, ov);\n                    int T = compute_cost_no_parent(S, dist, cellsByLetter, startIdx);\n                    if (T < globalBestT) {\n                        globalBestT = T;\n                        globalBestS = move(S);\n                    }\n\n                    improved = true;\n                    goto NEXT_ITERATION;\n                }\n            }\n        }\n        NEXT_ITERATION:;\n    }\n}\n\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M;\n    if (!(cin >> N >> M)) {\n        return 0;\n    }\n    int si, sj;\n    cin >> si >> sj;\n    vector<string> grid(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> grid[i];\n    }\n\n    vector<string> words(M);\n    for (int i = 0; i < M; ++i) {\n        cin >> words[i];\n    }\n\n    int G = N * N;\n    int startIdx = si * N + sj;\n\n    // Precompute cell coordinates\n    vector<pair<int,int>> coord(G);\n    for (int idx = 0; idx < G; ++idx) {\n        coord[idx] = {idx / N, idx % N};\n    }\n\n    // Cells by letter\n    vector<vector<int>> cellsByLetter(26);\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            char c = grid[i][j];\n            int idx = i * N + j;\n            cellsByLetter[c - 'A'].push_back(idx);\n        }\n    }\n\n    // Distance matrix\n    vector<vector<int>> dist(G, vector<int>(G));\n    for (int a = 0; a < G; ++a) {\n        int ax = coord[a].first;\n        int ay = coord[a].second;\n        for (int b = 0; b < G; ++b) {\n            int bx = coord[b].first;\n            int by = coord[b].second;\n            dist[a][b] = abs(ax - bx) + abs(ay - by) + 1;\n        }\n    }\n\n    // Overlap matrix between words\n    vector<vector<int>> ov(M, vector<int>(M, 0));\n    for (int i = 0; i < M; ++i) {\n        for (int j = 0; j < M; ++j) {\n            if (i == j) continue;\n            ov[i][j] = compute_overlap(words[i], words[j]);\n        }\n    }\n\n    mt19937 rng(712367821);\n\n    const int numRestarts = 400;  // increased for better exploration\n\n    vector<vector<int>> allPaths;\n    allPaths.reserve(numRestarts);\n    vector<int> allTOT(numRestarts, 0);\n    vector<int> allT(numRestarts, INF);\n\n    int globalBestT = INF;\n    string globalBestS;\n\n    vector<int> path(M);\n    vector<char> used(M);\n\n    for (int r = 0; r < numRestarts; ++r) {\n        fill(used.begin(), used.end(), 0);\n        int startNode = (int)(rng() % M);\n        path[0] = startNode;\n        used[startNode] = 1;\n\n        // Greedy path by overlap\n        for (int pos = 1; pos < M; ++pos) {\n            int u = path[pos - 1];\n            int bestOv = -1;\n            vector<int> cands;\n            cands.reserve(M);\n\n            for (int v = 0; v < M; ++v) {\n                if (used[v]) continue;\n                int o = ov[u][v];\n                if (o > bestOv) {\n                    bestOv = o;\n                    cands.clear();\n                    cands.push_back(v);\n                } else if (o == bestOv) {\n                    cands.push_back(v);\n                }\n            }\n\n            int v = cands[rng() % cands.size()];\n            path[pos] = v;\n            used[v] = 1;\n        }\n\n        // Local search with adjacent swaps\n        int totalOv = local_search_adjacent_swaps(path, ov);\n\n        // Build superstring and evaluate DP cost\n        string S = build_superstring(path, words, ov);\n        int T = compute_cost_no_parent(S, dist, cellsByLetter, startIdx);\n\n        allPaths.push_back(path);\n        allTOT[r] = totalOv;\n        allT[r] = T;\n\n        if (T < globalBestT) {\n            globalBestT = T;\n            globalBestS = move(S);\n        }\n    }\n\n    // Find best by DP cost and by overlap\n    int idxBestT = 0;\n    int idxBestOv = 0;\n    for (int r = 0; r < (int)allPaths.size(); ++r) {\n        if (allT[r] < allT[idxBestT]) idxBestT = r;\n        if (allTOT[r] > allTOT[idxBestOv]) idxBestOv = r;\n    }\n\n    // Extra refinement: relocation-based local search on best by overlap\n    {\n        vector<int> pathCopy = allPaths[idxBestOv];\n        relocate_local_search_T(pathCopy, ov, words, dist, cellsByLetter, startIdx, globalBestT, globalBestS);\n    }\n    // And also on best by DP cost (if different)\n    if (idxBestT != idxBestOv) {\n        vector<int> pathCopy = allPaths[idxBestT];\n        relocate_local_search_T(pathCopy, ov, words, dist, cellsByLetter, startIdx, globalBestT, globalBestS);\n    }\n\n    // Reconstruct final finger path for the best string\n    vector<int> bestCells = compute_path_with_parent(globalBestS, dist, cellsByLetter, startIdx);\n\n    int L = (int)bestCells.size();\n    for (int pos = 0; pos < L; ++pos) {\n        int idx = bestCells[pos];\n        int x = idx / N;\n        int y = idx % N;\n        cout << x << ' ' << y << '\\n';\n    }\n\n    return 0;\n}","ahc030":"#include <bits/stdc++.h>\nusing namespace std;\n\n// Representation of each field's shape\nstruct Field {\n    int H, W;                             // bounding box size\n    vector<pair<int,int>> offsets;        // shape cells relative to (0,0)\n    vector<char> occ;                     // occupancy grid H x W: 1 if cell in shape\n};\n\n// A single candidate placement of a field\nstruct Placement {\n    int di, dj;                           // translation offset on the N x N grid\n    bool alive;                           // still possible?\n    vector<int> cells;                    // global cell indices covered by this placement\n};\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)) {\n        return 0;\n    }\n\n    int N2 = N * N;\n\n    // Read field shapes\n    vector<Field> fields(M);\n    for (int k = 0; k < M; ++k) {\n        int d;\n        cin >> d;\n        vector<pair<int,int>> cells(d);\n        int max_i = 0, max_j = 0;\n        for (int t = 0; t < d; ++t) {\n            int x, y;\n            cin >> x >> y;\n            cells[t] = {x, y};\n            if (x > max_i) max_i = x;\n            if (y > max_j) max_j = y;\n        }\n        Field &f = fields[k];\n        f.H = max_i + 1;\n        f.W = max_j + 1;\n        f.offsets = move(cells);\n        f.occ.assign(f.H * f.W, 0);\n        for (auto &p : f.offsets) {\n            int x = p.first, y = p.second;\n            f.occ[x * f.W + y] = 1;\n        }\n    }\n\n    // Build all candidate placements and cover counts\n    vector<vector<Placement>> placements(M);\n    vector<vector<int>> coverCount(M, vector<int>(N2, 0)); // coverCount[k][cell]\n    vector<int> totalCandidates(M, 0);\n\n    for (int k = 0; k < M; ++k) {\n        Field &f = fields[k];\n        for (int di = 0; di <= N - f.H; ++di) {\n            for (int dj = 0; dj <= N - f.W; ++dj) {\n                Placement p;\n                p.di = di;\n                p.dj = dj;\n                p.alive = true;\n                p.cells.reserve(f.offsets.size());\n                for (auto &off : f.offsets) {\n                    int i = di + off.first;\n                    int j = dj + off.second;\n                    int cid = i * N + j;\n                    p.cells.push_back(cid);\n                    coverCount[k][cid]++;\n                }\n                placements[k].push_back(move(p));\n                totalCandidates[k]++;\n            }\n        }\n    }\n\n    // Observed v(i,j); -1 means not drilled yet\n    vector<int> observed(N2, -1);\n\n    // Temporary arrays for min/max possible v for each cell\n    vector<int> minV(N2), maxV(N2);\n\n    // Helper lambda: recompute minV and maxV from current candidate sets\n    auto recomputeMinMax = [&]() {\n        for (int c = 0; c < N2; ++c) {\n            int mn = 0, mx = 0;\n            for (int k = 0; k < M; ++k) {\n                int tc = totalCandidates[k];\n                if (tc <= 0) continue; // should not happen\n                int cc = coverCount[k][c];\n                // min contribution: 1 iff all remaining placements of field k cover c\n                if (cc == tc) mn += 1;\n                // max contribution: 1 iff at least one placement covers c\n                if (cc > 0) mx += 1;\n            }\n            minV[c] = mn;\n            maxV[c] = mx;\n        }\n    };\n\n    // Main loop: drill cells until all undrilled cells have minV == maxV\n    int drilledCount = 0;\n    while (true) {\n        // Update minV / maxV based on current candidate sets\n        recomputeMinMax();\n\n        // Check if all undrilled cells are already determined\n        bool allKnown = true;\n        for (int c = 0; c < N2; ++c) {\n            if (observed[c] == -1) {\n                if (minV[c] < maxV[c]) {\n                    allKnown = false;\n                    break;\n                }\n            }\n        }\n        if (allKnown) break; // we know v(i,j) for every cell\n\n        // Safety: if we've drilled all cells, we must be done\n        if (drilledCount >= N2) break;\n\n        // Choose next cell to drill:\n        // pick undrilled cell with largest (maxV - minV) (highest uncertainty)\n        int bestCell = -1;\n        int bestScore = -1;\n        for (int c = 0; c < N2; ++c) {\n            if (observed[c] != -1) continue; // already drilled\n            int diff = maxV[c] - minV[c];\n            if (diff <= 0) continue;         // already determined\n            if (diff > bestScore) {\n                bestScore = diff;\n                bestCell = c;\n            }\n        }\n\n        // In principle, bestCell must exist here (since allKnown was false).\n        if (bestCell == -1) break; // fallback safety\n\n        int bi = bestCell / N;\n        int bj = bestCell % N;\n\n        // Drill this cell\n        cout << \"q 1 \" << bi << ' ' << bj << '\\n' << flush;\n        int v_resp;\n        if (!(cin >> v_resp)) return 0; // defensive\n        observed[bestCell] = v_resp;\n        drilledCount++;\n\n        // Use this observation to prune candidate placements\n        int c = bestCell;\n        int observed_v = v_resp;\n\n        // For contribution calculations we use current minV/maxV (before removing)\n        for (int k = 0; k < M; ++k) {\n            int tc_before = totalCandidates[k];\n            if (tc_before <= 0) continue; // should not happen\n\n            int cc = coverCount[k][c];\n            bool minCk = (cc == tc_before); // all placements of k cover c?\n            bool maxCk = (cc > 0);          // some placement covers c?\n\n            int min_without_k = minV[c] - (minCk ? 1 : 0);\n            int max_without_k = maxV[c] - (maxCk ? 1 : 0);\n\n            Field &f = fields[k];\n\n            // For this field k, test each alive placement against the new constraint\n            for (int pi = 0; pi < (int)placements[k].size(); ++pi) {\n                Placement &p = placements[k][pi];\n                if (!p.alive) continue;\n\n                // Determine whether this placement covers cell c\n                int di = p.di, dj = p.dj;\n                int ci = c / N;\n                int cj = c % N;\n                int delta = 0;\n                int li = ci - di;\n                int lj = cj - dj;\n                if (0 <= li && li < f.H && 0 <= lj && lj < f.W) {\n                    if (f.occ[li * f.W + lj]) {\n                        delta = 1;\n                    }\n                }\n\n                int min_possible = delta + min_without_k;\n                int max_possible = delta + max_without_k;\n\n                if (observed_v < min_possible || observed_v > max_possible) {\n                    // This placement cannot be part of any configuration consistent\n                    // with this observation; remove it.\n                    p.alive = false;\n                    totalCandidates[k]--;\n                    // Update cover counts for all cells covered by this placement\n                    for (int cell2 : p.cells) {\n                        coverCount[k][cell2]--;\n                    }\n                }\n            }\n        }\n    }\n\n    // Now we know v(i,j) for all cells either by drilling or by minV==maxV.\n    // Recompute minV/maxV one last time for consistency.\n    recomputeMinMax();\n\n    vector<pair<int,int>> has_oil;\n    has_oil.reserve(N2);\n    for (int c = 0; c < N2; ++c) {\n        int val;\n        if (observed[c] != -1) {\n            val = observed[c];\n        } else {\n            // Undrilled but determined by constraints\n            // (by construction, minV[c] == maxV[c] here)\n            val = minV[c];\n        }\n        if (val > 0) {\n            int i = c / N;\n            int j = c % N;\n            has_oil.emplace_back(i, j);\n        }\n    }\n\n    // Output the answer\n    cout << \"a \" << has_oil.size();\n    for (auto &p : has_oil) {\n        cout << ' ' << p.first << ' ' << p.second;\n    }\n    cout << '\\n' << flush;\n\n    // Read verdict (1 = correct, 0 = wrong); should be 1 if logic is correct.\n    int verdict;\n    if (!(cin >> verdict)) return 0;\n\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    if (!(cin >> W >> D >> N)) return 0;\n\n    // Read a[d][k]; guaranteed non-decreasing in k for each d.\n    vector<vector<long long>> a(D, vector<long long>(N));\n    for (int d = 0; d < D; d++) {\n        for (int k = 0; k < N; k++) {\n            cin >> a[d][k];\n        }\n    }\n\n    // For each day, determine widths for vertical stripes\n    // and output rectangles.\n    for (int d = 0; d < D; d++) {\n        const auto &ad = a[d];\n\n        // Width of each stripe assigned to reservation k\n        vector<int> w(N, 1);  // minimum width 1\n        int widthSum = N;     // total used width so far\n\n        // Max-heap of (residual shortfall, index)\n        // residual r_k = max(a_k - W * w_k, 0)\n        priority_queue<pair<long long,int>> pq;\n        long long baseAreaPerUnit = (long long)W; // height=W, width=1\n\n        for (int k = 0; k < N; k++) {\n            long long r = ad[k] - baseAreaPerUnit; // after giving width=1\n            if (r > 0) {\n                pq.emplace(r, k);\n            }\n        }\n\n        // Allocate extra width units greedily to minimize shortage\n        while (widthSum < W && !pq.empty()) {\n            auto [r, idx] = pq.top();\n            pq.pop();\n            if (r <= 0) break;  // no useful residuals left (shouldn't happen because we only push r>0)\n\n            // Give one more unit of width to this reservation\n            w[idx]++;\n            widthSum++;\n\n            r -= baseAreaPerUnit;\n            if (r > 0) {\n                pq.emplace(r, idx);\n            }\n        }\n\n        // Now construct vertical stripes with these widths.\n        // Stripes are placed from left to right; remaining width (if any) is unused.\n        int x = 0;\n        for (int k = 0; k < N; k++) {\n            int j0 = x;\n            int j1 = x + w[k];\n            x = j1;\n\n            int i0 = 0;\n            int i1 = W;\n\n            // Safety clamp (though x should never exceed W)\n            if (j1 > W) j1 = W;\n\n            cout << i0 << ' ' << j0 << ' ' << i1 << ' ' << j1 << '\\n';\n        }\n    }\n\n    return 0;\n}","ahc032":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const long long MOD = 998244353LL;\n\n// Fast RNG (xorshift64)\nstruct XorShift64 {\n    uint64_t x;\n    XorShift64(uint64_t seed = 88172645463325252ull) {\n        x = seed ? seed : 88172645463325252ull;\n    }\n    inline uint64_t next() {\n        uint64_t y = x;\n        y ^= y << 7;\n        y ^= y >> 9;\n        return x = y;\n    }\n    inline int next_int(int n) { // 0..n-1\n        return (int)(next() % (uint64_t)n);\n    }\n    inline double next_double() { // [0,1)\n        return (next() >> 11) * (1.0 / (1ULL << 53));\n    }\n};\n\nstruct Op {\n    int m;\n    int p;\n    int q;\n};\n\nstruct CellChange {\n    int idx;\n    int oldv;\n    int newv;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, K;\n    if (!(cin >> N >> M >> K)) return 0;\n\n    const int NN = N * N;\n\n    // Read initial board and keep a copy\n    vector<int> initial_board(NN);\n    long long initial_score = 0;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            long long v;\n            cin >> v;\n            v %= MOD;\n            initial_board[i * N + j] = (int)v;\n            initial_score += v;\n        }\n    }\n\n    // Read stamps s[m][3][3]\n    static int s[20][3][3]; // M <= 20\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                long long v;\n                cin >> v;\n                v %= MOD;\n                s[m][i][j] = (int)v;\n            }\n        }\n    }\n\n    // Precompute all candidate operations (m, p, q)\n    vector<Op> all_ops;\n    all_ops.reserve(M * (N - 2) * (N - 2));\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                all_ops.push_back({m, p, q});\n            }\n        }\n    }\n    const int NUM_OPS = (int)all_ops.size(); // for N=9,M=20 => 980\n\n    // Precompute for each op: its 9 cell indices and values\n    vector<array<int, 9>> op_cells(NUM_OPS);\n    vector<array<int, 9>> op_vals(NUM_OPS);\n    // For fast lookup: for each op, a map board_idx -> pos (0..8) or -1\n    vector<array<int8_t, 81>> op_pos(NUM_OPS);\n\n    for (int op_id = 0; op_id < NUM_OPS; ++op_id) {\n        const Op &op = all_ops[op_id];\n        int m = op.m, p = op.p, q = op.q;\n        array<int, 9> cells;\n        array<int, 9> vals;\n        int t = 0;\n        for (int di = 0; di < 3; ++di) {\n            int r = p + di;\n            int base = r * N;\n            for (int dj = 0; dj < 3; ++dj) {\n                int c = q + dj;\n                int idx = base + c;\n                cells[t] = idx;\n                vals[t] = s[m][di][dj];\n                ++t;\n            }\n        }\n        op_cells[op_id] = cells;\n        op_vals[op_id] = vals;\n\n        // fill position map\n        auto &pos_map = op_pos[op_id];\n        pos_map.fill(-1);\n        for (int i = 0; i < 9; ++i) {\n            int idx = cells[i];\n            pos_map[idx] = (int8_t)i;\n        }\n    }\n\n    // Initialize RNG\n    uint64_t seed = chrono::high_resolution_clock::now().time_since_epoch().count();\n    XorShift64 rng(seed);\n\n    // Work board and score\n    vector<int> board = initial_board;\n    long long cur_score = initial_score;\n    vector<int> cur_ops;\n    cur_ops.reserve(K);\n\n    // Greedy initial solution: add best positive operation up to K times\n    for (int step = 0; step < K; ++step) {\n        long long best_delta = 0;\n        int best_id = -1;\n        for (int op_id = 0; op_id < NUM_OPS; ++op_id) {\n            const auto &cells = op_cells[op_id];\n            const auto &vals  = op_vals[op_id];\n            long long delta = 0;\n            for (int t = 0; t < 9; ++t) {\n                int idx = cells[t];\n                int d   = vals[t];\n                if (d == 0) continue;\n                int x = board[idx];\n                int tmp = x + d;\n                if (tmp >= MOD) tmp -= MOD;\n                delta += tmp - x;\n            }\n            if (delta > best_delta) {\n                best_delta = delta;\n                best_id = op_id;\n            }\n        }\n        if (best_id == -1 || best_delta <= 0) break;\n\n        // Apply best operation\n        const auto &cells = op_cells[best_id];\n        const auto &vals  = op_vals[best_id];\n        for (int t = 0; t < 9; ++t) {\n            int idx = cells[t];\n            int d   = vals[t];\n            if (d == 0) continue;\n            int x = board[idx];\n            int tmp = x + d;\n            if (tmp >= MOD) tmp -= MOD;\n            board[idx] = tmp;\n        }\n        cur_score += best_delta;\n        cur_ops.push_back(best_id);\n    }\n\n    long long best_score = cur_score;\n    vector<int> best_ops = cur_ops;\n\n    // Simulated Annealing\n    const double SA_TIME_LIMIT = 1.6; // seconds for SA\n    auto time_start = chrono::steady_clock::now();\n\n    const double T0 = 1e9;\n    const double T_end = 1e6;\n    double T = T0;\n\n    CellChange changes[18]; // max affected cells in REPLACE: union of two 3x3 patches\n    int iteration = 0;\n\n    while (true) {\n        if ((iteration & 1023) == 0) {\n            auto now = chrono::steady_clock::now();\n            double elapsed = chrono::duration<double>(now - time_start).count();\n            if (elapsed >= SA_TIME_LIMIT) break;\n            double progress = elapsed / SA_TIME_LIMIT;\n            if (progress > 1.0) progress = 1.0;\n            T = T0 + (T_end - T0) * progress;\n        }\n        ++iteration;\n\n        int L = (int)cur_ops.size();\n        int move_type; // 0=ADD, 1=REMOVE, 2=REPLACE\n        if (L == 0) {\n            move_type = 0;\n        } else if (L == K) {\n            move_type = (rng.next_int(2) == 0 ? 1 : 2);\n        } else {\n            int r = rng.next_int(100);\n            if (r < 40) move_type = 0;        // 40% ADD\n            else if (r < 80) move_type = 2;   // 40% REPLACE\n            else move_type = 1;               // 20% REMOVE\n        }\n\n        long long deltaScore = 0;\n        int chN = 0;\n\n        if (move_type == 0) { // ADD\n            int op_new = rng.next_int(NUM_OPS);\n            const auto &cells = op_cells[op_new];\n            const auto &vals  = op_vals[op_new];\n\n            deltaScore = 0;\n            chN = 0;\n            for (int t = 0; t < 9; ++t) {\n                int d = vals[t];\n                if (d == 0) continue;\n                int idx = cells[t];\n                int x = board[idx];\n                int tmp = x + d;\n                if (tmp >= MOD) tmp -= MOD;\n                if (tmp != x) {\n                    deltaScore += tmp - x;\n                    changes[chN++] = {idx, x, tmp};\n                }\n            }\n\n            bool accept;\n            if (deltaScore >= 0) {\n                accept = true;\n            } else if (-deltaScore > 20.0 * T) {\n                accept = false;\n            } else {\n                double prob = exp((double)deltaScore / T);\n                accept = (rng.next_double() < prob);\n            }\n\n            if (accept) {\n                for (int i = 0; i < chN; ++i) {\n                    board[changes[i].idx] = changes[i].newv;\n                }\n                cur_score += deltaScore;\n                cur_ops.push_back(op_new);\n                if (cur_score > best_score) {\n                    best_score = cur_score;\n                    best_ops = cur_ops;\n                }\n            }\n\n        } else if (move_type == 1) { // REMOVE\n            if (L == 0) continue;\n            int idx_op = rng.next_int(L);\n            int op_old = cur_ops[idx_op];\n            const auto &cells = op_cells[op_old];\n            const auto &vals  = op_vals[op_old];\n\n            deltaScore = 0;\n            chN = 0;\n            for (int t = 0; t < 9; ++t) {\n                int d = vals[t];\n                if (d == 0) continue;\n                int idx = cells[t];\n                int x = board[idx];\n                int tmp = x - d;\n                if (tmp < 0) tmp += MOD;\n                if (tmp != x) {\n                    deltaScore += tmp - x;\n                    changes[chN++] = {idx, x, tmp};\n                }\n            }\n\n            bool accept;\n            if (deltaScore >= 0) {\n                accept = true;\n            } else if (-deltaScore > 20.0 * T) {\n                accept = false;\n            } else {\n                double prob = exp((double)deltaScore / T);\n                accept = (rng.next_double() < prob);\n            }\n\n            if (accept) {\n                for (int i = 0; i < chN; ++i) {\n                    board[changes[i].idx] = changes[i].newv;\n                }\n                cur_score += deltaScore;\n                cur_ops[idx_op] = cur_ops.back();\n                cur_ops.pop_back();\n                if (cur_score > best_score) {\n                    best_score = cur_score;\n                    best_ops = cur_ops;\n                }\n            }\n\n        } else { // REPLACE\n            if (L == 0) continue;\n            int idx_old = rng.next_int(L);\n            int op_old = cur_ops[idx_old];\n            int op_new = rng.next_int(NUM_OPS);\n            if (op_new == op_old) continue;\n\n            const auto &cellsOld = op_cells[op_old];\n            const auto &valsOld  = op_vals[op_old];\n            const auto &cellsNew = op_cells[op_new];\n            const auto &valsNew  = op_vals[op_new];\n\n            // Build union of affected cells\n            int idxList[18];\n            int uc = 0;\n            for (int t = 0; t < 9; ++t) {\n                idxList[uc++] = cellsOld[t];\n            }\n            for (int t = 0; t < 9; ++t) {\n                int idx = cellsNew[t];\n                bool found = false;\n                for (int z = 0; z < uc; ++z) {\n                    if (idxList[z] == idx) {\n                        found = true;\n                        break;\n                    }\n                }\n                if (!found) idxList[uc++] = idx;\n            }\n\n            deltaScore = 0;\n            chN = 0;\n            auto &posOldMap = op_pos[op_old];\n            auto &posNewMap = op_pos[op_new];\n\n            for (int t = 0; t < uc; ++t) {\n                int idx = idxList[t];\n                int x = board[idx];\n\n                int posOld = (int)posOldMap[idx];\n                int d_old = (posOld >= 0 ? valsOld[posOld] : 0);\n\n                int posNew = (int)posNewMap[idx];\n                int d_new = (posNew >= 0 ? valsNew[posNew] : 0);\n\n                int diff = d_new - d_old;\n                if (diff == 0) continue;\n\n                int tmp = x + diff;\n                if (tmp < 0) tmp += MOD;\n                else if (tmp >= MOD) tmp -= MOD;\n\n                if (tmp != x) {\n                    deltaScore += tmp - x;\n                    changes[chN++] = {idx, x, tmp};\n                }\n            }\n\n            bool accept;\n            if (deltaScore >= 0) {\n                accept = true;\n            } else if (-deltaScore > 20.0 * T) {\n                accept = false;\n            } else {\n                double prob = exp((double)deltaScore / T);\n                accept = (rng.next_double() < prob);\n            }\n\n            if (accept) {\n                for (int i = 0; i < chN; ++i) {\n                    board[changes[i].idx] = changes[i].newv;\n                }\n                cur_score += deltaScore;\n                cur_ops[idx_old] = op_new;\n                if (cur_score > best_score) {\n                    best_score = cur_score;\n                    best_ops = cur_ops;\n                }\n            }\n        }\n    }\n\n    // Final greedy local improvement (hill-climbing) on best solution\n    vector<int> sol_ops = best_ops;\n    vector<int> boardHC = initial_board;\n    long long scoreHC = initial_score;\n\n    // Rebuild boardHC and scoreHC from sol_ops\n    for (int op_id : sol_ops) {\n        const auto &cells = op_cells[op_id];\n        const auto &vals  = op_vals[op_id];\n        for (int t = 0; t < 9; ++t) {\n            int d = vals[t];\n            if (d == 0) continue;\n            int idx = cells[t];\n            int x = boardHC[idx];\n            int tmp = x + d;\n            if (tmp >= MOD) tmp -= MOD;\n            boardHC[idx] = tmp;\n            scoreHC += tmp - x;\n        }\n    }\n\n    // Local search: best ADD / best REMOVE until no improvement or iteration cap\n    const int MAX_HC_ITERS = 2000;\n    for (int iter = 0; iter < MAX_HC_ITERS; ++iter) {\n        int L = (int)sol_ops.size();\n\n        long long bestAddDelta = 0;\n        int bestAddOp = -1;\n        if (L < K) {\n            for (int op_id = 0; op_id < NUM_OPS; ++op_id) {\n                const auto &cells = op_cells[op_id];\n                const auto &vals  = op_vals[op_id];\n                long long delta = 0;\n                for (int t = 0; t < 9; ++t) {\n                    int d = vals[t];\n                    if (d == 0) continue;\n                    int idx = cells[t];\n                    int x = boardHC[idx];\n                    int tmp = x + d;\n                    if (tmp >= MOD) tmp -= MOD;\n                    delta += tmp - x;\n                }\n                if (delta > bestAddDelta) {\n                    bestAddDelta = delta;\n                    bestAddOp = op_id;\n                }\n            }\n        }\n\n        long long bestRemDelta = 0;\n        int bestRemIdx = -1;\n        for (int i = 0; i < L; ++i) {\n            int op_id = sol_ops[i];\n            const auto &cells = op_cells[op_id];\n            const auto &vals  = op_vals[op_id];\n            long long delta = 0;\n            for (int t = 0; t < 9; ++t) {\n                int d = vals[t];\n                if (d == 0) continue;\n                int idx = cells[t];\n                int x = boardHC[idx];\n                int tmp = x - d;\n                if (tmp < 0) tmp += MOD;\n                delta += tmp - x;\n            }\n            if (delta > bestRemDelta) {\n                bestRemDelta = delta;\n                bestRemIdx = i;\n            }\n        }\n\n        if (bestAddDelta <= 0 && bestRemDelta <= 0) break;\n\n        if (bestAddDelta >= bestRemDelta && bestAddDelta > 0 && L < K && bestAddOp != -1) {\n            // Apply best add\n            const auto &cells = op_cells[bestAddOp];\n            const auto &vals  = op_vals[bestAddOp];\n            for (int t = 0; t < 9; ++t) {\n                int d = vals[t];\n                if (d == 0) continue;\n                int idx = cells[t];\n                int x = boardHC[idx];\n                int tmp = x + d;\n                if (tmp >= MOD) tmp -= MOD;\n                boardHC[idx] = tmp;\n                scoreHC += tmp - x;\n            }\n            sol_ops.push_back(bestAddOp);\n        } else if (bestRemDelta > 0 && bestRemIdx != -1) {\n            // Apply best remove\n            int op_id = sol_ops[bestRemIdx];\n            const auto &cells = op_cells[op_id];\n            const auto &vals  = op_vals[op_id];\n            for (int t = 0; t < 9; ++t) {\n                int d = vals[t];\n                if (d == 0) continue;\n                int idx = cells[t];\n                int x = boardHC[idx];\n                int tmp = x - d;\n                if (tmp < 0) tmp += MOD;\n                boardHC[idx] = tmp;\n                scoreHC += tmp - x;\n            }\n            sol_ops[bestRemIdx] = sol_ops.back();\n            sol_ops.pop_back();\n        } else {\n            break;\n        }\n    }\n\n    // Output final solution\n    cout << (int)sol_ops.size() << '\\n';\n    for (int op_id : sol_ops) {\n        const Op &op = all_ops[op_id];\n        cout << op.m << ' ' << op.p << ' ' << op.q << '\\n';\n    }\n\n    return 0;\n}","ahc033":"#include <bits/stdc++.h>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    if (!(cin >> N)) return 0;  // N=5\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    const int totalContainers = N * N; // 25\n\n    // For each container id, which receiving row does it spawn from?\n    vector<int> spawnRow(totalContainers);\n    for (int r = 0; r < N; ++r) {\n        for (int j = 0; j < N; ++j) {\n            int id = A[r][j];\n            spawnRow[id] = r;\n        }\n    }\n\n    // Grid of containers: -1 means empty; otherwise container id\n    vector<vector<int>> grid(N, vector<int>(N, -1));\n\n    // Container states\n    // 0 = not spawned, 1 = on grid, 2 = carried, 3 = dispatched\n    const int NOT_SPAWNED = 0, ON_GRID = 1, CARRIED = 2, DISPATCHED = 3;\n    vector<int> state(totalContainers, NOT_SPAWNED);\n\n    // Receiving spawn index for each row (how many from A[row] already spawned)\n    int next_idx[5] = {0, 0, 0, 0, 0};\n    bool spawn_done[5] = {false, false, false, false, false};\n\n    // Big crane\n    int bx = 0, by = 0; // position\n    int carry = -1;     // carried container id, -1 if none\n\n    // Operation strings for all cranes\n    vector<string> ops(N);\n\n    int dispatched_count = 0;\n    int curId = 0;   // next container id to dispatch (global order)\n\n    auto stepTowards = [&](int gx, int gy) -> char {\n        if (bx < gx) return 'D';\n        if (bx > gx) return 'U';\n        if (by < gy) return 'R';\n        if (by > gy) return 'L';\n        return '.';\n    };\n\n    const int MAX_TURNS = 10000;\n    for (int t = 0; t < MAX_TURNS && dispatched_count < totalContainers; ++t) {\n        // Step 0: advance curId if some early ids already dispatched\n        while (curId < totalContainers && state[curId] == DISPATCHED) curId++;\n\n        // Step 1: spawn containers at receiving gates\n        for (int r = 0; r < N; ++r) {\n            if (next_idx[r] < N &&\n                grid[r][0] == -1 &&\n                !(carry != -1 && bx == r && by == 0)) { // gate free and not blocked by carrying crane\n                int id = A[r][next_idx[r]];\n                grid[r][0] = id;\n                state[id] = ON_GRID;\n                ++next_idx[r];\n                if (next_idx[r] == N) spawn_done[r] = true;\n            }\n        }\n\n        // Step 2: decide big crane command\n        char big_cmd = '.';\n\n        if (curId >= totalContainers) {\n            big_cmd = '.';\n        } else if (carry != -1) {\n            int id = carry;\n            if (id == curId) {\n                // Deliver to dispatch gate of its dispatch row\n                int dr = id / N;\n                int gx = dr, gy = N - 1;\n                if (bx == gx && by == gy) {\n                    big_cmd = 'Q';\n                } else {\n                    big_cmd = stepTowards(gx, gy);\n                }\n            } else {\n                // Store this container (id > curId)\n                bool canStoreHere = (by >= 1 && by <= N - 2 && grid[bx][by] == -1);\n                if (canStoreHere) {\n                    big_cmd = 'Q';\n                } else {\n                    int bestX = -1, bestY = -1;\n                    int bestDist = INT_MAX;\n\n                    // Prefer interior cells (1..N-2) as storage\n                    for (int x = 0; x < N; ++x) {\n                        for (int y = 1; y <= N - 2; ++y) {\n                            if (grid[x][y] == -1) {\n                                int dist = abs(bx - x) + abs(by - y);\n                                if (dist < bestDist) {\n                                    bestDist = dist;\n                                    bestX = x;\n                                    bestY = y;\n                                }\n                            }\n                        }\n                    }\n                    // If none, use gates of rows whose spawn is complete\n                    if (bestX == -1) {\n                        for (int x = 0; x < N; ++x) {\n                            if (spawn_done[x] && grid[x][0] == -1) {\n                                int dist = abs(bx - x) + abs(by - 0);\n                                if (dist < bestDist) {\n                                    bestDist = dist;\n                                    bestX = x;\n                                    bestY = 0;\n                                }\n                            }\n                        }\n                    }\n                    if (bestX == -1) {\n                        // Fallback: dispatch out-of-order (should almost never happen)\n                        int dr = id / N;\n                        int gx = dr, gy = N - 1;\n                        if (bx == gx && by == gy) {\n                            big_cmd = 'Q';\n                        } else {\n                            big_cmd = stepTowards(gx, gy);\n                        }\n                    } else {\n                        if (bx == bestX && by == bestY) {\n                            big_cmd = 'Q';\n                        } else {\n                            big_cmd = stepTowards(bestX, bestY);\n                        }\n                    }\n                }\n            }\n        } else { // carry == -1\n            if (state[curId] == ON_GRID) {\n                // curId is already on the grid; go pick it\n                int cx = -1, cy = -1;\n                for (int i = 0; i < N; ++i) {\n                    for (int j = 0; j < N; ++j) {\n                        if (grid[i][j] == curId) {\n                            cx = i;\n                            cy = j;\n                        }\n                    }\n                }\n                if (cx != -1) {\n                    if (bx == cx && by == cy) {\n                        big_cmd = 'P';\n                    } else {\n                        big_cmd = stepTowards(cx, cy);\n                    }\n                } else {\n                    // Should not happen; just idle\n                    big_cmd = '.';\n                }\n            } else if (state[curId] == NOT_SPAWNED) {\n                // Need to spawn curId from its spawn row: clear blockers at its gate\n                int sr = spawnRow[curId];\n                if (grid[sr][0] != -1) {\n                    // Pick blocking container from gate (sr,0)\n                    if (bx == sr && by == 0) {\n                        big_cmd = 'P';\n                    } else {\n                        big_cmd = stepTowards(sr, 0);\n                    }\n                } else {\n                    // Gate empty: wait for next spawn\n                    big_cmd = '.';\n                }\n            } else {\n                // DISPATCHED (already handled by curId advance) or inconsistent; idle\n                big_cmd = '.';\n            }\n        }\n\n        // Small cranes: bomb at t=0, then do nothing\n        char small_cmd = (t == 0 ? 'B' : '.');\n\n        ops[0].push_back(big_cmd);\n        for (int i = 1; i < N; ++i) ops[i].push_back(small_cmd);\n\n        // Step 2: apply big crane action\n        if (big_cmd == 'P') {\n            if (carry == -1 && grid[bx][by] != -1) {\n                carry = grid[bx][by];\n                state[carry] = CARRIED;\n                grid[bx][by] = -1;\n            }\n        } else if (big_cmd == 'Q') {\n            if (carry != -1 && grid[bx][by] == -1) {\n                grid[bx][by] = carry;\n                state[carry] = ON_GRID;\n                carry = -1;\n            }\n        } else if (big_cmd == 'U') {\n            if (bx > 0) --bx;\n        } else if (big_cmd == 'D') {\n            if (bx < N - 1) ++bx;\n        } else if (big_cmd == 'L') {\n            if (by > 0) --by;\n        } else if (big_cmd == 'R') {\n            if (by < N - 1) ++by;\n        } else {\n            // '.', 'B': no movement for big crane\n        }\n\n        // Step 3: dispatch containers at right edge\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                state[id] = DISPATCHED;\n                ++dispatched_count;\n            }\n        }\n    }\n\n    // Output operations\n    for (int i = 0; i < N; ++i) {\n        cout << ops[i] << '\\n';\n    }\n\n    return 0;\n}","ahc034":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int MAXN = 20;\nconst int TOT_LIMIT = 100000;  // Hard limit from problem\nconst int LIMIT_GREEDY = 90000; // Cap for greedy stage, leave room for fallback\n\nint N;\nlong long h[MAXN][MAXN];\nvector<string> ops;\n\nint cur_r = 0, cur_c = 0;   // current truck position\nlong long load_truck = 0;   // current truck load\n\nvector<pair<int,int>> snakePath;\n\n// Move truck from current (cur_r, cur_c) to (tr, tc) along Manhattan path\nvoid move_to(int tr, int tc) {\n    while (cur_r < tr) {\n        ++cur_r;\n        ops.emplace_back(\"D\");\n    }\n    while (cur_r > tr) {\n        --cur_r;\n        ops.emplace_back(\"U\");\n    }\n    while (cur_c < tc) {\n        ++cur_c;\n        ops.emplace_back(\"R\");\n    }\n    while (cur_c > tc) {\n        --cur_c;\n        ops.emplace_back(\"L\");\n    }\n}\n\n// Find nearest cell of given sign from current position.\n// sign = +1: h > 0 (positive), sign = -1: h < 0 (negative).\n// Tie-break by larger |h|.\npair<int,int> findNearest(int sign) {\n    int bestR = -1, bestC = -1;\n    int bestd = INT_MAX;\n    long long bestVal = -1;\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            long long v = h[i][j];\n            if (sign == 1) {\n                if (v <= 0) continue;\n                int d = abs(i - cur_r) + abs(j - cur_c);\n                if (d < bestd || (d == bestd && v > bestVal)) {\n                    bestd = d;\n                    bestVal = v;\n                    bestR = i;\n                    bestC = j;\n                }\n            } else {\n                if (v >= 0) continue;\n                int d = abs(i - cur_r) + abs(j - cur_c);\n                long long absV = -v;\n                if (d < bestd || (d == bestd && absV > bestVal)) {\n                    bestd = d;\n                    bestVal = absV;\n                    bestR = i;\n                    bestC = j;\n                }\n            }\n        }\n    }\n    return {bestR, bestC};\n}\n\n// Stage 1: greedy shipping between nearest positives and negatives\nvoid greedy_phase() {\n    long long base_total = 0;\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            base_total += llabs(h[i][j]);\n\n    while (base_total > 0 && (int)ops.size() < LIMIT_GREEDY) {\n        if (load_truck == 0) {\n            // Need a positive cell\n            auto [pr, pc] = findNearest(+1);\n            if (pr == -1) break; // should not happen in a correct state\n            move_to(pr, pc);\n\n            long long v = h[pr][pc];\n            if (v > 0) {\n                long long d = v;\n                ops.emplace_back(\"+\" + to_string(d));\n                load_truck += d;\n                h[pr][pc] = 0;\n                base_total -= d;\n            }\n        } else {\n            // We have load, need a negative cell\n            auto [nr, nc] = findNearest(-1);\n            if (nr == -1) break; // should not happen if total sum is 0\n            move_to(nr, nc);\n\n            long long v = h[nr][nc];\n            if (v < 0) {\n                long long need = -v;\n                long long d = min(load_truck, need);\n                ops.emplace_back(\"-\" + to_string(d));\n                load_truck -= d;\n                h[nr][nc] += d;\n                base_total -= d;\n            }\n        }\n    }\n}\n\n// Build snake Hamiltonian path for fallback\nvoid buildSnakePath() {\n    snakePath.clear();\n    for (int i = 0; i < N; ++i) {\n        if (i % 2 == 0) {\n            for (int j = 0; j < N; ++j) {\n                snakePath.emplace_back(i, j);\n            }\n        } else {\n            for (int j = N - 1; j >= 0; --j) {\n                snakePath.emplace_back(i, j);\n            }\n        }\n    }\n}\n\n// Stage 2: fallback using two-pass snake sweep\nvoid fallback_snake() {\n    // Unload everything at current cell to make load_truck zero\n    if (load_truck > 0) {\n        ops.emplace_back(\"-\" + to_string(load_truck));\n        h[cur_r][cur_c] += load_truck;\n        load_truck = 0;\n    }\n\n    // Move to (0,0) which is snakePath[0]\n    move_to(0, 0);\n\n    int M = (int)snakePath.size();\n\n    // Forward pass\n    for (int idx = 0; idx < M; ++idx) {\n        int r = snakePath[idx].first;\n        int c = snakePath[idx].second;\n        move_to(r, c);\n\n        long long v = h[r][c];\n        if (v > 0) {\n            long long d = v;\n            ops.emplace_back(\"+\" + to_string(d));\n            load_truck += d;\n            h[r][c] = 0;\n        } else if (v < 0 && load_truck > 0) {\n            long long need = -v;\n            long long d = min(load_truck, need);\n            ops.emplace_back(\"-\" + to_string(d));\n            load_truck -= d;\n            h[r][c] += d;\n        }\n    }\n\n    // Backward pass\n    for (int idx = M - 1; idx >= 0; --idx) {\n        int r = snakePath[idx].first;\n        int c = snakePath[idx].second;\n        move_to(r, c);\n\n        long long v = h[r][c];\n        if (v < 0 && load_truck > 0) {\n            long long need = -v;\n            long long d = min(load_truck, need);\n            ops.emplace_back(\"-\" + to_string(d));\n            load_truck -= d;\n            h[r][c] += d;\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    if (!(cin >> N)) return 0;\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            cin >> h[i][j];\n\n    cur_r = 0;\n    cur_c = 0;\n    load_truck = 0;\n\n    buildSnakePath();\n    greedy_phase();\n\n    // Check if everything is leveled\n    bool all_zero = true;\n    for (int i = 0; i < N && all_zero; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (h[i][j] != 0) {\n                all_zero = false;\n                break;\n            }\n        }\n    }\n\n    if (!all_zero && (int)ops.size() < TOT_LIMIT) {\n        fallback_snake();\n    }\n\n    // Absolute safety: never output more than 100000 operations\n    if ((int)ops.size() > TOT_LIMIT) {\n        ops.resize(TOT_LIMIT);\n    }\n\n    for (const string &s : ops) {\n        cout << s << '\\n';\n    }\n    return 0;\n}","ahc035":"#include <bits/stdc++.h>\nusing namespace std;\n\n/*\n Heuristic strategy (improved):\n\n - N=6, M=15, T=10 fixed.\n - Seed count per generation: S = 2*N*(N - 1) = 60.\n - Each turn:\n   1) Compute normalized scores using global per-dim maxima from initial seeds.\n   2) Select 36 seeds:\n        - dimension champions (best for each dimension),\n        - fill remaining slots with highest normalized total score.\n   3) Compute pairwise \"synergy\" S(a,b) = sum_l max(x_a_l, x_b_l)/X_l.\n   4) Build a good initial placement:\n        - sort selected seeds by strength (normalized V),\n        - sort positions by degree (center > edge > corner),\n        - greedily place seeds to positions maximizing incremental synergy.\n   5) Hill-climb the placement by random swaps (200k iterations).\n   6) Output the arrangement, then read the next generation seeds.\n*/\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, T;\n    if (!(cin >> N >> M >> T)) return 0;\n\n    const int SEED_COUNT = 2 * N * (N - 1); // 60 for N=6\n    const int SZ = N * N;                   // 36 for N=6\n    const int MAXS = 60;                    // max seed count\n\n    // Current seeds: x[k][l]\n    vector<vector<int>> x(SEED_COUNT, vector<int>(M));\n    for (int i = 0; i < SEED_COUNT; i++) {\n        for (int l = 0; l < M; l++) cin >> x[i][l];\n    }\n\n    // Global per-dimension maxima from initial seeds\n    vector<int> X_global(M, 0);\n    for (int l = 0; l < M; l++) {\n        int mx = 0;\n        for (int i = 0; i < SEED_COUNT; i++) {\n            if (x[i][l] > mx) mx = x[i][l];\n        }\n        X_global[l] = mx;\n    }\n\n    // Active dimensions (those with X_global[l] > 0, to avoid division by zero)\n    vector<int> active_dims;\n    active_dims.reserve(M);\n    for (int l = 0; l < M; l++) {\n        if (X_global[l] > 0) active_dims.push_back(l);\n    }\n\n    // Precompute grid adjacency (neighbors) and edges\n    vector<vector<int>> neighbors(SZ);\n    vector<pair<int,int>> edges;\n    edges.reserve(2 * N * (N - 1));\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            int pos = i * N + j;\n            if (j + 1 < N) {\n                int q = pos + 1;\n                edges.emplace_back(pos, q);\n                neighbors[pos].push_back(q);\n                neighbors[q].push_back(pos);\n            }\n            if (i + 1 < N) {\n                int q = pos + N;\n                edges.emplace_back(pos, q);\n                neighbors[pos].push_back(q);\n                neighbors[q].push_back(pos);\n            }\n        }\n    }\n\n    // Precompute positions sorted by degree (center > edge > corner)\n    vector<int> pos_by_deg(SZ);\n    iota(pos_by_deg.begin(), pos_by_deg.end(), 0);\n    sort(pos_by_deg.begin(), pos_by_deg.end(), [&](int a, int b) {\n        if (neighbors[a].size() != neighbors[b].size())\n            return neighbors[a].size() > neighbors[b].size();\n        return a < b;\n    });\n\n    // Simple xorshift RNG (deterministic)\n    uint64_t rng_state = 88172645463325252ull;\n    auto rng = [&]() -> uint64_t {\n        rng_state ^= (rng_state << 7);\n        rng_state ^= (rng_state >> 9);\n        return rng_state;\n    };\n\n    // Normalized total scores per seed\n    vector<double> normV(SEED_COUNT);\n\n    // Synergy matrix (pairwise)\n    static double synergy[MAXS][MAXS];\n\n    for (int turn = 0; turn < T; turn++) {\n        // 1. Compute normalized total score for each seed\n        for (int k = 0; k < SEED_COUNT; k++) {\n            double s = 0.0;\n            for (int idx = 0; idx < (int)active_dims.size(); idx++) {\n                int l = active_dims[idx];\n                s += (double)x[k][l] / (double)X_global[l];\n            }\n            normV[k] = s;\n        }\n\n        // 2. Select 36 seeds: dimension champions + top by normV\n        vector<int> selected;\n        selected.reserve(SZ);\n        vector<char> used(SEED_COUNT, 0);\n\n        // Dimension champions\n        for (int idx = 0; idx < (int)active_dims.size(); idx++) {\n            int l = active_dims[idx];\n            int best = -1;\n            int bestVal = -1;\n            double bestNorm = -1.0;\n            for (int k = 0; k < SEED_COUNT; k++) {\n                int v = x[k][l];\n                if (v > bestVal || (v == bestVal && normV[k] > bestNorm)) {\n                    bestVal = v;\n                    bestNorm = normV[k];\n                    best = k;\n                }\n            }\n            if (best != -1 && !used[best]) {\n                used[best] = 1;\n                selected.push_back(best);\n                if ((int)selected.size() == SZ) break;\n            }\n        }\n\n        // Fill remaining slots with highest normV seeds\n        vector<int> ord(SEED_COUNT);\n        iota(ord.begin(), ord.end(), 0);\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            if (normV[a] != normV[b]) return normV[a] > normV[b];\n            return a < b;\n        });\n        for (int idx = 0; idx < SEED_COUNT && (int)selected.size() < SZ; idx++) {\n            int k = ord[idx];\n            if (!used[k]) {\n                used[k] = 1;\n                selected.push_back(k);\n            }\n        }\n        // Safety: if somehow still < SZ, fill arbitrarily\n        for (int k = 0; k < SEED_COUNT && (int)selected.size() < SZ; k++) {\n            if (!used[k]) {\n                used[k] = 1;\n                selected.push_back(k);\n            }\n        }\n\n        // 3. Compute synergy matrix for all seeds (we only use it for selected)\n        for (int i = 0; i < SEED_COUNT; i++) {\n            synergy[i][i] = 0.0;\n            for (int j = i + 1; j < SEED_COUNT; j++) {\n                double s = 0.0;\n                for (int idx = 0; idx < (int)active_dims.size(); idx++) {\n                    int l = active_dims[idx];\n                    s += (double)max(x[i][l], x[j][l]) / (double)X_global[l];\n                }\n                synergy[i][j] = synergy[j][i] = s;\n            }\n        }\n\n        // 4. Build an initial placement greedily\n\n        // 4-1. Order selected seeds by strength (normalized total) descending\n        vector<int> seed_order(SZ);\n        iota(seed_order.begin(), seed_order.end(), 0);\n        sort(seed_order.begin(), seed_order.end(), [&](int a, int b) {\n            int sa = selected[a];\n            int sb = selected[b];\n            if (normV[sa] != normV[sb]) return normV[sa] > normV[sb];\n            return sa < sb;\n        });\n\n        // 4-2. Greedy placement\n        vector<int> pos_to_seed(SZ, -1);\n        for (int idx = 0; idx < SZ; idx++) {\n            int seed_id = selected[seed_order[idx]]; // actual seed index\n            int bestPos = -1;\n            double bestInc = -1e100;\n\n            for (int pos : pos_by_deg) {\n                if (pos_to_seed[pos] != -1) continue;\n                double inc = 0.0;\n                for (int nb : neighbors[pos]) {\n                    if (pos_to_seed[nb] != -1) {\n                        int nbSeed = pos_to_seed[nb];\n                        inc += synergy[seed_id][nbSeed];\n                    }\n                }\n                if (inc > bestInc + 1e-9 ||\n                    (fabs(inc - bestInc) <= 1e-9 &&\n                     neighbors[pos].size() > (bestPos == -1 ? -1 : (int)neighbors[bestPos].size()))) {\n                    bestInc = inc;\n                    bestPos = pos;\n                }\n            }\n            if (bestPos == -1) bestPos = pos_by_deg[0]; // fallback (should not happen)\n            pos_to_seed[bestPos] = seed_id;\n        }\n\n        // Current arrangement: arr[pos] = seed index\n        vector<int> arr = pos_to_seed;\n\n        // Compute initial total synergy score\n        double cur_score = 0.0;\n        for (auto &e : edges) {\n            cur_score += synergy[arr[e.first]][arr[e.second]];\n        }\n\n        // 5. Hill-climb to improve placement\n        const int ITER = 200000;  // tuned: enough iterations per turn\n        for (int it = 0; it < ITER; it++) {\n            int p1 = (int)(rng() % SZ);\n            int p2 = (int)(rng() % SZ);\n            if (p1 == p2) continue;\n\n            int s1 = arr[p1];\n            int s2 = arr[p2];\n            if (s1 == s2) continue;\n\n            double delta = 0.0;\n\n            // Edges incident to p1 (excluding p2)\n            for (int nb : neighbors[p1]) {\n                if (nb == p2) continue; // edge (p1,p2) symmetric, no change\n                int s_nb = arr[nb];\n                delta -= synergy[s1][s_nb];\n                delta += synergy[s2][s_nb];\n            }\n            // Edges incident to p2 (excluding p1)\n            for (int nb : neighbors[p2]) {\n                if (nb == p1) continue;\n                int s_nb = arr[nb];\n                delta -= synergy[s2][s_nb];\n                delta += synergy[s1][s_nb];\n            }\n\n            if (delta > 0.0) {\n                cur_score += delta;\n                swap(arr[p1], arr[p2]);\n            }\n        }\n\n        // 6. Output arrangement for this turn\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                if (j) cout << ' ';\n                cout << arr[i * N + j];\n            }\n            cout << '\\n';\n        }\n        cout.flush();\n\n        // 7. Read next generation seeds (T times in total, including after last output)\n        if (turn + 1 <= T - 1) {\n            for (int i = 0; i < SEED_COUNT; i++) {\n                for (int l = 0; l < M; l++) {\n                    cin >> x[i][l];\n                }\n            }\n        } else {\n            // For completeness, also read for the last turn as the spec indicates\n            for (int i = 0; i < SEED_COUNT; i++) {\n                for (int l = 0; l < M; l++) {\n                    if (!(cin >> x[i][l])) {\n                        // If no more input, break safely (useful for local testing variations)\n                        break;\n                    }\n                }\n            }\n        }\n    }\n\n    return 0;\n}","ahc038":"#include <bits/stdc++.h>\nusing namespace std;\n\n// Directions: 0=Right, 1=Down, 2=Left, 3=Up\nconst int DX[4] = {0, 1, 0, -1};\nconst int DY[4] = {1, 0, -1, 0};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, V;\n    if (!(cin >> N >> M >> V)) return 0;\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    // Current occupancy grid\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            if (s[i][j] == '1') occ[i][j] = 1;\n        }\n    }\n\n    // Collect mismatches\n    vector<pair<int,int>> sources;\n    vector<pair<int,int>> targets;\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (s[i][j] == '1' && t[i][j] == '0') {\n                sources.emplace_back(i, j);\n            } else if (s[i][j] == '0' && t[i][j] == '1') {\n                targets.emplace_back(i, j);\n            }\n        }\n    }\n    int K = (int)sources.size(); // number of pairs to handle\n\n    // Arm: 2 vertices: 0=root, 1=fingertip (length 1)\n    const int Vp = 2;\n\n    struct PairInfo {\n        int sx, sy;\n        int tx, ty;\n    };\n    vector<PairInfo> pairs;\n\n    if (K > 0) {\n        // Global greedy matching between sources and targets\n        // Precompute Manhattan distances\n        vector<vector<int>> dist(K, vector<int>(K));\n        for (int i = 0; i < K; i++) {\n            for (int j = 0; j < K; j++) {\n                dist[i][j] = abs(sources[i].first - targets[j].first)\n                           + abs(sources[i].second - targets[j].second);\n            }\n        }\n        vector<int> matchT(K, -1);\n        vector<char> usedS(K, 0), usedT(K, 0);\n\n        for (int iter = 0; iter < K; iter++) {\n            int bestD = INT_MAX;\n            int bestI = -1, bestJ = -1;\n            for (int i = 0; i < K; i++) if (!usedS[i]) {\n                for (int j = 0; j < K; j++) if (!usedT[j]) {\n                    int d = dist[i][j];\n                    if (d < bestD) {\n                        bestD = d;\n                        bestI = i;\n                        bestJ = j;\n                    }\n                }\n            }\n            // Assign bestI -> bestJ\n            usedS[bestI] = 1;\n            usedT[bestJ] = 1;\n            matchT[bestI] = bestJ;\n        }\n\n        // Build pairs\n        pairs.resize(K);\n        for (int i = 0; i < K; i++) {\n            int j = matchT[i];\n            pairs[i].sx = sources[i].first;\n            pairs[i].sy = sources[i].second;\n            pairs[i].tx = targets[j].first;\n            pairs[i].ty = targets[j].second;\n        }\n    }\n\n    // Determine order of processing pairs: nearest-neighbor from fingertip position\n    vector<int> order;\n    if (K > 0) {\n        order.reserve(K);\n        vector<char> usedPair(K, 0);\n\n        // Initial fingertip position: root at (0,0), dir=Right => finger at (0,1)\n        int curFx = 0, curFy = 1;\n\n        for (int step = 0; step < K; step++) {\n            int bestId = -1;\n            int bestD = INT_MAX;\n            for (int i = 0; i < K; i++) if (!usedPair[i]) {\n                int d = abs(curFx - pairs[i].sx) + abs(curFy - pairs[i].sy);\n                if (d < bestD) {\n                    bestD = d;\n                    bestId = i;\n                }\n            }\n            usedPair[bestId] = 1;\n            order.push_back(bestId);\n            // After processing this pair, fingertip will end at its target\n            curFx = pairs[bestId].tx;\n            curFy = pairs[bestId].ty;\n        }\n    }\n\n    // Command sequence\n    vector<string> cmds;\n    cmds.reserve(100000);\n\n    int rootX = 0, rootY = 0; // initial root position\n    int initRootX = rootX, initRootY = rootY;\n    int dir = 0;              // 0=Right initially\n    bool holding = false;\n\n    auto add_step = [&](char mv, char rot, bool doP) {\n        string S(2 * Vp, '.'); // length 4\n        S[0] = mv;\n        S[1] = rot;\n        // S[2] is root action, always '.'\n        if (doP) S[3] = 'P';\n        cmds.push_back(S);\n\n        // Update root position\n        if (mv == 'U') rootX--;\n        else if (mv == 'D') rootX++;\n        else if (mv == 'L') rootY--;\n        else if (mv == 'R') rootY++;\n\n        // Update direction of edge (0,1)\n        if (rot == 'L') dir = (dir + 3) & 3;\n        else if (rot == 'R') dir = (dir + 1) & 3;\n    };\n\n    auto finger_x = [&]() { return rootX + DX[dir]; };\n    auto finger_y = [&]() { return rootY + DY[dir]; };\n\n    // Move root to (nx, ny) and orientation to ndir, overlapping movement & rotation\n    auto move_root_dir = [&](int nx, int ny, int ndir) {\n        int dx = nx - rootX;\n        int dy = ny - rootY;\n        vector<char> path;\n        if (dx > 0) path.insert(path.end(), dx, 'D');\n        else if (dx < 0) path.insert(path.end(), -dx, 'U');\n        if (dy > 0) path.insert(path.end(), dy, 'R');\n        else if (dy < 0) path.insert(path.end(), -dy, 'L');\n\n        int diff = (ndir - dir + 4) & 3;\n        int rotSteps = 0;\n        char rotChar = '.';\n        if (diff == 0) {\n            rotSteps = 0;\n        } else if (diff == 1) {\n            rotSteps = 1;\n            rotChar = 'R';\n        } else if (diff == 2) {\n            rotSteps = 2;\n            rotChar = 'R'; // two clockwise rotations\n        } else { // diff == 3\n            rotSteps = 1;\n            rotChar = 'L';\n        }\n\n        int moveSteps = (int)path.size();\n        int usedRot = min(rotSteps, moveSteps);\n        for (int i = 0; i < moveSteps; i++) {\n            char mv = path[i];\n            char rot = (i < usedRot ? rotChar : '.');\n            add_step(mv, rot, false);\n        }\n        for (int i = usedRot; i < rotSteps; i++) {\n            // rotate in place\n            add_step('.', rotChar, false);\n        }\n    };\n\n    // Move fingertip to exactly (tx, ty)\n    auto move_finger_to = [&](int tx, int ty) {\n        int bestNX = rootX, bestNY = rootY, bestDir = dir;\n        int bestCost = INT_MAX;\n\n        for (int ndir = 0; ndir < 4; ndir++) {\n            int nrX = tx - DX[ndir];\n            int nrY = ty - DY[ndir];\n            if (nrX < 0 || nrX >= N || nrY < 0 || nrY >= N) continue;\n            int distRoot = abs(nrX - rootX) + abs(nrY - rootY);\n            int diff = (ndir - dir + 4) & 3;\n            int rotCost = min(diff, 4 - diff);\n            int cost = max(distRoot, rotCost); // rotations can overlap with moves\n            if (cost < bestCost) {\n                bestCost = cost;\n                bestNX = nrX;\n                bestNY = nrY;\n                bestDir = ndir;\n            }\n        }\n\n        move_root_dir(bestNX, bestNY, bestDir);\n        // Now fingertip should be at (tx, ty)\n    };\n\n    if (K > 0) {\n        for (int idx : order) {\n            const auto &P = pairs[idx];\n\n            // Move fingertip to source\n            move_finger_to(P.sx, P.sy);\n            int fx = finger_x(), fy = finger_y();\n            bool doP = false;\n            if (!holding && fx >= 0 && fx < N && fy >= 0 && fy < N && occ[fx][fy] == 1) {\n                doP = true;\n                holding = true;\n                occ[fx][fy] = 0;\n            }\n            add_step('.', '.', doP); // pick\n\n            // Move fingertip to target\n            move_finger_to(P.tx, P.ty);\n            fx = finger_x();\n            fy = finger_y();\n            doP = false;\n            if (holding && fx >= 0 && fx < N && fy >= 0 && fy < N && occ[fx][fy] == 0) {\n                doP = true;\n                holding = false;\n                occ[fx][fy] = 1;\n            }\n            add_step('.', '.', doP); // drop\n        }\n    }\n\n    // Output\n    // 1) Tree description: 2 vertices: 0 (root), 1 (fingertip), length 1\n    cout << Vp << '\\n';\n    cout << 0 << ' ' << 1 << '\\n';\n\n    // 2) Initial root position\n    cout << initRootX << ' ' << initRootY << '\\n';\n\n    // 3) Operation sequence\n    for (const string &S : cmds) {\n        cout << S << '\\n';\n    }\n\n    return 0;\n}","ahc039":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Point {\n    int x, y;\n};\n\nstatic const int MAXC = 100000;\nstatic const int FULL = MAXC + 1;\n\n// Rectangle diff evaluation: #mackerel - #sardine inside rectangle (inclusive)\nint evaluateRectDiff(int xL, int yB, int xR, int yT,\n                     const vector<int>& xs, const vector<int>& ys, int N) {\n    int total = 2 * N;\n    int diff = 0;\n    for (int i = 0; i < total; ++i) {\n        int x = xs[i], y = ys[i];\n        if (x >= xL && x <= xR && y >= yB && y <= yT) {\n            diff += (i < N ? 1 : -1);\n        }\n    }\n    return diff;\n}\n\n// Point-in-polygon test (simple polygon, arbitrary orientation, edges count as inside)\nbool pointInPolygon(int px, int py, const vector<pair<int,int>>& poly) {\n    int n = (int)poly.size();\n    bool inside = false;\n    for (int i = 0, j = n - 1; i < n; j = i++) {\n        long long xi = poly[i].first, yi = poly[i].second;\n        long long xj = poly[j].first, yj = poly[j].second;\n\n        // Check if point lies on segment (xi,yi)-(xj,yj)\n        long long minx = min(xi, xj), maxx = max(xi, xj);\n        long long miny = min(yi, yj), maxy = max(yi, yj);\n        long long cross = (xj - xi) * 1LL * (py - yi) - (yj - yi) * 1LL * (px - xi);\n        if (cross == 0 && px >= minx && px <= maxx && py >= miny && py <= maxy) {\n            return true; // on edge, counted as inside\n        }\n\n        // Standard even-odd rule, ignoring horizontal edges\n        bool cond = ((yi > py) != (yj > py));\n        if (cond) {\n            double interX = xi + (double)(xj - xi) * (double)(py - yi) / (double)(yj - yi);\n            if (interX > px) inside = !inside;\n        }\n    }\n    return inside;\n}\n\n// Polygon diff evaluation: #mackerel - #sardine inside (edges inclusive)\nint evaluatePolygonDiff(const vector<pair<int,int>>& poly,\n                        const vector<int>& xs, const vector<int>& ys, int N) {\n    if (poly.empty()) return INT_MIN / 2;\n    int total = 2 * N;\n    int minx = INT_MAX, maxx = INT_MIN, miny = INT_MAX, maxy = INT_MIN;\n    for (auto &p : poly) {\n        minx = min(minx, p.first);\n        maxx = max(maxx, p.first);\n        miny = min(miny, p.second);\n        maxy = max(maxy, p.second);\n    }\n\n    int diff = 0;\n    for (int i = 0; i < total; ++i) {\n        int x = xs[i], y = ys[i];\n        if (x < minx || x > maxx || y < miny || y > maxy) continue;\n        if (pointInPolygon(x, y, poly)) {\n            diff += (i < N ? 1 : -1);\n        }\n    }\n    return diff;\n}\n\n// Build outer boundary polygon from a 4-connected component mask of grid cells.\n// inside: size H*W, 1 if cell is in the chosen component.\n// Returns empty if no valid polygon or if constraints violated.\nvector<pair<int,int>> buildPolygonFromMask(\n    int H, int W,\n    const vector<char>& inside,\n    const vector<int>& xCoord,\n    const vector<int>& yCoord\n) {\n    int V = (H + 1) * (W + 1);\n    vector<vector<int>> adj(V);\n\n    auto cellInside = [&](int i, int j) -> bool {\n        if (i < 0 || i >= H || j < 0 || j >= W) return false;\n        return inside[i * W + j] != 0;\n    };\n    auto vertIndex = [&](int r, int c) -> int {\n        return r * (W + 1) + c;\n    };\n    auto addEdge = [&](int u, int v) {\n        adj[u].push_back(v);\n        adj[v].push_back(u);\n    };\n\n    // Build boundary edges\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            if (!cellInside(i, j)) continue;\n            int idx = i * W + j;\n            (void)idx;\n\n            // Left side\n            if (j == 0 || !cellInside(i, j - 1)) {\n                int u = vertIndex(i, j);\n                int v = vertIndex(i + 1, j);\n                addEdge(u, v);\n            }\n            // Right side\n            if (j == W - 1 || !cellInside(i, j + 1)) {\n                int u = vertIndex(i, j + 1);\n                int v = vertIndex(i + 1, j + 1);\n                addEdge(u, v);\n            }\n            // Bottom side\n            if (i == 0 || !cellInside(i - 1, j)) {\n                int u = vertIndex(i, j);\n                int v = vertIndex(i, j + 1);\n                addEdge(u, v);\n            }\n            // Top side\n            if (i == H - 1 || !cellInside(i + 1, j)) {\n                int u = vertIndex(i + 1, j);\n                int v = vertIndex(i + 1, j + 1);\n                addEdge(u, v);\n            }\n        }\n    }\n\n    vector<char> used(V, false);\n    vector<pair<int,int>> bestPoly;\n    long long bestAreaAbs = -1;\n\n    // Traverse cycles\n    for (int start = 0; start < V; ++start) {\n        if (used[start] || adj[start].empty()) continue;\n\n        vector<int> cyc;\n        int cur = start;\n        int prev = -1;\n        int safety = 0;\n\n        while (true) {\n            cyc.push_back(cur);\n            used[cur] = true;\n\n            if (adj[cur].empty()) {\n                cyc.clear(); // invalid\n                break;\n            }\n\n            int nxt;\n            if ((int)adj[cur].size() == 1) {\n                nxt = adj[cur][0];\n            } else {\n                // choose neighbor that is not prev\n                if (adj[cur][0] != prev) nxt = adj[cur][0];\n                else nxt = adj[cur][1];\n            }\n\n            prev = cur;\n            cur = nxt;\n            if (cur == start) break;\n\n            if (++safety > V * 4) { // safety guard\n                cyc.clear();\n                break;\n            }\n        }\n\n        if (cyc.empty() || (int)cyc.size() < 4) continue;\n\n        // Convert vertices to coordinates\n        vector<pair<int,int>> ptsRaw;\n        ptsRaw.reserve(cyc.size());\n        for (int vid : cyc) {\n            int r = vid / (W + 1);\n            int c = vid % (W + 1);\n            int x = xCoord[c];\n            int y = yCoord[r];\n            ptsRaw.emplace_back(x, y);\n        }\n\n        // Remove collinear middle vertices (single pass is enough for our purposes)\n        int m = (int)ptsRaw.size();\n        vector<pair<int,int>> pts;\n        pts.reserve(m);\n        for (int i = 0; i < m; ++i) {\n            auto &prevP = ptsRaw[(i + m - 1) % m];\n            auto &curP  = ptsRaw[i];\n            auto &nextP = ptsRaw[(i + 1) % m];\n            bool collinear =\n                (prevP.first == curP.first && curP.first == nextP.first) ||\n                (prevP.second == curP.second && curP.second == nextP.second);\n            if (!collinear) {\n                pts.push_back(curP);\n            }\n        }\n        if ((int)pts.size() < 4) continue;\n        if ((int)pts.size() > 1000) continue;\n\n        // Perimeter check\n        long long per = 0;\n        int m2 = (int)pts.size();\n        for (int i = 0; i < m2; ++i) {\n            auto &a = pts[i];\n            auto &b = pts[(i + 1) % m2];\n            per += llabs((long long)a.first - b.first) + llabs((long long)a.second - b.second);\n        }\n        if (per > 400000LL) continue;\n\n        // Area (twice)\n        long long area2 = 0;\n        for (int i = 0; i < m2; ++i) {\n            long long x1 = pts[i].first, y1 = pts[i].second;\n            long long x2 = pts[(i + 1) % m2].first, y2 = pts[(i + 1) % m2].second;\n            area2 += x1 * y2 - x2 * y1;\n        }\n        long long areaAbs = llabs(area2);\n        if (areaAbs > bestAreaAbs) {\n            bestAreaAbs = areaAbs;\n            bestPoly = std::move(pts);\n        }\n    }\n\n    return bestPoly;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    if (!(cin >> N)) return 0;\n    int total = 2 * N;\n\n    vector<int> xs(total), ys(total);\n    for (int i = 0; i < total; ++i) {\n        cin >> xs[i] >> ys[i];\n    }\n\n    // Best solution tracked as polygon\n    vector<pair<int,int>> bestPoly;\n    int bestDiff = 0;\n\n    // Start with full bounding rectangle (diff=0)\n    bestPoly = {\n        {0, 0},\n        {MAXC, 0},\n        {MAXC, MAXC},\n        {0, MAXC}\n    };\n\n    // Helper to update best polygon if diff improved\n    auto updateBestWithRect = [&](int xL, int yB, int xR, int yT) {\n        if (xL > xR || yB > yT) return;\n        int diff = evaluateRectDiff(xL, yB, xR, yT, xs, ys, N);\n        if (diff > bestDiff) {\n            bestDiff = diff;\n            bestPoly.clear();\n            bestPoly.push_back({xL, yB});\n            bestPoly.push_back({xR, yB});\n            bestPoly.push_back({xR, yT});\n            bestPoly.push_back({xL, yT});\n        }\n    };\n\n    auto updateBestWithPoly = [&](const vector<pair<int,int>>& poly) {\n        if (poly.empty()) return;\n        int diff = evaluatePolygonDiff(poly, xs, ys, N);\n        if (diff > bestDiff) {\n            bestDiff = diff;\n            bestPoly = poly;\n        }\n    };\n\n    // Grid sizes and weight modes\n    vector<int> gridSizes = {40, 60, 90, 130};\n    // weightModes: (weight for mackerel, weight for sardine)\n    vector<pair<int,int>> weightModes = {\n        {1, -1},\n        {1, -2},\n        {2, -1}\n    };\n\n    // For each grid resolution and weight mode:\n    for (int S : gridSizes) {\n        int H = S, W = S;\n        vector<int> xCoord(W + 1), yCoord(H + 1);\n        for (int j = 0; j <= W; ++j) {\n            int val = (int)(1LL * j * FULL / W);\n            if (val > MAXC) val = MAXC;\n            xCoord[j] = val;\n        }\n        for (int i = 0; i <= H; ++i) {\n            int val = (int)(1LL * i * FULL / H);\n            if (val > MAXC) val = MAXC;\n            yCoord[i] = val;\n        }\n\n        for (auto [wM, wS] : weightModes) {\n            // Build cell weights\n            vector<int> cell(H * W, 0);\n            for (int idx = 0; idx < total; ++idx) {\n                int x = xs[idx];\n                int y = ys[idx];\n                int cx = (int)(1LL * x * W / FULL);\n                int cy = (int)(1LL * y * H / FULL);\n                if (cx < 0) cx = 0;\n                if (cx >= W) cx = W - 1;\n                if (cy < 0) cy = 0;\n                if (cy >= H) cy = H - 1;\n                cell[cy * W + cx] += (idx < N ? wM : wS);\n            }\n\n            // 2D Kadane for best rectangle on this grid\n            const long long NEG_INF = -(1LL << 60);\n            long long bestSum = NEG_INF;\n            int bestL = 0, bestR = 0, bestT = 0, bestB = 0;\n\n            vector<long long> colSum(W);\n            for (int top = 0; top < H; ++top) {\n                fill(colSum.begin(), colSum.end(), 0);\n                for (int bottom = top; bottom < H; ++bottom) {\n                    int rowOffset = bottom * W;\n                    for (int c = 0; c < W; ++c) {\n                        colSum[c] += cell[rowOffset + c];\n                    }\n                    long long sum = 0;\n                    int curL = 0;\n                    for (int c = 0; c < W; ++c) {\n                        if (sum <= 0) {\n                            sum = colSum[c];\n                            curL = c;\n                        } else {\n                            sum += colSum[c];\n                        }\n                        if (sum > bestSum) {\n                            bestSum = sum;\n                            bestL = curL;\n                            bestR = c;\n                            bestT = top;\n                            bestB = bottom;\n                        }\n                    }\n                }\n            }\n\n            if (bestSum > 0) {\n                int xL = xCoord[bestL];\n                int xR = xCoord[bestR + 1];\n                int yB = yCoord[bestT];\n                int yT = yCoord[bestB + 1];\n\n                if (xL < 0) xL = 0;\n                if (xR > MAXC) xR = MAXC;\n                if (yB < 0) yB = 0;\n                if (yT > MAXC) yT = MAXC;\n                updateBestWithRect(xL, yB, xR, yT);\n            }\n\n            // Best connected component of positive cells -> union-of-cells polygon\n            vector<char> visited(H * W, 0);\n            vector<char> bestMask(H * W, 0);\n            long long bestCompSum = 0;\n\n            vector<pair<int,int>> q;\n            q.reserve(H * W);\n            vector<pair<int,int>> compCells;\n            compCells.reserve(H * W);\n\n            for (int i = 0; i < H; ++i) {\n                for (int j = 0; j < W; ++j) {\n                    int idx = i * W + j;\n                    if (visited[idx] || cell[idx] <= 0) continue;\n\n                    q.clear();\n                    compCells.clear();\n                    long long curSum = 0;\n\n                    visited[idx] = 1;\n                    q.emplace_back(i, j);\n\n                    for (size_t qi = 0; qi < q.size(); ++qi) {\n                        auto [r, c] = q[qi];\n                        compCells.emplace_back(r, c);\n                        curSum += cell[r * W + c];\n\n                        static const int dr[4] = {-1, 1, 0, 0};\n                        static const int dc[4] = {0, 0, -1, 1};\n                        for (int dir = 0; dir < 4; ++dir) {\n                            int nr = r + dr[dir];\n                            int nc = c + dc[dir];\n                            if (nr < 0 || nr >= H || nc < 0 || nc >= W) continue;\n                            int nidx = nr * W + nc;\n                            if (!visited[nidx] && cell[nidx] > 0) {\n                                visited[nidx] = 1;\n                                q.emplace_back(nr, nc);\n                            }\n                        }\n                    }\n\n                    if (curSum > bestCompSum) {\n                        bestCompSum = curSum;\n                        fill(bestMask.begin(), bestMask.end(), 0);\n                        for (auto &rc : compCells) {\n                            bestMask[rc.first * W + rc.second] = 1;\n                        }\n                    }\n                }\n            }\n\n            if (bestCompSum > 0) {\n                vector<pair<int,int>> poly = buildPolygonFromMask(H, W, bestMask, xCoord, yCoord);\n                if (!poly.empty()) {\n                    updateBestWithPoly(poly);\n                }\n            }\n        }\n    }\n\n    // Fallback: if no positive diff achieved, try small rectangles around mackerels\n    if (bestDiff <= 0) {\n        const int delta = 1000;\n        for (int i = 0; i < N; ++i) {\n            int x = xs[i], y = ys[i];\n            int xL = max(0, x - delta);\n            int xR = min(MAXC, x + delta);\n            int yB = max(0, y - delta);\n            int yT = min(MAXC, y + delta);\n            updateBestWithRect(xL, yB, xR, yT);\n        }\n    }\n\n    // Ensure polygon is valid in terms of vertex count and perimeter; if not, fall back to full box\n    auto checkPolygon = [&](const vector<pair<int,int>>& poly) -> bool {\n        int m = (int)poly.size();\n        if (m < 4 || m > 1000) return false;\n        long long per = 0;\n        for (int i = 0; i < m; ++i) {\n            auto &a = poly[i];\n            auto &b = poly[(i + 1) % m];\n            per += llabs((long long)a.first - b.first) + llabs((long long)a.second - b.second);\n        }\n        if (per > 400000LL) return false;\n        // Distinct vertices check\n        // (Coordinates already come from grid; collisions are unlikely but we ensure)\n        set<pair<int,int>> st(poly.begin(), poly.end());\n        if ((int)st.size() != m) return false;\n        return true;\n    };\n\n    if (!checkPolygon(bestPoly)) {\n        // Fall back to full bounding rectangle\n        bestPoly = {\n            {0, 0},\n            {MAXC, 0},\n            {MAXC, MAXC},\n            {0, MAXC}\n        };\n    }\n\n    cout << bestPoly.size() << '\\n';\n    for (auto &p : bestPoly) {\n        cout << p.first << ' ' << p.second << '\\n';\n    }\n    return 0;\n}","ahc040":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct EvalResult {\n    long long W = (1LL<<62);\n    long long H = (1LL<<62);\n    long long S = (1LL<<62);\n    vector<int> cuts; // row boundaries: 0 = cuts[0] < ... < cuts[R] = N\n};\n\n// Evaluate a given orientation vector 'rot' (0=no-rot,1=rot):\n// compute best shelf segmentation (contiguous rows) and return W,H,S and cuts.\nEvalResult evaluate_orientation(const vector<long long>& w0,\n                                const vector<long long>& h0,\n                                const vector<int>& rot) {\n    int N = (int)w0.size();\n    const long long INF = (1LL<<62);\n\n    // Build width/height under this orientation\n    vector<long long> width(N), height(N);\n    long long sumW = 0, maxW = 0;\n    long double area = 0.0L;\n\n    for (int i = 0; i < N; i++) {\n        if (rot[i] == 0) {\n            width[i]  = w0[i];\n            height[i] = h0[i];\n        } else {\n            width[i]  = h0[i];\n            height[i] = w0[i];\n        }\n        sumW += width[i];\n        maxW = max(maxW, width[i]);\n        area += (long double)width[i] * (long double)height[i];\n    }\n\n    if (sumW == 0) { // degenerate, shouldn't happen\n        EvalResult res;\n        res.W = res.H = res.S = 0;\n        res.cuts = {0, N};\n        return res;\n    }\n\n    // Candidate width limits\n    vector<long long> Ws;\n    Ws.reserve(16);\n    Ws.push_back(sumW);  // one big row (upper extreme)\n    Ws.push_back(maxW);  // narrow rows (lower extreme)\n\n    long double base = sqrtl(max((long double)1.0L, area));\n    long double low  = max((long double)maxW, base * 0.5L);\n    long double high = min((long double)sumW, base * 2.0L);\n    if (high < low) high = low;\n\n    const int EXTRA = 10;\n    if (high == low) {\n        long long Wc = (long long)(low + 0.5L);\n        Ws.push_back(Wc);\n    } else {\n        for (int k = 0; k < EXTRA; k++) {\n            long double t = (k + 0.5L) / (long double)EXTRA;\n            long double w = low + (high - low) * t;\n            long long Wc = (long long)(w + 0.5L);\n            if (Wc < maxW) Wc = maxW;\n            if (Wc > sumW) Wc = sumW;\n            Ws.push_back(Wc);\n        }\n    }\n\n    sort(Ws.begin(), Ws.end());\n    Ws.erase(unique(Ws.begin(), Ws.end()), Ws.end());\n\n    EvalResult best;\n\n    vector<long long> dp(N + 1);\n    vector<int> prev(N + 1);\n\n    for (long long W_limit : Ws) {\n        // DP over prefix length\n        dp[0] = 0;\n        prev[0] = -1;\n        for (int i = 1; i <= N; i++) {\n            long long bestH = INF;\n            int bestJ = -1;\n            long long rowW = 0;\n            long long rowH = 0;\n            // consider last row being [j, i)\n            for (int j = i - 1; j >= 0; j--) {\n                rowW += width[j];\n                if (rowW > W_limit) break;\n                if (height[j] > rowH) rowH = height[j];\n                long long cand = dp[j] + rowH;\n                if (cand < bestH) {\n                    bestH = cand;\n                    bestJ = j;\n                }\n            }\n            dp[i] = bestH;\n            prev[i] = bestJ;\n        }\n        if (prev[N] == -1 || dp[N] >= INF) continue;\n\n        // Recover cuts\n        vector<int> cuts;\n        int cur = N;\n        cuts.push_back(N);\n        while (cur > 0) {\n            int pj = prev[cur];\n            if (pj < 0) { cuts.clear(); break; }\n            cuts.push_back(pj);\n            cur = pj;\n        }\n        if (cuts.empty()) continue;\n        if (cuts.back() != 0) {\n            // something went wrong; skip\n            continue;\n        }\n        reverse(cuts.begin(), cuts.end());\n\n        // Compute actual W,H\n        long long Htotal = 0;\n        long long Wactual = 0;\n        int R = (int)cuts.size() - 1;\n        for (int r = 0; r < R; r++) {\n            int L = cuts[r];\n            int Ridx = cuts[r+1];\n            long long rowW = 0;\n            long long rowH = 0;\n            for (int i = L; i < Ridx; i++) {\n                rowW += width[i];\n                if (height[i] > rowH) rowH = height[i];\n            }\n            Htotal += rowH;\n            if (rowW > Wactual) Wactual = rowW;\n        }\n        long long S = Htotal + Wactual;\n        if (S < best.S) {\n            best.S = S;\n            best.W = Wactual;\n            best.H = Htotal;\n            best.cuts = std::move(cuts);\n        }\n    }\n\n    // As a fallback, ensure we have some segmentation\n    if (best.S >= INF) {\n        best.cuts = {0, N};\n        long long Htotal = 0, Wactual = 0;\n        long long rowW = 0, rowH = 0;\n        for (int i = 0; i < N; i++) {\n            rowW += width[i];\n            if (height[i] > rowH) rowH = height[i];\n        }\n        Htotal = rowH;\n        Wactual = rowW;\n        best.W = Wactual;\n        best.H = Htotal;\n        best.S = Wactual + Htotal;\n    }\n\n    return best;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, T;\n    long long sigma;\n    if (!(cin >> N >> T >> sigma)) {\n        return 0;\n    }\n\n    vector<long long> w0(N), h0(N);\n    for (int i = 0; i < N; i++) {\n        cin >> w0[i] >> h0[i];\n        if (w0[i] < 1) w0[i] = 1;\n        if (h0[i] < 1) h0[i] = 1;\n    }\n\n    // Initial orientation: minimize height\n    vector<int> rot(N);\n    for (int i = 0; i < N; i++) {\n        // If h <= w, keep; else rotate so height=min\n        rot[i] = (h0[i] > w0[i]) ? 1 : 0;\n    }\n\n    // Local search over orientations\n    EvalResult bestEval = evaluate_orientation(w0, h0, rot);\n\n    const int MAX_PASSES = 2;\n    for (int pass = 0; pass < MAX_PASSES; pass++) {\n        bool improved = false;\n        for (int i = 0; i < N; i++) {\n            rot[i] ^= 1; // toggle\n            EvalResult cand = evaluate_orientation(w0, h0, rot);\n            if (cand.S < bestEval.S) {\n                bestEval = cand;\n                improved = true;\n            } else {\n                rot[i] ^= 1; // revert\n            }\n        }\n        if (!improved) break;\n    }\n\n    // Final width/height arrays under chosen orientation\n    vector<long long> width(N), height(N);\n    for (int i = 0; i < N; i++) {\n        if (rot[i] == 0) {\n            width[i]  = w0[i];\n            height[i] = h0[i];\n        } else {\n            width[i]  = h0[i];\n            height[i] = w0[i];\n        }\n    }\n\n    // Derive row index for each rectangle, and bases per row\n    vector<int>& cuts = bestEval.cuts;\n    int R = (int)cuts.size() - 1; // number of rows\n    vector<int> rowOf(N, 0);\n    for (int r = 0; r < R; r++) {\n        for (int i = cuts[r]; i < cuts[r+1]; i++) {\n            rowOf[i] = r;\n        }\n    }\n    vector<int> base(R, -1);\n    for (int r = 0; r < R; r++) {\n        int L = cuts[r];\n        int Ridx = cuts[r+1];\n        long long bestH = -1;\n        int bestIdx = L;\n        for (int i = L; i < Ridx; i++) {\n            if (height[i] > bestH) {\n                bestH = height[i];\n                bestIdx = i;\n            }\n        }\n        base[r] = bestIdx;\n    }\n\n    // We output the same arrangement T times\n    for (int t = 0; t < T; t++) {\n        // Number of rectangles used: all N\n        cout << N << '\\n';\n        for (int i = 0; i < N; i++) {\n            int r = rowOf[i];\n            int b = -1;\n            if (r > 0) {\n                b = base[r - 1]; // base of previous row\n            }\n            char d = 'L';\n            cout << i << ' ' << rot[i] << ' ' << d << ' ' << b << '\\n';\n        }\n        cout.flush();\n\n        long long Wm, Hm;\n        if (!(cin >> Wm >> Hm)) {\n            // In official judge this should not happen, but be safe\n            return 0;\n        }\n    }\n\n    return 0;\n}","ahc041":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct FastRand {\n    uint64_t x;\n    FastRand() {\n        x = 88172645463393265ull;\n    }\n    uint64_t next() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return x;\n    }\n    int nextInt(int n) { // 0..n-1\n        return (int)(next() % (uint64_t)n);\n    }\n    double nextDouble() {\n        return (next() >> 11) * (1.0 / 9007199254740992.0); // [0,1)\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, H;\n    if (!(cin >> N >> M >> H)) {\n        return 0;\n    }\n\n    vector<int> A(N);\n    for (int i = 0; i < N; ++i) cin >> A[i];\n\n    vector<vector<int>> adj(N);\n    for (int i = 0; i < M; ++i) {\n        int u, v;\n        cin >> u >> v;\n        adj[u].push_back(v);\n        adj[v].push_back(u);\n    }\n\n    // Read coordinates but we don't use them in this solution.\n    vector<int> x(N), y(N);\n    for (int i = 0; i < N; ++i) cin >> x[i] >> y[i];\n\n    // ---------- Initial forest construction (ascending beauty) ----------\n\n    vector<int> parent(N, -1);\n    vector<int> depth(N, 0);\n    vector<char> processed(N, 0);\n\n    vector<int> order(N);\n    iota(order.begin(), order.end(), 0);\n    sort(order.begin(), order.end(), [&](int i, int j) {\n        if (A[i] != A[j]) return A[i] < A[j];\n        return i < j;\n    });\n\n    for (int idx = 0; idx < N; ++idx) {\n        int v = order[idx];\n        processed[v] = 1;\n        int bestParent = -1;\n        int bestDepth = -1;\n        for (int u : adj[v]) {\n            if (!processed[u]) continue; // only earlier vertices\n            if (depth[u] > H - 1) continue; // parent depth must allow child depth \u2264 H\n            if (depth[u] > bestDepth) {\n                bestDepth = depth[u];\n                bestParent = u;\n            }\n        }\n        if (bestParent == -1) {\n            parent[v] = -1;\n            depth[v] = 0;\n        } else {\n            parent[v] = bestParent;\n            depth[v] = depth[bestParent] + 1;\n            if (depth[v] > H) {\n                // Should not happen due to check above, but just in case, clamp:\n                depth[v] = H;\n            }\n        }\n    }\n\n    // ---------- Build children lists ----------\n    vector<vector<int>> children(N);\n    for (int v = 0; v < N; ++v) {\n        int p = parent[v];\n        if (p != -1) {\n            children[p].push_back(v);\n        }\n    }\n\n    // ---------- Compute subtreeSum and subHeight bottom-up ----------\n    vector<vector<int>> nodesAtDepth(H + 1);\n    for (int v = 0; v < N; ++v) {\n        int d = depth[v];\n        if (d < 0) d = 0;\n        if (d > H) d = H; // safety\n        nodesAtDepth[d].push_back(v);\n    }\n\n    vector<long long> subtreeSum(N, 0);\n    vector<int> subHeight(N, 0);\n\n    for (int d = H; d >= 0; --d) {\n        for (int v : nodesAtDepth[d]) {\n            long long sum = A[v];\n            int h = 0;\n            for (int c : children[v]) {\n                sum += subtreeSum[c];\n                h = max(h, 1 + subHeight[c]);\n            }\n            subtreeSum[v] = sum;\n            subHeight[v] = h;\n        }\n    }\n\n    // ---------- Compute initial score ----------\n    long long score = 0;\n    for (int v = 0; v < N; ++v) {\n        int d = depth[v];\n        if (d < 0) d = 0;\n        if (d > H) d = H; // safety\n        score += (long long)(d + 1) * (long long)A[v];\n    }\n\n    // After this, we no longer trust `depth[]` and compute depths on demand.\n\n    auto getDepth = [&](int v) -> int {\n        int d = 0;\n        while (parent[v] != -1) {\n            v = parent[v];\n            ++d;\n        }\n        return d; // at most H\n    };\n\n    auto recomputeHeightFrom = [&](int start) {\n        int x = start;\n        while (x != -1) {\n            int old_h = subHeight[x];\n            int new_h = 0;\n            for (int c : children[x]) {\n                new_h = max(new_h, 1 + subHeight[c]);\n            }\n            if (new_h == old_h) break;\n            subHeight[x] = new_h;\n            x = parent[x];\n        }\n    };\n\n    auto reparentFn = [&](int v, int newParent, int oldDepth, int newDepth) {\n        int oldParent = parent[v];\n        if (oldParent == newParent) return;\n        long long deltaDepth = (long long)(newDepth - oldDepth);\n        long long deltaScore = deltaDepth * subtreeSum[v];\n        score += deltaScore;\n\n        // Update subtreeSum along old parent path\n        if (oldParent != -1) {\n            for (int x = oldParent; x != -1; x = parent[x]) {\n                subtreeSum[x] -= subtreeSum[v];\n            }\n        }\n\n        // Update subtreeSum along new parent path\n        if (newParent != -1) {\n            for (int x = newParent; x != -1; x = parent[x]) {\n                subtreeSum[x] += subtreeSum[v];\n            }\n        }\n\n        // Update children lists\n        if (oldParent != -1) {\n            auto &vec = children[oldParent];\n            for (int i = 0; i < (int)vec.size(); ++i) {\n                if (vec[i] == v) {\n                    vec[i] = vec.back();\n                    vec.pop_back();\n                    break;\n                }\n            }\n        }\n        if (newParent != -1) {\n            children[newParent].push_back(v);\n        }\n\n        parent[v] = newParent;\n\n        // Update heights along old and new parent paths\n        if (oldParent != -1) {\n            recomputeHeightFrom(oldParent);\n        }\n        if (newParent != -1) {\n            recomputeHeightFrom(newParent);\n        }\n    };\n\n    // ---------- Greedy local improvement ----------\n\n    vector<int> orderDesc(N);\n    iota(orderDesc.begin(), orderDesc.end(), 0);\n    sort(orderDesc.begin(), orderDesc.end(), [&](int i, int j) {\n        if (A[i] != A[j]) return A[i] > A[j];\n        return i < j;\n    });\n\n    bool improved;\n    do {\n        improved = false;\n        for (int v : orderDesc) {\n            int oldParent = parent[v];\n            int oldDepth = getDepth(v);\n            long long bestDelta = 0;\n            int bestParent = oldParent;\n            int bestNewDepth = oldDepth;\n\n            for (int u : adj[v]) {\n                if (u == oldParent) continue;\n\n                // Check if u is in subtree of v (avoid cycles)\n                int x = u;\n                bool cyc = false;\n                while (x != -1) {\n                    if (x == v) {\n                        cyc = true;\n                        break;\n                    }\n                    x = parent[x];\n                }\n                if (cyc) continue;\n\n                int depth_u = getDepth(u);\n                int newDepth = depth_u + 1;\n                if (newDepth > H) continue;\n                if (newDepth + subHeight[v] > H) continue;\n\n                long long deltaScore = (long long)(newDepth - oldDepth) * subtreeSum[v];\n                if (deltaScore > bestDelta) {\n                    bestDelta = deltaScore;\n                    bestParent = u;\n                    bestNewDepth = newDepth;\n                }\n            }\n\n            if (bestParent != oldParent && bestDelta > 0) {\n                reparentFn(v, bestParent, oldDepth, bestNewDepth);\n                improved = true;\n            }\n        }\n    } while (improved);\n\n    // ---------- Output ----------\n    for (int i = 0; i < N; ++i) {\n        if (i) cout << ' ';\n        cout << parent[i];\n    }\n    cout << '\\n';\n\n    return 0;\n}","ahc042":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Operation {\n    char dir;      // 'U', 'D', 'L', 'R' : direction of the first half\n    int  p;        // row or column index\n    int  len;      // number of shifts in each direction\n    int  cost;     // 2 * len\n    uint64_t mask; // which Oni are removed by this operation\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    if (!(cin >> N)) return 0;\n    vector<string> C(N);\n    for (int i = 0; i < N; ++i) cin >> C[i];\n\n    // Collect Oni and Fuku positions\n    vector<pair<int,int>> oni;  // (row,col) for each Oni\n    vector<vector<int>> oni_id(N, vector<int>(N, -1));\n    vector<vector<bool>> fuku(N, vector<bool>(N, false));\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            char ch = C[i][j];\n            if (ch == 'x') {\n                int id = (int)oni.size();\n                oni.emplace_back(i, j);\n                oni_id[i][j] = id;\n            } else if (ch == 'o') {\n                fuku[i][j] = true;\n            }\n        }\n    }\n\n    int M = (int)oni.size(); // number of Oni, should be 2N\n    if (M == 0) {\n        // No Oni: nothing to do\n        return 0;\n    }\n\n    // Prefix sums of Fuku for rows and columns\n    vector<vector<int>> row_pref(N, vector<int>(N, 0));\n    vector<vector<int>> col_pref(N, vector<int>(N, 0));\n\n    for (int i = 0; i < N; ++i) {\n        int acc = 0;\n        for (int j = 0; j < N; ++j) {\n            if (fuku[i][j]) acc++;\n            row_pref[i][j] = acc;\n        }\n    }\n    for (int j = 0; j < N; ++j) {\n        int acc = 0;\n        for (int i = 0; i < N; ++i) {\n            if (fuku[i][j]) acc++;\n            col_pref[j][i] = acc;\n        }\n    }\n\n    vector<Operation> ops;\n    ops.reserve(4 * N * N);\n\n    // Build all safe column operations\n    for (int j = 0; j < N; ++j) {\n        int total_fuku_col = col_pref[j][N-1];\n\n        // Up-prefix [0..h]\n        for (int h = 0; h < N; ++h) {\n            if (col_pref[j][h] == 0) { // no Fuku in [0..h]\n                uint64_t mask = 0;\n                for (int id = 0; id < M; ++id) {\n                    auto [r, c] = oni[id];\n                    if (c == j && r <= h) {\n                        mask |= (1ULL << id);\n                    }\n                }\n                if (mask) {\n                    int len = h + 1;\n                    Operation op;\n                    op.dir = 'U';\n                    op.p = j;\n                    op.len = len;\n                    op.cost = 2 * len;\n                    op.mask = mask;\n                    ops.push_back(op);\n                }\n            }\n        }\n\n        // Down-suffix [h..N-1]\n        for (int h = 0; h < N; ++h) {\n            int fuku_cnt = total_fuku_col - (h > 0 ? col_pref[j][h-1] : 0);\n            if (fuku_cnt == 0) { // no Fuku in [h..N-1]\n                uint64_t mask = 0;\n                for (int id = 0; id < M; ++id) {\n                    auto [r, c] = oni[id];\n                    if (c == j && r >= h) {\n                        mask |= (1ULL << id);\n                    }\n                }\n                if (mask) {\n                    int len = N - h;\n                    Operation op;\n                    op.dir = 'D';\n                    op.p = j;\n                    op.len = len;\n                    op.cost = 2 * len;\n                    op.mask = mask;\n                    ops.push_back(op);\n                }\n            }\n        }\n    }\n\n    // Build all safe row operations\n    for (int i = 0; i < N; ++i) {\n        int total_fuku_row = row_pref[i][N-1];\n\n        // Left-prefix [0..h]\n        for (int h = 0; h < N; ++h) {\n            if (row_pref[i][h] == 0) { // no Fuku in [0..h]\n                uint64_t mask = 0;\n                for (int id = 0; id < M; ++id) {\n                    auto [r, c] = oni[id];\n                    if (r == i && c <= h) {\n                        mask |= (1ULL << id);\n                    }\n                }\n                if (mask) {\n                    int len = h + 1;\n                    Operation op;\n                    op.dir = 'L';\n                    op.p = i;\n                    op.len = len;\n                    op.cost = 2 * len;\n                    op.mask = mask;\n                    ops.push_back(op);\n                }\n            }\n        }\n\n        // Right-suffix [h..N-1]\n        for (int h = 0; h < N; ++h) {\n            int fuku_cnt = total_fuku_row - (h > 0 ? row_pref[i][h-1] : 0);\n            if (fuku_cnt == 0) { // no Fuku in [h..N-1]\n                uint64_t mask = 0;\n                for (int id = 0; id < M; ++id) {\n                    auto [r, c] = oni[id];\n                    if (r == i && c >= h) {\n                        mask |= (1ULL << id);\n                    }\n                }\n                if (mask) {\n                    int len = N - h;\n                    Operation op;\n                    op.dir = 'R';\n                    op.p = i;\n                    op.len = len;\n                    op.cost = 2 * len;\n                    op.mask = mask;\n                    ops.push_back(op);\n                }\n            }\n        }\n    }\n\n    if (ops.empty()) {\n        // Should not happen due to problem guarantees, but be safe.\n        return 0;\n    }\n\n    // Deduplicate operations by their Oni-mask, keeping the cheapest one\n    sort(ops.begin(), ops.end(), [](const Operation &a, const Operation &b) {\n        if (a.mask != b.mask) return a.mask < b.mask;\n        if (a.cost != b.cost) return a.cost < b.cost;\n        if (a.dir != b.dir)   return a.dir < b.dir;\n        if (a.p != b.p)       return a.p < b.p;\n        return a.len < b.len;\n    });\n\n    {\n        vector<Operation> filtered;\n        filtered.reserve(ops.size());\n        for (int i = 0; i < (int)ops.size(); ) {\n            int j = i + 1;\n            Operation best = ops[i];\n            while (j < (int)ops.size() && ops[j].mask == ops[i].mask) {\n                if (ops[j].cost < best.cost) best = ops[j];\n                ++j;\n            }\n            filtered.push_back(best);\n            i = j;\n        }\n        ops.swap(filtered);\n    }\n\n    int K_ops = (int)ops.size();\n\n    // Build cover lists: for each Oni, which operations cover it\n    vector<vector<int>> cover_ops(M);\n    for (int idx = 0; idx < K_ops; ++idx) {\n        uint64_t m = ops[idx].mask;\n        while (m) {\n            int b = __builtin_ctzll(m);\n            m &= m - 1;\n            cover_ops[b].push_back(idx);\n        }\n    }\n\n    // Safety: each Oni must be coverable\n    for (int i = 0; i < M; ++i) {\n        if (cover_ops[i].empty()) {\n            // Extremely unlikely if generation is correct; fallback: do nothing\n            return 0;\n        }\n    }\n\n    uint64_t all_mask = (M == 64) ? ~0ULL : ((1ULL << M) - 1);\n\n    // Weights for Oni: rarer Oni (fewer covering operations) get higher weight\n    vector<double> oni_weight(M);\n    for (int i = 0; i < M; ++i) {\n        int deg = (int)cover_ops[i].size();\n        oni_weight[i] = (deg > 0 ? 1.0 / deg : 1.0);\n    }\n\n    // RNG for randomized greedy\n    uint64_t seed = chrono::steady_clock::now().time_since_epoch().count();\n    mt19937_64 rng(seed);\n\n    int best_cost = INT_MAX / 2;\n    vector<int> best_sel;\n\n    // Helper: prune redundant selected operations\n    auto prune_selected = [&](vector<bool> &selected, int &total_cost, vector<int> &cover_count) {\n        bool changed = true;\n        while (changed) {\n            changed = false;\n            uint64_t singular_mask = 0;\n            for (int i = 0; i < M; ++i) {\n                if (cover_count[i] == 1) singular_mask |= (1ULL << i);\n            }\n            for (int op_idx = 0; op_idx < K_ops; ++op_idx) {\n                if (!selected[op_idx]) continue;\n                if ((ops[op_idx].mask & singular_mask) == 0) {\n                    // Removing this op won't uncover any Oni\n                    selected[op_idx] = false;\n                    total_cost -= ops[op_idx].cost;\n                    uint64_t m = ops[op_idx].mask;\n                    while (m) {\n                        int b = __builtin_ctzll(m);\n                        m &= m - 1;\n                        cover_count[b]--;\n                    }\n                    changed = true;\n                }\n            }\n        }\n    };\n\n    // Greedy (GRASP-like) set cover\n    auto run_greedy = [&](mt19937_64 &rng) -> pair<int, vector<int>> {\n        uint64_t uncovered = all_mask;\n        vector<int> chosen;\n        chosen.reserve(M);\n        int greedy_cost = 0;\n\n        const int RCL_SIZE = 4;\n\n        while (uncovered) {\n            double bestRatios[RCL_SIZE];\n            int bestIdx[RCL_SIZE];\n            for (int k = 0; k < RCL_SIZE; ++k) {\n                bestRatios[k] = -1.0;\n                bestIdx[k] = -1;\n            }\n\n            for (int i = 0; i < K_ops; ++i) {\n                uint64_t gainMask = ops[i].mask & uncovered;\n                if (!gainMask) continue;\n\n                double gain = 0.0;\n                uint64_t tmp = gainMask;\n                while (tmp) {\n                    int b = __builtin_ctzll(tmp);\n                    tmp &= tmp - 1;\n                    gain += oni_weight[b];\n                }\n                double ratio = gain / (double)ops[i].cost;\n\n                for (int k = 0; k < RCL_SIZE; ++k) {\n                    if (ratio > bestRatios[k]) {\n                        for (int sh = RCL_SIZE - 1; sh > k; --sh) {\n                            bestRatios[sh] = bestRatios[sh - 1];\n                            bestIdx[sh] = bestIdx[sh - 1];\n                        }\n                        bestRatios[k] = ratio;\n                        bestIdx[k] = i;\n                        break;\n                    }\n                }\n            }\n\n            if (bestIdx[0] == -1) {\n                // Cannot cover remaining Oni (should not happen)\n                break;\n            }\n\n            // Early stop if this run can't beat current best\n            if (greedy_cost >= best_cost) {\n                return make_pair(INT_MAX / 2, vector<int>());\n            }\n\n            int rcl_end = 0;\n            while (rcl_end + 1 < RCL_SIZE && bestIdx[rcl_end + 1] != -1) ++rcl_end;\n            uniform_int_distribution<int> dist(0, rcl_end);\n            int chosen_pos = dist(rng);\n            int op_idx = bestIdx[chosen_pos];\n\n            chosen.push_back(op_idx);\n            uint64_t gainMask = ops[op_idx].mask & uncovered;\n            uncovered &= ~gainMask;\n            greedy_cost += ops[op_idx].cost;\n        }\n\n        if (uncovered) {\n            // Failed to cover all Oni\n            return make_pair(INT_MAX / 2, vector<int>());\n        }\n\n        // Remove duplicates and prune redundancies\n        vector<bool> selected(K_ops, false);\n        vector<int> cover_count(M, 0);\n        int total_cost = 0;\n        for (int idx : chosen) {\n            if (!selected[idx]) {\n                selected[idx] = true;\n                total_cost += ops[idx].cost;\n                uint64_t m = ops[idx].mask;\n                while (m) {\n                    int b = __builtin_ctzll(m);\n                    m &= m - 1;\n                    cover_count[b]++;\n                }\n            }\n        }\n\n        prune_selected(selected, total_cost, cover_count);\n\n        // Verify coverage (for safety)\n        for (int i = 0; i < M; ++i) {\n            if (cover_count[i] == 0) {\n                return make_pair(INT_MAX / 2, vector<int>());\n            }\n        }\n\n        vector<int> result;\n        result.reserve(M);\n        for (int i = 0; i < K_ops; ++i) {\n            if (selected[i]) result.push_back(i);\n        }\n\n        return make_pair(total_cost, move(result));\n    };\n\n    // Local search: 1-for-1 and 1-for-2 exchanges\n    auto local_search = [&](vector<int> &sel, int &cost) {\n        vector<bool> selected(K_ops, false);\n        vector<int> cover_count(M, 0);\n        int total_cost = 0;\n\n        for (int idx : sel) {\n            if (!selected[idx]) {\n                selected[idx] = true;\n                total_cost += ops[idx].cost;\n                uint64_t m = ops[idx].mask;\n                while (m) {\n                    int b = __builtin_ctzll(m);\n                    m &= m - 1;\n                    cover_count[b]++;\n                }\n            }\n        }\n\n        prune_selected(selected, total_cost, cover_count);\n\n        // If coverage is somehow broken, abort local search\n        for (int i = 0; i < M; ++i) {\n            if (cover_count[i] == 0) {\n                return;\n            }\n        }\n\n        vector<int> mark(K_ops, 0);\n        int currentMark = 1;\n        vector<int> cand;\n        cand.reserve(64);\n\n        bool improved = true;\n        while (improved) {\n            improved = false;\n\n            // 1-for-1 improvements\n            uint64_t singular_mask = 0;\n            for (int i = 0; i < M; ++i) {\n                if (cover_count[i] == 1) singular_mask |= (1ULL << i);\n            }\n\n            for (int a = 0; a < K_ops && !improved; ++a) {\n                if (!selected[a]) continue;\n                uint64_t U_mask = ops[a].mask & singular_mask;\n                if (!U_mask) continue;\n\n                cand.clear();\n                if (++currentMark == INT_MAX) {\n                    fill(mark.begin(), mark.end(), 0);\n                    currentMark = 1;\n                }\n                uint64_t tmp = U_mask;\n                while (tmp) {\n                    int b = __builtin_ctzll(tmp);\n                    tmp &= tmp - 1;\n                    for (int op_idx : cover_ops[b]) {\n                        if (mark[op_idx] != currentMark) {\n                            mark[op_idx] = currentMark;\n                            cand.push_back(op_idx);\n                        }\n                    }\n                }\n\n                for (int b_idx : cand) {\n                    if (selected[b_idx]) continue;\n                    if (ops[b_idx].cost >= ops[a].cost) continue;\n                    if ((ops[b_idx].mask & U_mask) == U_mask) {\n                        // 1-for-1 replacement: a -> b_idx\n                        selected[a] = false;\n                        selected[b_idx] = true;\n                        total_cost += ops[b_idx].cost - ops[a].cost;\n\n                        uint64_t ma = ops[a].mask;\n                        while (ma) {\n                            int bit = __builtin_ctzll(ma);\n                            ma &= ma - 1;\n                            cover_count[bit]--;\n                        }\n                        uint64_t mb = ops[b_idx].mask;\n                        while (mb) {\n                            int bit = __builtin_ctzll(mb);\n                            mb &= mb - 1;\n                            cover_count[bit]++;\n                        }\n\n                        prune_selected(selected, total_cost, cover_count);\n                        improved = true;\n                        break;\n                    }\n                }\n            }\n\n            if (improved) continue;\n\n            // 1-for-2 improvements\n            singular_mask = 0;\n            for (int i = 0; i < M; ++i) {\n                if (cover_count[i] == 1) singular_mask |= (1ULL << i);\n            }\n\n            for (int a = 0; a < K_ops && !improved; ++a) {\n                if (!selected[a]) continue;\n                uint64_t U_mask = ops[a].mask & singular_mask;\n                if (!U_mask) continue;\n\n                cand.clear();\n                if (++currentMark == INT_MAX) {\n                    fill(mark.begin(), mark.end(), 0);\n                    currentMark = 1;\n                }\n                uint64_t tmp = U_mask;\n                while (tmp) {\n                    int b = __builtin_ctzll(tmp);\n                    tmp &= tmp - 1;\n                    for (int op_idx : cover_ops[b]) {\n                        if (mark[op_idx] != currentMark) {\n                            mark[op_idx] = currentMark;\n                            cand.push_back(op_idx);\n                        }\n                    }\n                }\n\n                int csz = (int)cand.size();\n                for (int i1 = 0; i1 < csz && !improved; ++i1) {\n                    int b_idx = cand[i1];\n                    if (selected[b_idx]) continue;\n                    for (int i2 = i1 + 1; i2 < csz; ++i2) {\n                        int c_idx = cand[i2];\n                        if (selected[c_idx]) continue;\n                        int newCost = ops[b_idx].cost + ops[c_idx].cost;\n                        if (newCost >= ops[a].cost) continue;\n                        uint64_t union_mask = ops[b_idx].mask | ops[c_idx].mask;\n                        if ((union_mask & U_mask) == U_mask) {\n                            // 1-for-2 replacement: a -> b_idx, c_idx\n                            selected[a] = false;\n                            selected[b_idx] = true;\n                            selected[c_idx] = true;\n                            total_cost += newCost - ops[a].cost;\n\n                            uint64_t ma = ops[a].mask;\n                            while (ma) {\n                                int bit = __builtin_ctzll(ma);\n                                ma &= ma - 1;\n                                cover_count[bit]--;\n                            }\n                            uint64_t mb = ops[b_idx].mask;\n                            while (mb) {\n                                int bit = __builtin_ctzll(mb);\n                                mb &= mb - 1;\n                                cover_count[bit]++;\n                            }\n                            uint64_t mc = ops[c_idx].mask;\n                            while (mc) {\n                                int bit = __builtin_ctzll(mc);\n                                mc &= mc - 1;\n                                cover_count[bit]++;\n                            }\n\n                            prune_selected(selected, total_cost, cover_count);\n                            improved = true;\n                            break;\n                        }\n                    }\n                }\n            }\n        }\n\n        // Final coverage check\n        for (int i = 0; i < M; ++i) {\n            if (cover_count[i] == 0) {\n                // Something went wrong; keep original sel/cost\n                return;\n            }\n        }\n\n        vector<int> new_sel;\n        new_sel.reserve(M);\n        for (int i = 0; i < K_ops; ++i) {\n            if (selected[i]) new_sel.push_back(i);\n        }\n\n        sel.swap(new_sel);\n        cost = total_cost;\n    };\n\n    // Multi-start greedy\n    const int MAX_RUNS = 200;\n    const int MAX_STAG = 80;\n    int stagnation = 0;\n\n    for (int iter = 0; iter < MAX_RUNS && stagnation < MAX_STAG; ++iter) {\n        auto [cost, sel] = run_greedy(rng);\n        if (cost >= INT_MAX / 4) continue;\n\n        uint64_t covered = 0;\n        for (int idx : sel) covered |= ops[idx].mask;\n        if (covered != all_mask) continue;\n\n        if (cost < best_cost) {\n            best_cost = cost;\n            best_sel = move(sel);\n            stagnation = 0;\n        } else {\n            ++stagnation;\n        }\n    }\n\n    if (best_sel.empty()) {\n        auto [cost, sel] = run_greedy(rng);\n        best_cost = cost;\n        best_sel = move(sel);\n    }\n\n    // Local search refinement\n    vector<int> ls_sel = best_sel;\n    int ls_cost = best_cost;\n    local_search(ls_sel, ls_cost);\n\n    uint64_t covered = 0;\n    for (int idx : ls_sel) covered |= ops[idx].mask;\n    if (covered == all_mask && ls_cost < best_cost) {\n        best_cost = ls_cost;\n        best_sel = move(ls_sel);\n    }\n\n    // Build the actual move sequence from best_sel\n    vector<pair<char,int>> moves;\n    moves.reserve(best_cost);\n\n    for (int idx : best_sel) {\n        const Operation &op = ops[idx];\n        char d1 = op.dir;\n        char d2;\n        if      (d1 == 'U') d2 = 'D';\n        else if (d1 == 'D') d2 = 'U';\n        else if (d1 == 'L') d2 = 'R';\n        else               d2 = 'L';\n\n        for (int k = 0; k < op.len; ++k) moves.emplace_back(d1, op.p);\n        for (int k = 0; k < op.len; ++k) moves.emplace_back(d2, op.p);\n    }\n\n    int T = (int)moves.size();\n    if (T > 4 * N * N) {\n        // Extremely unlikely with the above reasoning, but be safe.\n        return 0;\n    }\n\n    for (auto &mv : moves) {\n        cout << mv.first << ' ' << mv.second << '\\n';\n    }\n\n    return 0;\n}","ahc044":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const int MAXN = 100;\n\nstruct Candidate {\n    int a[MAXN];\n    int b[MAXN];\n    int t[MAXN];\n    int used[MAXN][2]; // edge usage counts: 0 -> a[i], 1 -> b[i]\n    long long E;\n};\n\n// Evaluate candidate by rotor-router simulation for L weeks\nvoid evalCandidate(Candidate &cand, int N, int L, const vector<long long> &T) {\n    static int rotor[MAXN];\n    for (int i = 0; i < N; ++i) {\n        cand.t[i] = 0;\n        rotor[i] = 0;\n        cand.used[i][0] = cand.used[i][1] = 0;\n    }\n\n    int cur = 0;  // week 1 cleaner is 0\n\n    // weeks 1..L-1: decide next cleaner\n    for (int week = 0; week < L - 1; ++week) {\n        int x = cur;\n        cand.t[x]++;\n\n        int e = rotor[x];\n        rotor[x] ^= 1;\n        int nxt = (e == 0 ? cand.a[x] : cand.b[x]);\n        cand.used[x][e]++;\n\n        cur = nxt;\n    }\n    // last week: count the final cleaner\n    cand.t[cur]++;\n\n    long long E = 0;\n    for (int i = 0; i < N; ++i) {\n        E += llabs((long long)cand.t[i] - T[i]);\n    }\n    cand.E = E;\n}\n\n// Build an \"ideal schedule\" based candidate using majority transitions\nCandidate buildMajorityCandidate(int N, int L, const vector<long long> &T, mt19937_64 &rng) {\n    Candidate cand;\n\n    // Work copy of T, ensure employee 0 appears at least once\n    vector<int> Twork(N);\n    for (int i = 0; i < N; ++i) Twork[i] = (int)T[i];\n\n    if (Twork[0] == 0) {\n        int j = 1;\n        for (int i = 2; i < N; ++i) {\n            if (Twork[i] > Twork[j]) j = i;\n        }\n        if (Twork[j] > 0) {\n            Twork[0] = 1;\n            Twork[j]--;\n        } else {\n            for (int i = 1; i < N; ++i) {\n                if (Twork[i] > 0) {\n                    Twork[i]--;\n                    break;\n                }\n            }\n            Twork[0] = 1;\n        }\n    }\n\n    // Build sequence of length L with counts Twork\n    vector<int> seq(L);\n    int pos = 0;\n    for (int i = 0; i < N; ++i) {\n        for (int k = 0; k < Twork[i]; ++k) {\n            if (pos < L) seq[pos++] = i;\n        }\n    }\n    if (pos < L) {\n        for (; pos < L; ++pos) seq[pos] = 0;\n    } else if (pos > L) {\n        seq.resize(L);\n    }\n\n    shuffle(seq.begin(), seq.end(), rng);\n\n    // Ensure seq[0] == 0 (since week1 cleaner is 0 in real process)\n    if (seq[0] != 0) {\n        for (int i = 1; i < L; ++i) {\n            if (seq[i] == 0) {\n                swap(seq[0], seq[i]);\n                break;\n            }\n        }\n        seq[0] = 0; // safety\n    }\n\n    vector<vector<int>> freqOdd(N, vector<int>(N, 0));\n    vector<vector<int>> freqEven(N, vector<int>(N, 0));\n    vector<int> cntVisit(N, 0);\n\n    for (int i = 0; i < N; ++i) cntVisit[i] = 0;\n\n    for (int i = 0; i < L - 1; ++i) {\n        int x = seq[i];\n        int y = seq[i + 1];\n        int k = ++cntVisit[x];\n        if (k & 1) freqOdd[x][y]++;\n        else       freqEven[x][y]++;\n    }\n\n    // Fallback destination: employee with largest T[i]\n    int fallback = 0;\n    for (int i = 1; i < N; ++i) {\n        if (T[i] > T[fallback]) fallback = i;\n    }\n\n    for (int x = 0; x < N; ++x) {\n        int best_j = fallback;\n        int best_c = 0;\n        for (int y = 0; y < N; ++y) {\n            if (freqOdd[x][y] > best_c) {\n                best_c = freqOdd[x][y];\n                best_j = y;\n            }\n        }\n        cand.a[x] = best_j;\n\n        best_j = fallback;\n        best_c = 0;\n        for (int y = 0; y < N; ++y) {\n            if (freqEven[x][y] > best_c) {\n                best_c = freqEven[x][y];\n                best_j = y;\n            }\n        }\n        cand.b[x] = best_j;\n    }\n\n    evalCandidate(cand, N, L, T);\n    return cand;\n}\n\n// Build template of edge destinations by apportionment according to T\nvector<int> buildDestTemplate(int N, const vector<long long> &T) {\n    vector<double> w(N);\n    double sumW = 0.0;\n    for (int i = 0; i < N; ++i) {\n        w[i] = (double)T[i] + 1.0; // +1 to avoid zero\n        sumW += w[i];\n    }\n    int totalEdges = 2 * N;\n\n    vector<double> ideal(N), frac(N);\n    vector<int> destCount(N, 0);\n    long long S = 0;\n\n    for (int i = 0; i < N; ++i) {\n        double val = totalEdges * w[i] / sumW;\n        ideal[i] = val;\n        int base = (int)floor(val);\n        destCount[i] = base;\n        frac[i] = val - base;\n        S += base;\n    }\n    int R = totalEdges - (int)S;\n    if (R < 0) R = 0;\n\n    vector<int> ord(N);\n    iota(ord.begin(), ord.end(), 0);\n    sort(ord.begin(), ord.end(), [&](int a, int b) {\n        return frac[a] > frac[b];\n    });\n    for (int k = 0; k < R && k < N; ++k) {\n        destCount[ord[k]]++;\n    }\n\n    vector<int> edgesDest;\n    edgesDest.reserve(totalEdges);\n    for (int i = 0; i < N; ++i) {\n        for (int c = 0; c < destCount[i]; ++c) {\n            edgesDest.push_back(i);\n        }\n    }\n    while ((int)edgesDest.size() > totalEdges) edgesDest.pop_back();\n    while ((int)edgesDest.size() < totalEdges) edgesDest.push_back(0);\n\n    return edgesDest;\n}\n\n// Build a random candidate from a given destination template\nCandidate buildRandomCandidateFromTemplate(const vector<int> &edgesTemplate,\n                                           int N, int L,\n                                           const vector<long long> &T,\n                                           mt19937_64 &rng) {\n    Candidate cand;\n    vector<int> edges = edgesTemplate; // copy\n    shuffle(edges.begin(), edges.end(), rng);\n\n    for (int i = 0; i < N; ++i) {\n        cand.a[i] = edges[2 * i];\n        cand.b[i] = edges[2 * i + 1];\n    }\n    evalCandidate(cand, N, L, T);\n    return cand;\n}\n\n// Mutate node idx's outgoing edges in candidate based on deficits (random/diversification move)\nvoid mutateNode(int idx,\n                Candidate &cand,\n                int N,\n                const vector<long long> &T,\n                const vector<int> &deficit,\n                const vector<int> &posIndices,\n                const vector<long long> &posPrefix,\n                long long sumPos,\n                const vector<long long> &Tprefix,\n                long long sumTw,\n                mt19937_64 &rng) {\n    auto samplePos = [&]() -> int {\n        if (sumPos <= 0 || posIndices.empty()) {\n            return idx; // fallback (should not generally happen)\n        }\n        long long r = (long long)(rng() % sumPos);\n        int pos = int(lower_bound(posPrefix.begin(), posPrefix.end(), r + 1) - posPrefix.begin());\n        if (pos < 0) pos = 0;\n        if (pos >= (int)posIndices.size()) pos = (int)posIndices.size() - 1;\n        return posIndices[pos];\n    };\n\n    auto sampleTdist = [&]() -> int {\n        if (sumTw <= 0) return idx;\n        long long r = (long long)(rng() % sumTw);\n        int pos = int(upper_bound(Tprefix.begin(), Tprefix.end(), r) - Tprefix.begin());\n        if (pos < 0) pos = 0;\n        if (pos >= N) pos = N - 1;\n        return pos;\n    };\n\n    if (deficit[idx] > 0) {\n        // node needs more visits: encourage self-loop\n        cand.a[idx] = idx;\n        if (sumPos > 0) {\n            cand.b[idx] = samplePos();\n        } else {\n            cand.b[idx] = sampleTdist();\n        }\n    } else {\n        // node has enough or too many visits: redirect to under-visited nodes\n        if (sumPos > 0) {\n            cand.a[idx] = samplePos();\n            cand.b[idx] = samplePos();\n        } else {\n            cand.a[idx] = sampleTdist();\n            cand.b[idx] = sampleTdist();\n        }\n    }\n\n    if (cand.a[idx] < 0) cand.a[idx] = 0;\n    if (cand.a[idx] >= N) cand.a[idx] = N - 1;\n    if (cand.b[idx] < 0) cand.b[idx] = 0;\n    if (cand.b[idx] >= N) cand.b[idx] = N - 1;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, L;\n    if (!(cin >> N >> L)) {\n        return 0;\n    }\n    vector<long long> T(N);\n    for (int i = 0; i < N; ++i) cin >> T[i];\n\n    mt19937_64 rng(123456789ULL);\n\n    auto startTime = chrono::steady_clock::now();\n    const int TIME_LIMIT_MS = 1950;\n\n    // Pre-build destination template from T\n    vector<int> destTemplate = buildDestTemplate(N, T);\n\n    // Best candidate\n    Candidate best;\n    bool bestInitialized = false;\n\n    // 1) Majority-based candidate from a shuffled ideal sequence\n    Candidate candMaj = buildMajorityCandidate(N, L, T, rng);\n    best = candMaj;\n    bestInitialized = true;\n\n    // 2) Some random candidates from destination template\n    const int INIT_RANDOM = 40;\n    for (int i = 0; i < INIT_RANDOM; ++i) {\n        Candidate c = buildRandomCandidateFromTemplate(destTemplate, N, L, T, rng);\n        if (!bestInitialized || c.E < best.E) {\n            best = c;\n            bestInitialized = true;\n        }\n    }\n\n    // Precompute T-weighted distribution for fallback sampling in local search\n    vector<long long> Tprefix(N);\n    long long sumTw = 0;\n    for (int i = 0; i < N; ++i) {\n        sumTw += (long long)T[i] + 1;\n        Tprefix[i] = sumTw;\n    }\n\n    // Local search: deficits and positive-deficit distribution\n    vector<int> deficit(N);\n    for (int i = 0; i < N; ++i) {\n        deficit[i] = (int)(T[i] - best.t[i]);\n    }\n\n    vector<int> posIndices;\n    vector<long long> posPrefix;\n    long long sumPos = 0;\n\n    auto updatePosDist = [&]() {\n        posIndices.clear();\n        posPrefix.clear();\n        sumPos = 0;\n        for (int i = 0; i < N; ++i) {\n            if (deficit[i] > 0) {\n                posIndices.push_back(i);\n                sumPos += deficit[i];\n                posPrefix.push_back(sumPos);\n            }\n        }\n    };\n    updatePosDist();\n\n    const int LOCAL_ITER_MAX = 600;\n\n    for (int iter = 0; iter < LOCAL_ITER_MAX; ++iter) {\n        if (iter % 8 == 0) {\n            auto now = chrono::steady_clock::now();\n            long long elapsed = chrono::duration_cast<chrono::milliseconds>(now - startTime).count();\n            if (elapsed > TIME_LIMIT_MS) break;\n        }\n\n        Candidate cand = best;  // copy\n\n        int numMut = 1;\n        if (iter > 200) numMut = 2;\n        if (iter > 400) numMut = 3;\n\n        // Sampling helpers for this iteration\n        auto samplePos = [&]() -> int {\n            if (sumPos <= 0 || posIndices.empty()) {\n                return (int)(rng() % N);\n            }\n            long long r = (long long)(rng() % sumPos);\n            int pos = int(lower_bound(posPrefix.begin(), posPrefix.end(), r + 1) - posPrefix.begin());\n            if (pos < 0) pos = 0;\n            if (pos >= (int)posIndices.size()) pos = (int)posIndices.size() - 1;\n            return posIndices[pos];\n        };\n\n        auto sampleTdist = [&]() -> int {\n            if (sumTw <= 0) return (int)(rng() % N);\n            long long r = (long long)(rng() % sumTw);\n            int pos = int(upper_bound(Tprefix.begin(), Tprefix.end(), r) - Tprefix.begin());\n            if (pos < 0) pos = 0;\n            if (pos >= N) pos = N - 1;\n            return pos;\n        };\n\n        bool usedTargeted = false;\n\n        // Decide whether to use targeted or random mutation\n        bool canTarget = (!posIndices.empty());\n        bool doTargeted = canTarget && (iter % 3 != 2); // ~2/3 of iterations use targeted\n\n        if (doTargeted) {\n            struct EdgeInfo {\n                int x;\n                int edge; // 0 or 1\n                long long score;\n            };\n            vector<EdgeInfo> edges;\n            edges.reserve(2 * N);\n\n            // Build list of \"bad\" edges: many uses into over-visited nodes\n            for (int x = 0; x < N; ++x) {\n                for (int e = 0; e < 2; ++e) {\n                    int uses = best.used[x][e];\n                    if (uses <= 0) continue;\n                    int child = (e == 0 ? best.a[x] : best.b[x]);\n                    if (deficit[child] < 0) {\n                        long long score = (long long)uses * (long long)(-deficit[child]);\n                        edges.push_back({x, e, score});\n                    }\n                }\n            }\n\n            if (!edges.empty() && sumPos > 0) {\n                sort(edges.begin(), edges.end(),\n                     [](const EdgeInfo &p, const EdgeInfo &q) {\n                         return p.score > q.score;\n                     });\n\n                int Ktop = (int)edges.size();\n                if (Ktop > 20) Ktop = 20; // focus on top edges\n\n                for (int m = 0; m < numMut && m < Ktop; ++m) {\n                    int idxEdge = m; // deterministic within top Ktop\n                    int x = edges[idxEdge].x;\n                    int e = edges[idxEdge].edge;\n\n                    int oldChild = (e == 0 ? cand.a[x] : cand.b[x]);\n                    int newChild = oldChild;\n\n                    int tries = 0;\n                    while (tries < 5) {\n                        newChild = samplePos();\n                        if (newChild != oldChild) break;\n                        ++tries;\n                    }\n                    if (newChild == oldChild) {\n                        // As a fallback, allow even if equal, but this likely won't happen often\n                        newChild = samplePos();\n                    }\n\n                    if (newChild < 0) newChild = 0;\n                    if (newChild >= N) newChild = N - 1;\n\n                    if (e == 0) cand.a[x] = newChild;\n                    else        cand.b[x] = newChild;\n                }\n                usedTargeted = true;\n            }\n        }\n\n        if (!usedTargeted) {\n            // Fallback / diversification: random node-based mutation\n            for (int k = 0; k < numMut; ++k) {\n                int idx = (int)(rng() % N);\n                mutateNode(idx, cand, N, T, deficit, posIndices, posPrefix, sumPos,\n                           Tprefix, sumTw, rng);\n            }\n        }\n\n        evalCandidate(cand, N, L, T);\n\n        if (cand.E < best.E) {\n            best = cand;\n            for (int i = 0; i < N; ++i) {\n                deficit[i] = (int)(T[i] - best.t[i]);\n            }\n            updatePosDist();\n        }\n    }\n\n    // Output best found a_i, b_i\n    for (int i = 0; i < N; ++i) {\n        int ai = best.a[i];\n        int bi = best.b[i];\n        if (ai < 0) ai = 0;\n        if (ai >= N) ai = N - 1;\n        if (bi < 0) bi = 0;\n        if (bi >= N) bi = N - 1;\n        cout << ai << ' ' << bi << '\\n';\n    }\n\n    return 0;\n}","ahc045":"#include <bits/stdc++.h>\nusing namespace std;\n\n// --------- Global constants ---------\nconst int MAXN = 800;\n\n// --------- Global data ---------\nint N, M, Q, L, W;\nint G_in[400];               // original group sizes\nint lx[MAXN], rx[MAXN], ly[MAXN], ry[MAXN];\nint cx[MAXN], cy[MAXN];      // centers\nint baseDist[MAXN][MAXN];    // squared distances using centers\nbool isGood[MAXN][MAXN];     // true if edge (i,j) appeared in some query-MST\nint B_bias = 0;              // bias to subtract for good edges\n\n// --------- Hilbert order ---------\nstatic uint64_t hilbert_order(int x, int y, int pow_bits) {\n    uint64_t res = 0;\n    for (int s = pow_bits - 1; s >= 0; --s) {\n        int rx = (x >> s) & 1;\n        int ry = (y >> s) & 1;\n        res <<= 2;\n        res |= (uint64_t)((rx * 3) ^ ry);\n        if (ry == 0) {\n            if (rx == 1) {\n                x = ((1 << pow_bits) - 1) - x;\n                y = ((1 << pow_bits) - 1) - y;\n            }\n            std::swap(x, y);\n        }\n    }\n    return res;\n}\n\n// --------- Build MST for one group using Prim ---------\nvoid buildMSTForGroup(const vector<int> &nodes,\n                      vector<pair<int,int>> &edgesOut,\n                      long long &costOut) {\n    int m = (int)nodes.size();\n    if (m <= 1) return;\n\n    const int INF = 1000000007;\n    edgesOut.clear();\n    edgesOut.reserve(max(0, m - 1));\n\n    static int best[MAXN];\n    static int parentIdx[MAXN];\n    static bool used[MAXN];\n\n    for (int i = 0; i < m; ++i) {\n        best[i] = INF;\n        parentIdx[i] = -1;\n        used[i] = false;\n    }\n\n    int root = 0;\n    used[root] = true;\n    // Initialize distances from root\n    for (int j = 1; j < m; ++j) {\n        int u = nodes[root];\n        int v = nodes[j];\n        int w = baseDist[u][v];\n        if (B_bias > 0 && isGood[u][v]) {\n            w -= B_bias;\n            if (w < 0) w = 0;\n        }\n        best[j] = w;\n        parentIdx[j] = root;\n    }\n\n    for (int it = 1; it < m; ++it) {\n        int t = -1;\n        int val = INF;\n        for (int i = 0; i < m; ++i) {\n            if (!used[i] && best[i] < val) {\n                val = best[i];\n                t = i;\n            }\n        }\n        if (t == -1) break; // shouldn't happen in complete graph\n\n        used[t] = true;\n        int u = nodes[t];\n        int pIdx = parentIdx[t];\n        if (pIdx != -1) {\n            int v = nodes[pIdx];\n            edgesOut.emplace_back(u, v);\n            costOut += val;\n        }\n\n        // Update distances using new node t\n        for (int i = 0; i < m; ++i) {\n            if (!used[i]) {\n                int uu = u;\n                int vv = nodes[i];\n                int w = baseDist[uu][vv];\n                if (B_bias > 0 && isGood[uu][vv]) {\n                    w -= B_bias;\n                    if (w < 0) w = 0;\n                }\n                if (w < best[i]) {\n                    best[i] = w;\n                    parentIdx[i] = t;\n                }\n            }\n        }\n    }\n}\n\n// --------- Main ---------\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    if (!(cin >> N >> M >> Q >> L >> W)) {\n        return 0;\n    }\n    for (int i = 0; i < M; ++i) cin >> G_in[i];\n    for (int i = 0; i < N; ++i) {\n        cin >> lx[i] >> rx[i] >> ly[i] >> ry[i];\n    }\n\n    // Approximate coordinates: centers\n    for (int i = 0; i < N; ++i) {\n        cx[i] = (lx[i] + rx[i]) / 2;\n        cy[i] = (ly[i] + ry[i]) / 2;\n    }\n\n    // Precompute squared distances between all pairs\n    for (int i = 0; i < N; ++i) {\n        baseDist[i][i] = 0;\n        for (int j = i + 1; j < N; ++j) {\n            long dx = (long)cx[i] - (long)cx[j];\n            long dy = (long)cy[i] - (long)cy[j];\n            long v = dx * dx + dy * dy;\n            if (v > INT_MAX) v = INT_MAX;\n            int d = (int)v;\n            baseDist[i][j] = baseDist[j][i] = d;\n        }\n    }\n\n    // Hilbert order of cities\n    const int HILBERT_BITS = 15; // 2^15 = 32768 > 10000\n    vector<pair<uint64_t,int>> hv(N);\n    for (int i = 0; i < N; ++i) {\n        uint64_t h = hilbert_order(cx[i], cy[i], HILBERT_BITS);\n        hv[i] = {h, i};\n    }\n    sort(hv.begin(), hv.end());\n    vector<int> order(N);\n    for (int i = 0; i < N; ++i) order[i] = hv[i].second;\n\n    // Initialize isGood to false\n    for (int i = 0; i < N; ++i) {\n        memset(isGood[i], 0, N * sizeof(bool));\n    }\n\n    // --------- Use queries to get local MST edges along Hilbert order ---------\n    vector<int> good_dists;\n    int qUsed = 0;\n\n    if (Q > 0 && L >= 2 && N > 1) {\n        if (N <= L) {\n            // Only one query on all cities (or all we choose)\n            int len = N;\n            cout << \"? \" << len;\n            vector<int> subset(len);\n            for (int k = 0; k < len; ++k) {\n                subset[k] = order[k];\n                cout << ' ' << subset[k];\n            }\n            cout << endl;\n\n            for (int t = 0; t < len - 1; ++t) {\n                int a, b;\n                cin >> a >> b;\n                if (!isGood[a][b]) {\n                    isGood[a][b] = isGood[b][a] = true;\n                    good_dists.push_back(baseDist[a][b]);\n                }\n            }\n            ++qUsed;\n        } else {\n            // Multiple overlapping windows along Hilbert order\n            int maxQueries = Q;\n            int numerator = (N - L) + (maxQueries - 2);\n            int step = numerator / (maxQueries - 1);\n            if (step < 1) step = 1;\n\n            for (int start = 0; start < N && qUsed < Q; start += step) {\n                int len = min(L, N - start);\n                if (len < 2) break;\n                cout << \"? \" << len;\n                vector<int> subset(len);\n                for (int k = 0; k < len; ++k) {\n                    subset[k] = order[start + k];\n                    cout << ' ' << subset[k];\n                }\n                cout << endl;\n\n                for (int t = 0; t < len - 1; ++t) {\n                    int a, b;\n                    cin >> a >> b;\n                    if (!isGood[a][b]) {\n                        isGood[a][b] = isGood[b][a] = true;\n                        good_dists.push_back(baseDist[a][b]);\n                    }\n                }\n                ++qUsed;\n            }\n        }\n    }\n\n    // --------- Determine bias B based on gathered good edges ---------\n    if (!good_dists.empty()) {\n        sort(good_dists.begin(), good_dists.end());\n        int med = good_dists[good_dists.size() / 2];\n        if (med > 0) {\n            B_bias = max(1, med / 8);  // moderate bias\n        } else {\n            B_bias = 0;\n        }\n    } else {\n        B_bias = 0;\n    }\n\n    // --------- Build candidate groupings ---------\n    struct Solution {\n        vector<vector<int>> groups;\n        vector<vector<pair<int,int>>> edges;\n        long long cost;\n    };\n    vector<Solution> candidates;\n    candidates.reserve(3);\n\n    // Helper lambda to build MSTs and compute cost for a given grouping\n    auto build_solution = [&](const vector<pair<int,int>> &sizeOrder) {\n        Solution sol;\n        sol.groups.assign(M, {});\n        int ptr = 0;\n        for (auto [sz, idxGroup] : sizeOrder) {\n            sol.groups[idxGroup].reserve(sz);\n            for (int k = 0; k < sz; ++k) {\n                sol.groups[idxGroup].push_back(order[ptr++]);\n            }\n        }\n        sol.edges.assign(M, {});\n        sol.cost = 0;\n        for (int g = 0; g < M; ++g) {\n            buildMSTForGroup(sol.groups[g], sol.edges[g], sol.cost);\n        }\n        candidates.push_back(std::move(sol));\n    };\n\n    // Pattern 0: sizes sorted descending\n    {\n        vector<pair<int,int>> sizeOrder; // (size, original_index)\n        sizeOrder.reserve(M);\n        for (int i = 0; i < M; ++i) sizeOrder.emplace_back(G_in[i], i);\n        sort(sizeOrder.begin(), sizeOrder.end(),\n             [](const auto &a, const auto &b) {\n                 if (a.first != b.first) return a.first > b.first; // larger first\n                 return a.second < b.second;\n             });\n        build_solution(sizeOrder);\n    }\n\n    // Pattern 1: sizes sorted ascending\n    {\n        vector<pair<int,int>> sizeOrder;\n        sizeOrder.reserve(M);\n        for (int i = 0; i < M; ++i) sizeOrder.emplace_back(G_in[i], i);\n        sort(sizeOrder.begin(), sizeOrder.end(),\n             [](const auto &a, const auto &b) {\n                 if (a.first != b.first) return a.first < b.first; // smaller first\n                 return a.second < b.second;\n             });\n        build_solution(sizeOrder);\n    }\n\n    // Pattern 2: original order of G\n    {\n        vector<pair<int,int>> sizeOrder;\n        sizeOrder.reserve(M);\n        for (int i = 0; i < M; ++i) sizeOrder.emplace_back(G_in[i], i);\n        // no reordering\n        build_solution(sizeOrder);\n    }\n\n    // Choose best candidate by approximate cost\n    int bestIdx = 0;\n    long long bestCost = candidates[0].cost;\n    for (int i = 1; i < (int)candidates.size(); ++i) {\n        if (candidates[i].cost < bestCost) {\n            bestCost = candidates[i].cost;\n            bestIdx = i;\n        }\n    }\n    Solution &bestSol = candidates[bestIdx];\n\n    // --------- Output final answer ---------\n    cout << \"!\\n\";\n    for (int g = 0; g < M; ++g) {\n        const auto &nodes = bestSol.groups[g];\n        int sz = (int)nodes.size();\n        for (int i = 0; i < sz; ++i) {\n            if (i) cout << ' ';\n            cout << nodes[i];\n        }\n        cout << '\\n';\n        const auto &edges = bestSol.edges[g];\n        for (auto &e : edges) {\n            cout << e.first << ' ' << e.second << '\\n';\n        }\n    }\n\n    return 0;\n}","ahc046":"#include <bits/stdc++.h>\nusing namespace std;\n\n// Directions: Up, Down, Left, Right\nconst int DX[4] = {-1, 1, 0, 0};\nconst int DY[4] = {0, 0, -1, 1};\nconst char DCH[4] = {'U', 'D', 'L', 'R'};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M;\n    if (!(cin >> N >> M)) return 0;\n\n    vector<pair<int,int>> points(M);\n    for (int k = 0; k < M; ++k) {\n        cin >> points[k].first >> points[k].second;\n    }\n\n    vector<char> actions; actions.reserve(2 * N * M);\n    vector<char> dirs;    dirs.reserve(2 * N * M);\n\n    int totalCells = N * N;\n\n    // BFS for each segment from points[k-1] to points[k]\n    for (int k = 1; k < M; ++k) {\n        int sx = points[k-1].first;\n        int sy = points[k-1].second;\n        int gx = points[k].first;\n        int gy = points[k].second;\n\n        int sidx = sx * N + sy;\n        int gidx = gx * N + gy;\n\n        // BFS arrays\n        static int dist[400];\n        static int prev_idx[400];\n        static char prev_action[400];\n        static char prev_dir[400];\n\n        const int INF = 1e9;\n        for (int i = 0; i < totalCells; ++i) {\n            dist[i] = INF;\n        }\n\n        queue<int> q;\n        dist[sidx] = 0;\n        prev_idx[sidx] = -1;\n        q.push(sidx);\n\n        while (!q.empty()) {\n            int v = q.front(); q.pop();\n            if (v == gidx) break;\n\n            int x = v / N;\n            int y = v % N;\n\n            for (int d = 0; d < 4; ++d) {\n                // Move\n                {\n                    int nx = x + DX[d];\n                    int ny = y + DY[d];\n                    if (0 <= nx && nx < N && 0 <= ny && ny < N) {\n                        int to = nx * N + ny;\n                        if (dist[to] == INF) {\n                            dist[to] = dist[v] + 1;\n                            prev_idx[to] = v;\n                            prev_action[to] = 'M';\n                            prev_dir[to] = DCH[d];\n                            q.push(to);\n                        }\n                    }\n                }\n                // Slide to border (no internal blocks)\n                {\n                    int nx = x, ny = y;\n                    if (d == 0) nx = 0;          // Up\n                    else if (d == 1) nx = N - 1; // Down\n                    else if (d == 2) ny = 0;     // Left\n                    else if (d == 3) ny = N - 1; // Right\n\n                    int to = nx * N + ny;\n                    if (to != v && dist[to] == INF) {\n                        dist[to] = dist[v] + 1;\n                        prev_idx[to] = v;\n                        prev_action[to] = 'S';\n                        prev_dir[to] = DCH[d];\n                        q.push(to);\n                    }\n                }\n            }\n        }\n\n        // Reconstruct path from gidx back to sidx\n        vector<char> seg_actions;\n        vector<char> seg_dirs;\n        int cur = gidx;\n        while (cur != sidx) {\n            seg_actions.push_back(prev_action[cur]);\n            seg_dirs.push_back(prev_dir[cur]);\n            cur = prev_idx[cur];\n        }\n        // Reverse to get correct order\n        for (int i = (int)seg_actions.size() - 1; i >= 0; --i) {\n            actions.push_back(seg_actions[i]);\n            dirs.push_back(seg_dirs[i]);\n        }\n    }\n\n    // Output\n    int T = (int)actions.size();\n    // We are guaranteed T <= 2*N*M from argument (<=1482 when no blocks)\n    for (int t = 0; t < T; ++t) {\n        cout << actions[t] << ' ' << dirs[t] << '\\n';\n    }\n\n    return 0;\n}"},"4":{"ahc001":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Rect {\n    int a, b, c, d; // [a,c) x [b,d)\n};\n\nint n;\nvector<int> xs, ys;\nvector<long long> rs;\n\n// Satisfaction for s <= r\ninline double satisfaction(long long s, long long r) {\n    if (s <= 0) return 0.0;\n    double q = (double)s / (double)r; // q in (0,1]\n    double t = 1.0 - q;\n    return 1.0 - t * t; // = 2q - q^2\n}\n\n// Positive-area overlap?\ninline bool overlap(const Rect &x, const Rect &y) {\n    return (x.a < y.c && y.a < x.c && x.b < y.d && y.b < x.d);\n}\n\n// Greedy growth for a given order. Fills rect and area, returns total score.\ndouble run_order(const vector<int> &order, vector<Rect> &rect, vector<long long> &area) {\n    rect.assign(n, Rect());\n    area.assign(n, 1);\n\n    // Initialize as 1x1 cells at seeds\n    for (int i = 0; i < n; ++i) {\n        rect[i].a = xs[i];\n        rect[i].c = xs[i] + 1;\n        rect[i].b = ys[i];\n        rect[i].d = ys[i] + 1;\n        area[i] = 1;\n    }\n\n    for (int pos = 0; pos < n; ++pos) {\n        int i = order[pos];\n        long long target = rs[i];\n        if (target <= 1) continue;\n\n        while (area[i] < target) {\n            Rect &cur = rect[i];\n            int w = cur.c - cur.a;\n            int h = cur.d - cur.b;\n            if (w <= 0 || h <= 0) break;\n            long long remaining = target - area[i];\n\n            int bestDir = -1;\n            int bestL = 0;\n            long long bestDelta = 0;\n\n            // 0: up (increase d)\n            if (cur.d < 10000 && remaining >= w) {\n                long long L_area = remaining / w;\n                if (L_area > 0) {\n                    int limit = 10000 - cur.d;\n                    if (limit > 0) {\n                        for (int j = 0; j < n; ++j) {\n                            if (j == i) continue;\n                            const Rect &s = rect[j];\n                            // x-overlap?\n                            if (s.a >= cur.c || s.c <= cur.a) continue;\n                            if (cur.d >= s.d) continue; // s below or touching\n                            if (s.b <= cur.d) {\n                                // s.b <= d < s.d, any extension hits s\n                                limit = 0;\n                                break;\n                            } else {\n                                int cand = s.b - cur.d;\n                                if (cand < limit) {\n                                    limit = cand;\n                                    if (limit <= 0) {\n                                        limit = 0;\n                                        break;\n                                    }\n                                }\n                            }\n                        }\n                        if (limit > 0) {\n                            int L = (int)min<long long>(limit, L_area);\n                            if (L > 0) {\n                                long long delta = 1LL * L * w;\n                                if (delta > bestDelta) {\n                                    bestDelta = delta;\n                                    bestDir = 0;\n                                    bestL = L;\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n\n            // 1: down (decrease b)\n            if (cur.b > 0 && remaining >= w) {\n                long long L_area = remaining / w;\n                if (L_area > 0) {\n                    int limit = cur.b;\n                    if (limit > 0) {\n                        for (int j = 0; j < n; ++j) {\n                            if (j == i) continue;\n                            const Rect &s = rect[j];\n                            // x-overlap?\n                            if (s.a >= cur.c || s.c <= cur.a) continue;\n                            if (s.b >= cur.b) continue; // s above or touching\n                            if (s.d > cur.b) {\n                                // s.b < b < s.d\n                                limit = 0;\n                                break;\n                            } else {\n                                int cand = cur.b - s.d;\n                                if (cand < limit) {\n                                    limit = cand;\n                                    if (limit <= 0) {\n                                        limit = 0;\n                                        break;\n                                    }\n                                }\n                            }\n                        }\n                        if (limit > 0) {\n                            int L = (int)min<long long>(limit, L_area);\n                            if (L > 0) {\n                                long long delta = 1LL * L * w;\n                                if (delta > bestDelta) {\n                                    bestDelta = delta;\n                                    bestDir = 1;\n                                    bestL = L;\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n\n            // 2: left (decrease a)\n            if (cur.a > 0 && remaining >= h) {\n                long long L_area = remaining / h;\n                if (L_area > 0) {\n                    int limit = cur.a;\n                    if (limit > 0) {\n                        for (int j = 0; j < n; ++j) {\n                            if (j == i) continue;\n                            const Rect &s = rect[j];\n                            // y-overlap?\n                            if (s.d <= cur.b || cur.d <= s.b) continue;\n                            if (s.a >= cur.a) {\n                                // s to the right or touching\n                                continue;\n                            } else {\n                                if (s.c > cur.a) {\n                                    // s crosses x = cur.a\n                                    limit = 0;\n                                    break;\n                                } else {\n                                    int cand = cur.a - s.c;\n                                    if (cand < limit) {\n                                        limit = cand;\n                                        if (limit <= 0) {\n                                            limit = 0;\n                                            break;\n                                        }\n                                    }\n                                }\n                            }\n                        }\n                        if (limit > 0) {\n                            int L = (int)min<long long>(limit, L_area);\n                            if (L > 0) {\n                                long long delta = 1LL * L * h;\n                                if (delta > bestDelta) {\n                                    bestDelta = delta;\n                                    bestDir = 2;\n                                    bestL = L;\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n\n            // 3: right (increase c)\n            if (cur.c < 10000 && remaining >= h) {\n                long long L_area = remaining / h;\n                if (L_area > 0) {\n                    int limit = 10000 - cur.c;\n                    if (limit > 0) {\n                        for (int j = 0; j < n; ++j) {\n                            if (j == i) continue;\n                            const Rect &s = rect[j];\n                            // y-overlap?\n                            if (s.d <= cur.b || cur.d <= s.b) continue;\n                            if (cur.c >= s.c) {\n                                // s to the left or touching\n                                continue;\n                            } else {\n                                if (s.a <= cur.c) {\n                                    // s crosses x = cur.c\n                                    limit = 0;\n                                    break;\n                                } else {\n                                    int cand = s.a - cur.c;\n                                    if (cand < limit) {\n                                        limit = cand;\n                                        if (limit <= 0) {\n                                            limit = 0;\n                                            break;\n                                        }\n                                    }\n                                }\n                            }\n                        }\n                        if (limit > 0) {\n                            int L = (int)min<long long>(limit, L_area);\n                            if (L > 0) {\n                                long long delta = 1LL * L * h;\n                                if (delta > bestDelta) {\n                                    bestDelta = delta;\n                                    bestDir = 3;\n                                    bestL = L;\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n\n            if (bestDir == -1 || bestL <= 0 || bestDelta <= 0) break;\n\n            switch (bestDir) {\n                case 0: cur.d += bestL; break;\n                case 1: cur.b -= bestL; break;\n                case 2: cur.a -= bestL; break;\n                case 3: cur.c += bestL; break;\n            }\n            area[i] += bestDelta;\n        }\n    }\n\n    double score = 0.0;\n    for (int i = 0; i < n; ++i) {\n        score += satisfaction(area[i], rs[i]);\n    }\n    return score;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> n;\n    xs.resize(n);\n    ys.resize(n);\n    rs.resize(n);\n    for (int i = 0; i < n; ++i) {\n        cin >> xs[i] >> ys[i] >> rs[i];\n    }\n\n    // Time management\n    const double ORDER_PHASE_END = 2.0; // seconds\n    const double SA_PHASE_END    = 4.6; // seconds (leave margin to 5.0)\n\n    auto time_start = chrono::steady_clock::now();\n    auto elapsed = [&]() -> double {\n        return chrono::duration<double>(chrono::steady_clock::now() - time_start).count();\n    };\n\n    // RNG\n    uint64_t seed = chrono::steady_clock::now().time_since_epoch().count();\n    seed ^= (uint64_t)n << 32;\n    if (n > 0) {\n        seed ^= (uint64_t)xs[0] * 10007 + (uint64_t)ys[0] * 1000003;\n    }\n    std::mt19937_64 rng(seed);\n\n    vector<int> base(n);\n    iota(base.begin(), base.end(), 0);\n\n    vector<Rect> rect, bestRect;\n    vector<long long> area, bestArea;\n    double bestScore = -1.0;\n\n    auto try_order = [&](const vector<int> &order) {\n        double sc = run_order(order, rect, area);\n        if (sc > bestScore) {\n            bestScore = sc;\n            bestRect = rect;\n            bestArea = area;\n        }\n    };\n\n    // Deterministic orders\n\n    // 1) increasing r\n    {\n        vector<int> ord = base;\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            if (rs[a] != rs[b]) return rs[a] < rs[b];\n            return a < b;\n        });\n        try_order(ord);\n    }\n    // 2) decreasing r\n    {\n        vector<int> ord = base;\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            if (rs[a] != rs[b]) return rs[a] > rs[b];\n            return a < b;\n        });\n        try_order(ord);\n    }\n    // 3) increasing x\n    {\n        vector<int> ord = base;\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            if (xs[a] != xs[b]) return xs[a] < xs[b];\n            return a < b;\n        });\n        try_order(ord);\n    }\n    // 4) increasing y\n    {\n        vector<int> ord = base;\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            if (ys[a] != ys[b]) return ys[a] < ys[b];\n            return a < b;\n        });\n        try_order(ord);\n    }\n\n    // Random permutations until ORDER_PHASE_END\n    {\n        vector<int> ord = base;\n        while (elapsed() < ORDER_PHASE_END) {\n            shuffle(ord.begin(), ord.end(), rng);\n            try_order(ord);\n        }\n    }\n\n    // Local search (simulated annealing) starting from bestRect\n    vector<Rect> curRect = bestRect;\n    vector<long long> curArea = bestArea;\n    vector<double> curP(n);\n    double curScore = 0.0;\n    for (int i = 0; i < n; ++i) {\n        curP[i] = satisfaction(curArea[i], rs[i]);\n        curScore += curP[i];\n    }\n    bestScore = curScore;\n    bestRect = curRect; // ensure consistency\n\n    double sa_start_time = elapsed();\n    double sa_total = SA_PHASE_END - sa_start_time;\n    if (sa_total > 0.0) {\n        uniform_int_distribution<int> distRect(0, n - 1);\n        uniform_real_distribution<double> dist01(0.0, 1.0);\n\n        // Temperature schedule\n        const double T0 = 1e-3;\n        const double T1 = 1e-5;\n\n        while (true) {\n            double tnow = elapsed();\n            if (tnow >= SA_PHASE_END) break;\n            double sa_elapsed = tnow - sa_start_time;\n            double progress = sa_elapsed / sa_total;\n            if (progress > 1.0) progress = 1.0;\n            double T = T0 + (T1 - T0) * progress; // linear cooling\n\n            // Choose a rectangle, biasing toward under-satisfied ones\n            int i = distRect(rng);\n            for (int tries = 0; tries < 4; ++tries) {\n                double fill0 = (double)curArea[i] / (double)rs[i];\n                if (fill0 < 0.99) break;\n                i = distRect(rng);\n            }\n\n            Rect old = curRect[i];\n            long long oldArea = curArea[i];\n            double oldPi = curP[i];\n\n            int w = old.c - old.a;\n            int h = old.d - old.b;\n            if (w <= 0 || h <= 0) continue;\n\n            double fill = (double)oldArea / (double)rs[i];\n\n            // Decide operation type (0..3 expand, 4..7 shrink, 8..11 shift)\n            int op;\n            if (fill < 0.98) {\n                // mostly expand and shift\n                uint64_t r = rng() % 10;\n                if (r < 6) { // 60% expand\n                    op = (int)(rng() % 4); // 0..3\n                } else if (r < 9) { // 30% shift\n                    op = 8 + (int)(rng() % 4); // 8..11\n                } else { // 10% shrink\n                    op = 4 + (int)(rng() % 4); // 4..7\n                }\n            } else {\n                // mostly shrink and shift\n                uint64_t r = rng() % 10;\n                if (r < 5) { // 50% shrink\n                    op = 4 + (int)(rng() % 4);\n                } else if (r < 8) { // 30% shift\n                    op = 8 + (int)(rng() % 4);\n                } else { // 20% expand\n                    op = (int)(rng() % 4);\n                }\n            }\n\n            Rect cand = old;\n            long long newArea = oldArea;\n            bool ok = true;\n            bool changed = false;\n\n            switch (op) {\n                case 0: { // expand left (a -= L)\n                    if (old.a == 0) { ok = false; break; }\n                    long long remaining = rs[i] - oldArea;\n                    if (remaining < h) { ok = false; break; }\n                    long long L_area = remaining / h;\n                    if (L_area <= 0) { ok = false; break; }\n                    int limit = old.a; // distance to boundary 0\n                    if (limit <= 0) { ok = false; break; }\n                    for (int j = 0; j < n; ++j) {\n                        if (j == i) continue;\n                        const Rect &s = curRect[j];\n                        // y-overlap?\n                        if (s.d <= old.b || old.d <= s.b) continue;\n                        if (s.a >= old.a) {\n                            // s to the right or touching\n                            continue;\n                        } else {\n                            if (s.c > old.a) {\n                                // s crosses x = old.a, cannot expand\n                                limit = 0;\n                                break;\n                            } else {\n                                int candLim = old.a - s.c;\n                                if (candLim < limit) {\n                                    limit = candLim;\n                                    if (limit <= 0) {\n                                        limit = 0;\n                                        break;\n                                    }\n                                }\n                            }\n                        }\n                    }\n                    if (limit <= 0) { ok = false; break; }\n                    {\n                        int L = (int)min<long long>(limit, L_area);\n                        if (L <= 0) { ok = false; break; }\n                        cand.a = old.a - L;\n                        newArea = oldArea + 1LL * L * h;\n                        changed = true;\n                    }\n                    break;\n                }\n                case 1: { // expand right (c += L)\n                    if (old.c == 10000) { ok = false; break; }\n                    long long remaining = rs[i] - oldArea;\n                    if (remaining < h) { ok = false; break; }\n                    long long L_area = remaining / h;\n                    if (L_area <= 0) { ok = false; break; }\n                    int limit = 10000 - old.c;\n                    if (limit <= 0) { ok = false; break; }\n                    for (int j = 0; j < n; ++j) {\n                        if (j == i) continue;\n                        const Rect &s = curRect[j];\n                        // y-overlap?\n                        if (s.d <= old.b || old.d <= s.b) continue;\n                        if (old.c >= s.c) {\n                            // s to the left or touching\n                            continue;\n                        } else {\n                            if (s.a <= old.c) {\n                                // s crosses x = old.c, cannot expand\n                                limit = 0;\n                                break;\n                            } else {\n                                int candLim = s.a - old.c;\n                                if (candLim < limit) {\n                                    limit = candLim;\n                                    if (limit <= 0) {\n                                        limit = 0;\n                                        break;\n                                    }\n                                }\n                            }\n                        }\n                    }\n                    if (limit <= 0) { ok = false; break; }\n                    {\n                        int L = (int)min<long long>(limit, L_area);\n                        if (L <= 0) { ok = false; break; }\n                        cand.c = old.c + L;\n                        newArea = oldArea + 1LL * L * h;\n                        changed = true;\n                    }\n                    break;\n                }\n                case 2: { // expand down (b -= L)\n                    if (old.b == 0) { ok = false; break; }\n                    long long remaining = rs[i] - oldArea;\n                    if (remaining < w) { ok = false; break; }\n                    long long L_area = remaining / w;\n                    if (L_area <= 0) { ok = false; break; }\n                    int limit = old.b; // distance to 0\n                    if (limit <= 0) { ok = false; break; }\n                    for (int j = 0; j < n; ++j) {\n                        if (j == i) continue;\n                        const Rect &s = curRect[j];\n                        // x-overlap?\n                        if (s.a >= old.c || s.c <= old.a) continue;\n                        if (s.b >= old.b) continue; // s above or touching\n                        if (s.d > old.b) {\n                            // s.b < b < s.d\n                            limit = 0;\n                            break;\n                        } else {\n                            int candLim = old.b - s.d;\n                            if (candLim < limit) {\n                                limit = candLim;\n                                if (limit <= 0) {\n                                    limit = 0;\n                                    break;\n                                }\n                            }\n                        }\n                    }\n                    if (limit <= 0) { ok = false; break; }\n                    {\n                        int L = (int)min<long long>(limit, L_area);\n                        if (L <= 0) { ok = false; break; }\n                        cand.b = old.b - L;\n                        newArea = oldArea + 1LL * L * w;\n                        changed = true;\n                    }\n                    break;\n                }\n                case 3: { // expand up (d += L)\n                    if (old.d == 10000) { ok = false; break; }\n                    long long remaining = rs[i] - oldArea;\n                    if (remaining < w) { ok = false; break; }\n                    long long L_area = remaining / w;\n                    if (L_area <= 0) { ok = false; break; }\n                    int limit = 10000 - old.d;\n                    if (limit <= 0) { ok = false; break; }\n                    for (int j = 0; j < n; ++j) {\n                        if (j == i) continue;\n                        const Rect &s = curRect[j];\n                        // x-overlap?\n                        if (s.a >= old.c || s.c <= old.a) continue;\n                        if (old.d >= s.d) continue; // s below or touching\n                        if (s.b <= old.d) {\n                            // s.b <= d < s.d\n                            limit = 0;\n                            break;\n                        } else {\n                            int candLim = s.b - old.d;\n                            if (candLim < limit) {\n                                limit = candLim;\n                                if (limit <= 0) {\n                                    limit = 0;\n                                    break;\n                                }\n                            }\n                        }\n                    }\n                    if (limit <= 0) { ok = false; break; }\n                    {\n                        int L = (int)min<long long>(limit, L_area);\n                        if (L <= 0) { ok = false; break; }\n                        cand.d = old.d + L;\n                        newArea = oldArea + 1LL * L * w;\n                        changed = true;\n                    }\n                    break;\n                }\n                case 4: { // shrink left (a++)\n                    if (w <= 1) { ok = false; break; }\n                    // seed must stay inside: xs[i] != old.a\n                    if (xs[i] == old.a) { ok = false; break; }\n                    cand.a = old.a + 1;\n                    newArea = oldArea - h;\n                    changed = true;\n                    break;\n                }\n                case 5: { // shrink right (c--)\n                    if (w <= 1) { ok = false; break; }\n                    if (xs[i] == old.c - 1) { ok = false; break; }\n                    cand.c = old.c - 1;\n                    newArea = oldArea - h;\n                    changed = true;\n                    break;\n                }\n                case 6: { // shrink down (b++)\n                    if (h <= 1) { ok = false; break; }\n                    if (ys[i] == old.b) { ok = false; break; }\n                    cand.b = old.b + 1;\n                    newArea = oldArea - w;\n                    changed = true;\n                    break;\n                }\n                case 7: { // shrink up (d--)\n                    if (h <= 1) { ok = false; break; }\n                    if (ys[i] == old.d - 1) { ok = false; break; }\n                    cand.d = old.d - 1;\n                    newArea = oldArea - w;\n                    changed = true;\n                    break;\n                }\n                case 8: { // shift left (a--, c--)\n                    if (old.a == 0) { ok = false; break; }\n                    // seed must stay inside after shift\n                    if (xs[i] == old.c - 1) { ok = false; break; }\n                    cand.a = old.a - 1;\n                    cand.c = old.c - 1;\n                    // area unchanged\n                    for (int j = 0; j < n; ++j) {\n                        if (j == i) continue;\n                        if (overlap(cand, curRect[j])) { ok = false; break; }\n                    }\n                    if (!ok) break;\n                    changed = true;\n                    break;\n                }\n                case 9: { // shift right (a++, c++)\n                    if (old.c == 10000) { ok = false; break; }\n                    if (xs[i] == old.a) { ok = false; break; }\n                    cand.a = old.a + 1;\n                    cand.c = old.c + 1;\n                    for (int j = 0; j < n; ++j) {\n                        if (j == i) continue;\n                        if (overlap(cand, curRect[j])) { ok = false; break; }\n                    }\n                    if (!ok) break;\n                    changed = true;\n                    break;\n                }\n                case 10: { // shift down (b--, d--)\n                    if (old.b == 0) { ok = false; break; }\n                    if (ys[i] == old.d - 1) { ok = false; break; }\n                    cand.b = old.b - 1;\n                    cand.d = old.d - 1;\n                    for (int j = 0; j < n; ++j) {\n                        if (j == i) continue;\n                        if (overlap(cand, curRect[j])) { ok = false; break; }\n                    }\n                    if (!ok) break;\n                    changed = true;\n                    break;\n                }\n                case 11: { // shift up (b++, d++)\n                    if (old.d == 10000) { ok = false; break; }\n                    if (ys[i] == old.b) { ok = false; break; }\n                    cand.b = old.b + 1;\n                    cand.d = old.d + 1;\n                    for (int j = 0; j < n; ++j) {\n                        if (j == i) continue;\n                        if (overlap(cand, curRect[j])) { ok = false; break; }\n                    }\n                    if (!ok) break;\n                    changed = true;\n                    break;\n                }\n            }\n\n            if (!ok || !changed) continue;\n            if (!(cand.a < cand.c && cand.b < cand.d)) continue;\n\n            double newPi = satisfaction(newArea, rs[i]);\n            double delta = newPi - oldPi;\n            double newScore = curScore + delta;\n\n            if (delta >= 0.0) {\n                // Always accept non-worse moves (expansion, shifts that don't hurt, some shrinks)\n                curRect[i] = cand;\n                curArea[i] = newArea;\n                curP[i] = newPi;\n                curScore = newScore;\n                if (curScore > bestScore) {\n                    bestScore = curScore;\n                    bestRect = curRect;\n                }\n            } else {\n                double prob = exp(delta / T);\n                double r = dist01(rng);\n                if (r < prob) {\n                    // Accept worse move\n                    curRect[i] = cand;\n                    curArea[i] = newArea;\n                    curP[i] = newPi;\n                    curScore = newScore;\n                    if (curScore > bestScore) {\n                        bestScore = curScore;\n                        bestRect = curRect;\n                    }\n                }\n                // else reject\n            }\n        }\n    }\n\n    // Output best layout\n    for (int i = 0; i < n; ++i) {\n        cout << bestRect[i].a << ' ' << bestRect[i].b << ' '\n             << bestRect[i].c << ' ' << bestRect[i].d << '\\n';\n    }\n\n    return 0;\n}","ahc002":"#include <bits/stdc++.h>\nusing namespace std;\n\n// Fast xorshift RNG\nstruct XorShift64 {\n    uint64_t x;\n    XorShift64() {\n        uint64_t seed = chrono::steady_clock::now().time_since_epoch().count();\n        x = seed ^ (seed << 13);\n    }\n    inline uint64_t next() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return x;\n    }\n    inline uint32_t next_u32() {\n        return static_cast<uint32_t>(next());\n    }\n};\n\nstruct Path {\n    int score;\n    vector<int> seq;\n};\n\nconstexpr int H = 50;\nconstexpr int W = 50;\nconstexpr int N = H * W;\nconstexpr int MAX_TILES = 2500;\n\nint tileID[N];                 // tile index for each cell\nint valCell[N];                // score of each cell\nint nei[N][4];                 // neighbors (cell indices)\nint neiCnt[N];                 // number of neighbors for each cell\nint visitedTime[MAX_TILES];    // last iteration stamp when tile was visited\nint startCell;                 // starting cell index\nint maxTileId;                 // maximum tile id in input\n\nint iterStamp = 0;\nXorShift64 rng;\n\n// Check if tile t is visited in current walk\ninline bool isVisitedTile(int t) {\n    return visitedTime[t] == iterStamp;\n}\n\n// Build one path using a given mode (0,1,2)\nPath build_path(int mode) {\n    ++iterStamp;\n    Path path;\n    path.seq.reserve(N);\n    path.score = 0;\n\n    int cur = startCell;\n    path.seq.push_back(cur);\n    path.score += valCell[cur];\n    visitedTime[tileID[cur]] = iterStamp;\n\n    while (true) {\n        int cand[4];\n        int candCount = 0;\n\n        // Collect candidate neighbors: adjacent cells whose tile is not yet visited\n        for (int k = 0; k < neiCnt[cur]; ++k) {\n            int v = nei[cur][k];\n            int t = tileID[v];\n            if (isVisitedTile(t)) continue; // tile already visited\n            cand[candCount++] = v;\n        }\n\n        if (candCount == 0) break;\n\n        int deg[4];\n\n        // Compute \"forward degree\" for each candidate: how many moves are possible after stepping there\n        for (int i = 0; i < candCount; ++i) {\n            int v = cand[i];\n            int tv = tileID[v];\n            int d = 0;\n            for (int k = 0; k < neiCnt[v]; ++k) {\n                int w = nei[v][k];\n                int tw = tileID[w];\n                if (tw == tv) continue;                 // same tile, won't be allowed after step\n                if (isVisitedTile(tw)) continue;        // tile already used\n                ++d;\n            }\n            deg[i] = d;\n        }\n\n        int chosenIdx = 0;\n\n        if (mode == 0) {\n            // Mode 0: balanced\n            // Prefer class 0 (deg>=2), then 1 (deg==1), then 2 (deg==0)\n            // Within class: smaller deg first, then higher value\n            int bestClass = 3;\n            int bestDeg = 1000;\n            int bestVal = -1;\n            for (int i = 0; i < candCount; ++i) {\n                int d = deg[i];\n                int cls = (d >= 2 ? 0 : (d == 1 ? 1 : 2));\n                int v = cand[i];\n                int pv = valCell[v];\n                bool better = false;\n\n                if (cls < bestClass) {\n                    better = true;\n                } else if (cls == bestClass) {\n                    if (d < bestDeg) {\n                        better = true;\n                    } else if (d == bestDeg) {\n                        if (pv > bestVal) {\n                            better = true;\n                        } else if (pv == bestVal) {\n                            // random tie-break\n                            if (rng.next_u32() & 1u) better = true;\n                        }\n                    }\n                }\n\n                if (better) {\n                    bestClass = cls;\n                    bestDeg = d;\n                    bestVal = pv;\n                    chosenIdx = i;\n                }\n            }\n        } else if (mode == 1) {\n            // Mode 1: Warnsdorff-like (minimize deg), but avoid deg=0 if possible.\n            bool hasPositive = false;\n            for (int i = 0; i < candCount; ++i) {\n                if (deg[i] > 0) { hasPositive = true; break; }\n            }\n\n            int bestDeg = 1000;\n            int bestVal = -1;\n            for (int i = 0; i < candCount; ++i) {\n                int d = deg[i];\n                if (hasPositive && d == 0) continue; // skip dead-ends if any extension exists\n                int v = cand[i];\n                int pv = valCell[v];\n                bool better = false;\n\n                if (d < bestDeg) {\n                    better = true;\n                } else if (d == bestDeg) {\n                    if (pv > bestVal) {\n                        better = true;\n                    } else if (pv == bestVal) {\n                        if (rng.next_u32() & 1u) better = true;\n                    }\n                }\n\n                if (better) {\n                    bestDeg = d;\n                    bestVal = pv;\n                    chosenIdx = i;\n                }\n            }\n        } else {\n            // Mode 2: value-first, but avoid deg=0 if possible.\n            bool hasPositive = false;\n            for (int i = 0; i < candCount; ++i) {\n                if (deg[i] > 0) { hasPositive = true; break; }\n            }\n\n            int bestVal = -1;\n            int bestDeg = -1;\n            for (int i = 0; i < candCount; ++i) {\n                int d = deg[i];\n                if (hasPositive && d == 0) continue; // skip dead-ends if any extension exists\n                int v = cand[i];\n                int pv = valCell[v];\n                bool better = false;\n\n                if (pv > bestVal) {\n                    better = true;\n                } else if (pv == bestVal) {\n                    if (d > bestDeg) {\n                        better = true;\n                    } else if (d == bestDeg) {\n                        if (rng.next_u32() & 1u) better = true;\n                    }\n                }\n\n                if (better) {\n                    bestVal = pv;\n                    bestDeg = d;\n                    chosenIdx = i;\n                }\n            }\n        }\n\n        // Small random exploration: 5% chance choose totally random candidate\n        if (candCount > 1 && (rng.next_u32() % 20u == 0u)) {\n            chosenIdx = rng.next_u32() % candCount;\n        }\n\n        int nextCell = cand[chosenIdx];\n        cur = nextCell;\n        path.seq.push_back(cur);\n        path.score += valCell[cur];\n        visitedTime[tileID[cur]] = iterStamp;\n    }\n\n    return path;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int si, sj;\n    if (!(cin >> si >> sj)) {\n        return 0;\n    }\n\n    maxTileId = -1;\n\n    // Read tiles\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            int t;\n            cin >> t;\n            int idx = i * W + j;\n            tileID[idx] = t;\n            if (t > maxTileId) maxTileId = t;\n        }\n    }\n\n    // Read cell values\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            int p;\n            cin >> p;\n            int idx = i * W + j;\n            valCell[idx] = p;\n        }\n    }\n\n    // Precompute neighbors on the grid (4-neighborhood)\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            int idx = i * W + j;\n            int cnt = 0;\n            if (i > 0)     nei[idx][cnt++] = (i - 1) * W + j;\n            if (i + 1 < H) nei[idx][cnt++] = (i + 1) * W + j;\n            if (j > 0)     nei[idx][cnt++] = i * W + (j - 1);\n            if (j + 1 < W) nei[idx][cnt++] = i * W + (j + 1);\n            neiCnt[idx] = cnt;\n        }\n    }\n\n    // Initialize visitedTime\n    for (int i = 0; i <= maxTileId; ++i) visitedTime[i] = 0;\n\n    startCell = si * W + sj;\n\n    auto startTime = chrono::steady_clock::now();\n    const double TIME_LIMIT = 1.9; // seconds\n\n    Path best;\n    best.score = -1;\n\n    int iterations = 0;\n    while (true) {\n        int mode = static_cast<int>(rng.next_u32() % 3u); // 0,1,2\n        Path cur = build_path(mode);\n\n        if (cur.score > best.score ||\n            (cur.score == best.score && cur.seq.size() > best.seq.size())) {\n            best = std::move(cur);\n        }\n\n        ++iterations;\n        if ((iterations & 7) == 0) { // check time every 8 iterations\n            auto now = chrono::steady_clock::now();\n            double elapsed = chrono::duration<double>(now - startTime).count();\n            if (elapsed > TIME_LIMIT) break;\n        }\n    }\n\n    // Convert best.seq (cells) into moves string\n    string ans;\n    ans.reserve(best.seq.size());\n    for (size_t k = 1; k < best.seq.size(); ++k) {\n        int prev = best.seq[k - 1];\n        int cur = best.seq[k];\n        int pi = prev / W, pj = prev % W;\n        int ci = cur / W, cj = cur % W;\n        if (ci == pi) {\n            if (cj == pj + 1) ans.push_back('R');\n            else if (cj == pj - 1) ans.push_back('L');\n        } else if (cj == pj) {\n            if (ci == pi + 1) ans.push_back('D');\n            else if (ci == pi - 1) ans.push_back('U');\n        }\n        // No other case should occur because we only move to neighbors.\n    }\n\n    cout << ans << '\\n';\n    return 0;\n}","ahc003":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const int H = 30;\nstatic const int W = 30;\nstatic const int N = H * W;\nstatic const int EH = H * (W - 1);\nstatic const int EV = (H - 1) * W;\nstatic const int E = EH + EV;\nstatic const double INF = 1e100;\n\n// Edge indices for canonical orientations\nint h_id[H][W - 1]; // horizontal: (i,j)-(i,j+1) -> h_id[i][j]\nint v_id[H - 1][W]; // vertical:   (i,j)-(i+1,j) -> v_id[i][j]\n\n// Adjacency: for each vertex, (to, edge_id)\nvector<pair<int,int>> adj[N];\n\n// Edge weights (our estimates) and their randomized version per query\nvector<double> w(E), eff_w(E);\n\n// Dijkstra buffers\ndouble dist_arr[N];\nint prev_v_arr[N];\nint prev_e_arr[N];\n\ninline int vid(int i, int j) {\n    return i * W + j;\n}\n\n// RNG for jitter\nmt19937_64 rng(71236782123ULL);\n\ninline double rand01() {\n    return std::generate_canonical<double, 53>(rng); // [0,1)\n}\n\n// Dijkstra using eff_w, returns path as \"UDLR\"\nstring dijkstra_path(int si, int sj, int ti, int tj, int query_id) {\n    // Jitter decreases over time\n    const double JITTER0 = 0.03;\n    double jitter = JITTER0 * max(0.0, 1.0 - (double)query_id / 800.0);\n    if (jitter < 0.0) jitter = 0.0;\n\n    // Build jittered weights\n    for (int e = 0; e < E; ++e) {\n        double u = 2.0 * rand01() - 1.0; // [-1,1)\n        double factor = 1.0 + jitter * u;\n        if (factor < 0.5) factor = 0.5; // safety\n        eff_w[e] = w[e] * factor;\n        if (eff_w[e] < 1.0) eff_w[e] = 1.0; // strictly positive\n    }\n\n    int s = vid(si, sj);\n    int t = vid(ti, tj);\n\n    // Initialize Dijkstra\n    for (int i = 0; i < N; ++i) {\n        dist_arr[i] = INF;\n        prev_v_arr[i] = -1;\n        prev_e_arr[i] = -1;\n    }\n    dist_arr[s] = 0.0;\n\n    using P = pair<double,int>;\n    priority_queue<P, vector<P>, greater<P>> pq;\n    pq.emplace(0.0, s);\n\n    while (!pq.empty()) {\n        auto [d, u] = pq.top();\n        pq.pop();\n        if (d != dist_arr[u]) continue;\n        if (u == t) break;\n        for (auto &pe : adj[u]) {\n            int v = pe.first;\n            int eid = pe.second;\n            double nd = d + eff_w[eid];\n            if (nd < dist_arr[v]) {\n                dist_arr[v] = nd;\n                prev_v_arr[v] = u;\n                prev_e_arr[v] = eid;\n                pq.emplace(nd, v);\n            }\n        }\n    }\n\n    // Reconstruct path\n    string rev;\n    int v = t;\n    while (v != s) {\n        int u = prev_v_arr[v];\n        if (u == -1) {\n            // Fallback: Manhattan path if something goes wrong\n            rev.clear();\n            int ci = si, cj = sj;\n            while (ci < ti) { rev.push_back('D'); ++ci; }\n            while (ci > ti) { rev.push_back('U'); --ci; }\n            while (cj < tj) { rev.push_back('R'); ++cj; }\n            while (cj > tj) { rev.push_back('L'); --cj; }\n            break;\n        }\n        int ui = u / W, uj = u % W;\n        int vi = v / W, vj = v % W;\n        if (vi == ui) {\n            if (vj == uj + 1) rev.push_back('R');\n            else if (vj == uj - 1) rev.push_back('L');\n        } else if (vj == uj) {\n            if (vi == ui + 1) rev.push_back('D');\n            else if (vi == ui - 1) rev.push_back('U');\n        }\n        v = u;\n    }\n    reverse(rev.begin(), rev.end());\n    return rev;\n}\n\n// Convert move string into list of edge IDs\nvoid path_to_edges(int si, int sj, const string &path, vector<int> &edges) {\n    edges.clear();\n    edges.reserve(path.size());\n    int i = si, j = sj;\n    for (char c : path) {\n        int eid = -1;\n        if (c == 'U') {\n            int ni = i - 1;\n            eid = v_id[ni][j]; // edge between (ni,j) and (ni+1,j)\n            i = ni;\n        } else if (c == 'D') {\n            eid = v_id[i][j]; // edge between (i,j) and (i+1,j)\n            i = i + 1;\n        } else if (c == 'L') {\n            int nj = j - 1;\n            eid = h_id[i][nj]; // edge between (i,nj) and (i,nj+1)\n            j = nj;\n        } else if (c == 'R') {\n            eid = h_id[i][j]; // edge between (i,j) and (i,j+1)\n            j = j + 1;\n        }\n        edges.push_back(eid);\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // Build graph and edge indexing\n    int eid = 0;\n    // Horizontal edges\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W - 1; ++j) {\n            h_id[i][j] = eid;\n            int u = vid(i, j);\n            int v = vid(i, j + 1);\n            adj[u].emplace_back(v, eid);\n            adj[v].emplace_back(u, eid);\n            ++eid;\n        }\n    }\n    // Vertical edges\n    for (int i = 0; i < H - 1; ++i) {\n        for (int j = 0; j < W; ++j) {\n            v_id[i][j] = eid;\n            int u = vid(i, j);\n            int v = vid(i + 1, j);\n            adj[u].emplace_back(v, eid);\n            adj[v].emplace_back(u, eid);\n            ++eid;\n        }\n    }\n\n    // Initialize weights\n    w.assign(E, 5000.0);\n    eff_w.assign(E, 5000.0);\n\n    vector<int> edges;\n    const double ETA = 0.5; // learning rate multiplier\n\n    for (int q = 0; q < 1000; ++q) {\n        int si, sj, ti, tj;\n        if (!(cin >> si >> sj >> ti >> tj)) {\n            return 0; // EOF / error\n        }\n\n        // Compute path\n        string path = dijkstra_path(si, sj, ti, tj, q);\n\n        // Output and flush\n        cout << path << '\\n';\n        cout.flush();\n\n        long long y_ll;\n        if (!(cin >> y_ll)) {\n            return 0; // EOF / error\n        }\n        double y = (double)y_ll;\n\n        // Update weights based on feedback\n        path_to_edges(si, sj, path, edges);\n        int L = (int)edges.size();\n        if (L == 0) continue; // shouldn't happen (distance >= 10)\n\n        double pred = 0.0;\n        for (int e : edges) {\n            pred += w[e];\n        }\n        double error = y - pred;\n\n        double lr = ETA / (double)L;\n        for (int e : edges) {\n            w[e] += lr * error;\n            if (w[e] < 1000.0) w[e] = 1000.0;\n            else if (w[e] > 9000.0) w[e] = 9000.0;\n        }\n    }\n\n    return 0;\n}","ahc004":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const int MAX_N = 20;\nstatic const int MAX_M = 800;\nstatic const int ALPHA = 8;\nstatic const int MAXW = (MAX_M + 63) / 64;\n\nint N, M;\nint WORDS; // actual number of 64-bit words used\nvector<string> patterns;\n\n// bitset over up to MAX_M bits\nstruct BS {\n    uint64_t w[MAXW];\n};\n\n// bitset helpers\ninline void bs_clear(BS &b) {\n    // clear all words; cost is tiny (<= 13 words)\n    memset(b.w, 0, sizeof(b.w));\n}\ninline void bs_or_inplace(BS &a, const BS &b) {\n    for (int i = 0; i < WORDS; ++i) a.w[i] |= b.w[i];\n}\ninline void bs_xor(BS &res, const BS &a, const BS &b) {\n    for (int i = 0; i < WORDS; ++i) res.w[i] = a.w[i] ^ b.w[i];\n}\ninline void bs_or(BS &res, const BS &a, const BS &b) {\n    for (int i = 0; i < WORDS; ++i) res.w[i] = a.w[i] | b.w[i];\n}\ninline bool bs_test(const BS &b, int idx) {\n    return (b.w[idx >> 6] >> (idx & 63)) & 1ULL;\n}\ninline void bs_set(BS &b, int idx) {\n    b.w[idx >> 6] |= 1ULL << (idx & 63);\n}\ninline void bs_reset(BS &b, int idx) {\n    b.w[idx >> 6] &= ~(1ULL << (idx & 63));\n}\n\n// iterate over set bits of b, calling f(idx) for each\ntemplate <class F>\ninline void bs_for_each(const BS &b, F f) {\n    for (int w = 0; w < WORDS; ++w) {\n        uint64_t x = b.w[w];\n        while (x) {\n            int lsb = __builtin_ctzll(x);\n            int idx = (w << 6) + lsb;\n            if (idx >= M) return; // safety; bits >=M are never set\n            f(idx);\n            x &= x - 1; // clear lowest set bit\n        }\n    }\n}\n\n// Aho\u2013Corasick automaton\nstruct Node {\n    int next[ALPHA];\n    int link;\n    BS out; // bitset of patterns that end at this state (including via failure)\n    Node() {\n        fill(next, next + ALPHA, -1);\n        link = 0;\n        bs_clear(out);\n    }\n};\nvector<Node> ac;\n\n// grid\nchar grid[MAX_N][MAX_N];\n\n// row/col pattern presence\nBS row_bs[MAX_N], col_bs[MAX_N];\n\n// pattern coverage count across all rows+cols\nint pattern_cov_count[MAX_M];\nint current_c = 0;\n\n// RNG\nmt19937_64 rng;\n\ninline int ch_idx(char c) {\n    return c - 'A'; // 'A'..'H' -> 0..7\n}\n\nvoid build_automaton() {\n    ac.clear();\n    ac.emplace_back(); // root\n\n    // build trie and set pattern bits\n    for (int i = 0; i < M; ++i) {\n        const string &s = patterns[i];\n        int v = 0;\n        for (char ch : s) {\n            int c = ch_idx(ch);\n            if (ac[v].next[c] == -1) {\n                ac[v].next[c] = (int)ac.size();\n                ac.emplace_back();\n            }\n            v = ac[v].next[c];\n        }\n        bs_set(ac[v].out, i);\n    }\n\n    // build failure links\n    queue<int> q;\n\n    // initialize root transitions\n    for (int c = 0; c < ALPHA; ++c) {\n        int u = ac[0].next[c];\n        if (u != -1) {\n            ac[u].link = 0;\n            q.push(u);\n        } else {\n            ac[0].next[c] = 0;\n        }\n    }\n\n    while (!q.empty()) {\n        int v = q.front(); q.pop();\n        int link = ac[v].link;\n\n        // propagate pattern bits from failure link\n        bs_or_inplace(ac[v].out, ac[link].out);\n\n        for (int c = 0; c < ALPHA; ++c) {\n            int u = ac[v].next[c];\n            if (u != -1) {\n                ac[u].link = ac[link].next[c];\n                q.push(u);\n            } else {\n                ac[v].next[c] = ac[link].next[c];\n            }\n        }\n    }\n}\n\n// scan a line through AC, return bitset of patterns appearing\ninline BS scan_line(const char *s, int len) {\n    BS res;\n    bs_clear(res);\n    int v = 0;\n    for (int i = 0; i < len; ++i) {\n        int c = ch_idx(s[i]);\n        v = ac[v].next[c];\n        bs_or_inplace(res, ac[v].out);\n    }\n    return res;\n}\n\n// recompute one row r and update global counts\nvoid recalc_row(int r) {\n    char line[2 * MAX_N];\n    for (int j = 0; j < N; ++j) line[j] = grid[r][j];\n    for (int j = 0; j < N; ++j) line[N + j] = line[j];\n\n    BS mark = scan_line(line, 2 * N);\n    BS changed;\n    bs_xor(changed, row_bs[r], mark);\n\n    bs_for_each(changed, [&](int i) {\n        bool oldFlag = bs_test(row_bs[r], i);\n        bool newFlag = bs_test(mark, i);\n        if (oldFlag == newFlag) return; // should not happen but safe\n\n        if (newFlag) {\n            bs_set(row_bs[r], i);\n            if (pattern_cov_count[i] == 0) current_c++;\n            pattern_cov_count[i]++;\n        } else {\n            bs_reset(row_bs[r], i);\n            pattern_cov_count[i]--;\n            if (pattern_cov_count[i] == 0) current_c--;\n        }\n    });\n}\n\n// recompute one column c and update global counts\nvoid recalc_col(int c) {\n    char line[2 * MAX_N];\n    for (int i = 0; i < N; ++i) line[i] = grid[i][c];\n    for (int i = 0; i < N; ++i) line[N + i] = line[i];\n\n    BS mark = scan_line(line, 2 * N);\n    BS changed;\n    bs_xor(changed, col_bs[c], mark);\n\n    bs_for_each(changed, [&](int i) {\n        bool oldFlag = bs_test(col_bs[c], i);\n        bool newFlag = bs_test(mark, i);\n        if (oldFlag == newFlag) return; // should not happen but safe\n\n        if (newFlag) {\n            bs_set(col_bs[c], i);\n            if (pattern_cov_count[i] == 0) current_c++;\n            pattern_cov_count[i]++;\n        } else {\n            bs_reset(col_bs[c], i);\n            pattern_cov_count[i]--;\n            if (pattern_cov_count[i] == 0) current_c--;\n        }\n    });\n}\n\n// pattern \"kick\" move: force-place a random pattern somewhere\nvoid apply_pattern_kick() {\n    uniform_int_distribution<int> pat_dist(0, M - 1);\n    int pid = pat_dist(rng);\n    const string &s = patterns[pid];\n    int len = (int)s.size();\n\n    uniform_int_distribution<int> dir_dist(0, 1);\n    int dir = dir_dist(rng); // 0: horizontal, 1: vertical\n\n    bool rowChanged[MAX_N] = {false};\n    bool colChanged[MAX_N] = {false};\n\n    if (dir == 0) {\n        uniform_int_distribution<int> row_dist(0, N - 1);\n        uniform_int_distribution<int> col_dist(0, N - 1);\n        int r = row_dist(rng);\n        int c0 = col_dist(rng);\n\n        int c = c0;\n        for (int t = 0; t < len; ++t) {\n            if (grid[r][c] != s[t]) {\n                grid[r][c] = s[t];\n                rowChanged[r] = true;\n                colChanged[c] = true;\n            }\n            c++;\n            if (c == N) c = 0;\n        }\n    } else {\n        uniform_int_distribution<int> row_dist(0, N - 1);\n        uniform_int_distribution<int> col_dist(0, N - 1);\n        int r0 = row_dist(rng);\n        int c = col_dist(rng);\n\n        int r = r0;\n        for (int t = 0; t < len; ++t) {\n            if (grid[r][c] != s[t]) {\n                grid[r][c] = s[t];\n                rowChanged[r] = true;\n                colChanged[c] = true;\n            }\n            r++;\n            if (r == N) r = 0;\n        }\n    }\n\n    for (int r = 0; r < N; ++r) if (rowChanged[r]) recalc_row(r);\n    for (int c = 0; c < N; ++c) if (colChanged[c]) recalc_col(c);\n}\n\ndouble my_rand_double() {\n    // 53-bit mantissa random double in [0,1)\n    return (rng() >> 11) * (1.0 / (1ULL << 53));\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> M;\n    patterns.resize(M);\n    for (int i = 0; i < M; ++i) cin >> patterns[i];\n\n    WORDS = (M + 63) / 64;\n\n    // init RNG\n    uint64_t seed = chrono::high_resolution_clock::now().time_since_epoch().count();\n    rng.seed(seed);\n\n    build_automaton();\n\n    uniform_int_distribution<int> letter_dist(0, ALPHA - 1);\n\n    // initial grid: random letters\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            grid[i][j] = char('A' + letter_dist(rng));\n\n    // constructive pass: greedily place patterns to align with existing letters\n    vector<int> order(M);\n    iota(order.begin(), order.end(), 0);\n    shuffle(order.begin(), order.end(), rng);\n\n    for (int idx = 0; idx < M; ++idx) {\n        int pid = order[idx];\n        const string &s = patterns[pid];\n        int len = (int)s.size();\n\n        int bestScore = -1;\n        int bestDir = 0;\n        int bestR = 0;\n        int bestC = 0;\n\n        // horizontal candidates\n        for (int r = 0; r < N; ++r) {\n            for (int c0 = 0; c0 < N; ++c0) {\n                int score = 0;\n                int c = c0;\n                for (int t = 0; t < len; ++t) {\n                    if (grid[r][c] == s[t]) score++;\n                    c++;\n                    if (c == N) c = 0;\n                }\n                if (score > bestScore) {\n                    bestScore = score;\n                    bestDir = 0;\n                    bestR = r;\n                    bestC = c0;\n                } else if (score == bestScore && my_rand_double() < 0.5) {\n                    bestScore = score;\n                    bestDir = 0;\n                    bestR = r;\n                    bestC = c0;\n                }\n            }\n        }\n\n        // vertical candidates\n        for (int c = 0; c < N; ++c) {\n            for (int r0 = 0; r0 < N; ++r0) {\n                int score = 0;\n                int r = r0;\n                for (int t = 0; t < len; ++t) {\n                    if (grid[r][c] == s[t]) score++;\n                    r++;\n                    if (r == N) r = 0;\n                }\n                if (score > bestScore) {\n                    bestScore = score;\n                    bestDir = 1;\n                    bestR = r0;\n                    bestC = c;\n                } else if (score == bestScore && my_rand_double() < 0.5) {\n                    bestScore = score;\n                    bestDir = 1;\n                    bestR = r0;\n                    bestC = c;\n                }\n            }\n        }\n\n        // apply best placement\n        if (bestDir == 0) {\n            int r = bestR;\n            int c = bestC;\n            for (int t = 0; t < len; ++t) {\n                grid[r][c] = s[t];\n                c++;\n                if (c == N) c = 0;\n            }\n        } else {\n            int c = bestC;\n            int r = bestR;\n            for (int t = 0; t < len; ++t) {\n                grid[r][c] = s[t];\n                r++;\n                if (r == N) r = 0;\n            }\n        }\n    }\n\n    // Initialize evaluation\n    for (int r = 0; r < N; ++r) bs_clear(row_bs[r]);\n    for (int c = 0; c < N; ++c) bs_clear(col_bs[c]);\n    fill(pattern_cov_count, pattern_cov_count + M, 0);\n    current_c = 0;\n\n    for (int r = 0; r < N; ++r) recalc_row(r);\n    for (int c = 0; c < N; ++c) recalc_col(c);\n\n    // SA parameters\n    const double TIME_LIMIT = 2.75; // seconds for SA part\n    auto start_time = chrono::high_resolution_clock::now();\n    double T0 = 1.5;\n    double T1 = 0.05;\n\n    // keep best grid\n    char best_grid[MAX_N][MAX_N];\n    int best_c = current_c;\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            best_grid[i][j] = grid[i][j];\n\n    int iter = 0;\n    uniform_int_distribution<int> row_dist(0, N - 1);\n    uniform_int_distribution<int> col_dist(0, N - 1);\n\n    while (true) {\n        auto now = chrono::high_resolution_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        if (elapsed > TIME_LIMIT) break;\n        double progress = elapsed / TIME_LIMIT;\n        double T = T0 + (T1 - T0) * progress;\n\n        // occasional pattern kick in early phase\n        if ((iter % 2000 == 0) && (progress < 0.5)) {\n            apply_pattern_kick();\n            if (current_c > best_c) {\n                best_c = current_c;\n                for (int i = 0; i < N; ++i)\n                    for (int j = 0; j < N; ++j)\n                        best_grid[i][j] = grid[i][j];\n            }\n        }\n\n        int r = row_dist(rng);\n        int c = col_dist(rng);\n        char oldCh = grid[r][c];\n\n        char newCh;\n        do {\n            newCh = char('A' + letter_dist(rng));\n        } while (newCh == oldCh);\n\n        // candidate row\n        char row_line[2 * MAX_N];\n        for (int j = 0; j < N; ++j)\n            row_line[j] = (j == c) ? newCh : grid[r][j];\n        for (int j = 0; j < N; ++j)\n            row_line[N + j] = row_line[j];\n\n        BS mark_row = scan_line(row_line, 2 * N);\n\n        // candidate column\n        char col_line[2 * MAX_N];\n        for (int i = 0; i < N; ++i)\n            col_line[i] = (i == r) ? newCh : grid[i][c];\n        for (int i = 0; i < N; ++i)\n            col_line[N + i] = col_line[i];\n\n        BS mark_col = scan_line(col_line, 2 * N);\n\n        // changed patterns on row and column\n        BS changed_row, changed_col, changed_union;\n        bs_xor(changed_row, row_bs[r], mark_row);\n        bs_xor(changed_col, col_bs[c], mark_col);\n        bs_or(changed_union, changed_row, changed_col);\n\n        int new_c = current_c;\n\n        // compute new_c considering only changed patterns\n        bs_for_each(changed_union, [&](int i) {\n            int oldCov = pattern_cov_count[i];\n            int newCov = oldCov;\n\n            bool oldRow = bs_test(row_bs[r], i);\n            bool newRow = bs_test(mark_row, i);\n            newCov += (int)newRow - (int)oldRow;\n\n            bool oldCol = bs_test(col_bs[c], i);\n            bool newCol = bs_test(mark_col, i);\n            newCov += (int)newCol - (int)oldCol;\n\n            if (oldCov == 0 && newCov > 0) new_c++;\n            else if (oldCov > 0 && newCov == 0) new_c--;\n        });\n\n        int delta = new_c - current_c;\n        bool accept = false;\n        if (delta >= 0) {\n            accept = true;\n        } else {\n            double prob = exp((double)delta / T);\n            if (prob > my_rand_double()) accept = true;\n        }\n\n        if (accept) {\n            // commit the change\n            grid[r][c] = newCh;\n            bs_for_each(changed_union, [&](int i) {\n                int oldCov = pattern_cov_count[i];\n                int newCov = oldCov;\n\n                bool oldRow = bs_test(row_bs[r], i);\n                bool newRow = bs_test(mark_row, i);\n                newCov += (int)newRow - (int)oldRow;\n\n                bool oldCol = bs_test(col_bs[c], i);\n                bool newCol = bs_test(mark_col, i);\n                newCov += (int)newCol - (int)oldCol;\n\n                pattern_cov_count[i] = newCov;\n\n                if (newRow) bs_set(row_bs[r], i);\n                else bs_reset(row_bs[r], i);\n                if (newCol) bs_set(col_bs[c], i);\n                else bs_reset(col_bs[c], i);\n            });\n            current_c = new_c;\n\n            if (current_c > best_c) {\n                best_c = current_c;\n                for (int i = 0; i < N; ++i)\n                    for (int j = 0; j < N; ++j)\n                        best_grid[i][j] = grid[i][j];\n            }\n        }\n\n        ++iter;\n    }\n\n    // Output best grid\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cout << best_grid[i][j];\n        }\n        cout << '\\n';\n    }\n\n    return 0;\n}","ahc005":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Edge {\n    int to;\n    int w;\n};\n\nconst int INF = 1e9;\n\n// Compute travel time of a route (sequence of cell IDs).\n// Cost to move into cell v is cost[v].\nlong long computeTravelTime(const vector<int> &route, const vector<int> &cost) {\n    long long t = 0;\n    for (int i = 1; i < (int)route.size(); ++i) {\n        t += cost[route[i]];\n    }\n    return t;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, si, sj;\n    if (!(cin >> N >> si >> sj)) return 0;\n    vector<string> grid(N);\n    for (int i = 0; i < N; ++i) cin >> grid[i];\n\n    // Map each road cell to an ID\n    static int idOf[70][70];\n    int r = 0;\n    vector<pair<int,int>> pos;   // id -> (i,j)\n    vector<int> cost;            // id -> cell cost (5-9)\n    pos.reserve(N * N);\n    cost.reserve(N * N);\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (grid[i][j] != '#') {\n                idOf[i][j] = r++;\n                pos.emplace_back(i, j);\n                cost.push_back(grid[i][j] - '0');\n            } else {\n                idOf[i][j] = -1;\n            }\n        }\n    }\n\n    if (r == 0) {\n        cout << \"\\n\";\n        return 0;\n    }\n\n    int startId = idOf[si][sj];\n\n    // Build graph of road cells\n    vector<vector<Edge>> G(r);\n    int di[4] = {-1, 1, 0, 0};\n    int dj[4] = {0, 0, -1, 1};\n    for (int id = 0; id < r; ++id) {\n        auto [i, j] = pos[id];\n        for (int d = 0; d < 4; ++d) {\n            int ni = i + di[d], nj = j + dj[d];\n            if (0 <= ni && ni < N && 0 <= nj && nj < N && idOf[ni][nj] != -1) {\n                int v = idOf[ni][nj];\n                G[id].push_back({v, cost[v]});\n            }\n        }\n    }\n\n    // ---------- Fallback DFS route (visit all cells) ----------\n    auto buildDFSRoute = [&]() -> vector<int> {\n        vector<int> route;\n        route.reserve(2 * r + 5);\n        vector<char> used(r, 0);\n        vector<int> st;\n        vector<int> edgeIdx(r, 0);\n\n        route.push_back(startId);\n        used[startId] = 1;\n        st.push_back(startId);\n\n        while (!st.empty()) {\n            int u = st.back();\n            bool advanced = false;\n            int &ei = edgeIdx[u];\n            while (ei < (int)G[u].size()) {\n                int v = G[u][ei].to;\n                ++ei;\n                if (!used[v]) {\n                    used[v] = 1;\n                    st.push_back(v);\n                    route.push_back(v);\n                    advanced = true;\n                    break;\n                }\n            }\n            if (!advanced) {\n                st.pop_back();\n                if (!st.empty()) {\n                    route.push_back(st.back());\n                }\n            }\n        }\n        return route; // starts and ends at startId\n    };\n\n    vector<int> fallbackRoute = buildDFSRoute();\n    long long fallbackTime = computeTravelTime(fallbackRoute, cost);\n\n    // ---------- Build horizontal and vertical segments ----------\n    vector<vector<int>> rowSegCells;\n    vector<int> rowSegIdOfCell(r, -1);\n    for (int i = 0; i < N; ++i) {\n        int j = 0;\n        while (j < N) {\n            if (grid[i][j] == '#') {\n                ++j;\n                continue;\n            }\n            int segIdx = (int)rowSegCells.size();\n            rowSegCells.emplace_back();\n            while (j < N && grid[i][j] != '#') {\n                int id = idOf[i][j];\n                rowSegIdOfCell[id] = segIdx;\n                rowSegCells.back().push_back(id);\n                ++j;\n            }\n        }\n    }\n\n    vector<vector<int>> colSegCells;\n    vector<int> colSegIdOfCell(r, -1);\n    for (int j = 0; j < N; ++j) {\n        int i = 0;\n        while (i < N) {\n            if (grid[i][j] == '#') {\n                ++i;\n                continue;\n            }\n            int segIdx = (int)colSegCells.size();\n            colSegCells.emplace_back();\n            while (i < N && grid[i][j] != '#') {\n                int id = idOf[i][j];\n                colSegIdOfCell[id] = segIdx;\n                colSegCells.back().push_back(id);\n                ++i;\n            }\n        }\n    }\n\n    // ---------- Precompute visibility (coverage) for all cells ----------\n    vector<vector<int>> coverageAll(r);\n    for (int id = 0; id < r; ++id) {\n        auto &v = coverageAll[id];\n        auto &rowV = rowSegCells[rowSegIdOfCell[id]];\n        auto &colV = colSegCells[colSegIdOfCell[id]];\n        v.reserve(rowV.size() + colV.size());\n        for (int x : rowV) v.push_back(x);\n        for (int x : colV) v.push_back(x);\n    }\n\n    // ---------- Build candidate vantage cells (mostly intersections) ----------\n    vector<char> isIntersection(r, 0);\n    vector<char> hasInterRow(rowSegCells.size(), 0);\n    vector<char> hasInterCol(colSegCells.size(), 0);\n\n    for (int id = 0; id < r; ++id) {\n        auto [i, j] = pos[id];\n        bool hor = false, ver = false;\n        if (j > 0 && idOf[i][j-1] != -1) hor = true;\n        if (j+1 < N && idOf[i][j+1] != -1) hor = true;\n        if (i > 0 && idOf[i-1][j] != -1) ver = true;\n        if (i+1 < N && idOf[i+1][j] != -1) ver = true;\n        if (hor && ver) {\n            isIntersection[id] = 1;\n            hasInterRow[rowSegIdOfCell[id]] = 1;\n            hasInterCol[colSegIdOfCell[id]] = 1;\n        }\n    }\n\n    vector<char> isCandidate(r, 0);\n    vector<int> candidateCells;\n    candidateCells.reserve(r);\n\n    // Intersections\n    for (int id = 0; id < r; ++id) {\n        if (isIntersection[id]) {\n            isCandidate[id] = 1;\n            candidateCells.push_back(id);\n        }\n    }\n    // Midpoints of segments without intersections\n    for (int s = 0; s < (int)rowSegCells.size(); ++s) {\n        if (!hasInterRow[s]) {\n            int mid = rowSegCells[s][rowSegCells[s].size() / 2];\n            if (!isCandidate[mid]) {\n                isCandidate[mid] = 1;\n                candidateCells.push_back(mid);\n            }\n        }\n    }\n    for (int s = 0; s < (int)colSegCells.size(); ++s) {\n        if (!hasInterCol[s]) {\n            int mid = colSegCells[s][colSegCells[s].size() / 2];\n            if (!isCandidate[mid]) {\n                isCandidate[mid] = 1;\n                candidateCells.push_back(mid);\n            }\n        }\n    }\n    // Ensure start cell is candidate\n    if (!isCandidate[startId]) {\n        isCandidate[startId] = 1;\n        candidateCells.push_back(startId);\n    }\n\n    // Coverage of candidates, and which cells are coverable by some candidate\n    int C = (int)candidateCells.size();\n    vector<vector<int>> candCover;\n    candCover.reserve(C);\n    vector<char> cellCovered(r, 0);\n    for (int idx = 0; idx < C; ++idx) {\n        int cell = candidateCells[idx];\n        candCover.push_back(coverageAll[cell]);\n        for (int x : candCover.back()) cellCovered[x] = 1;\n    }\n\n    // Patch: if some cell is not covered by any candidate, add it itself as candidate\n    for (int id = 0; id < r; ++id) {\n        if (!cellCovered[id]) {\n            candidateCells.push_back(id);\n            candCover.push_back(coverageAll[id]);\n            for (int x : coverageAll[id]) cellCovered[x] = 1;\n        }\n    }\n    C = (int)candidateCells.size();\n\n    // ---------- Greedy set cover on candidates (cell-based) ----------\n    vector<int> vantageCells;        // resulting vantage cell IDs\n    vantageCells.reserve(C);\n\n    vector<char> coveredCells(r, 0);\n    int coveredCount = 0;\n    vector<char> candSelected(C, 0);\n\n    auto selectCandidate = [&](int idx) {\n        if (candSelected[idx]) return;\n        candSelected[idx] = 1;\n        int cell = candidateCells[idx];\n        vantageCells.push_back(cell);\n        for (int x : candCover[idx]) {\n            if (!coveredCells[x]) {\n                coveredCells[x] = 1;\n                ++coveredCount;\n            }\n        }\n    };\n\n    // Use start cell as the first vantage\n    int startCandIdx = -1;\n    for (int idx = 0; idx < C; ++idx) {\n        if (candidateCells[idx] == startId) {\n            startCandIdx = idx;\n            break;\n        }\n    }\n    if (startCandIdx == -1) {\n        // Safeguard (shouldn't happen)\n        vantageCells.push_back(startId);\n        for (int x : coverageAll[startId]) {\n            if (!coveredCells[x]) {\n                coveredCells[x] = 1;\n                ++coveredCount;\n            }\n        }\n    } else {\n        selectCandidate(startCandIdx);\n    }\n\n    while (coveredCount < r) {\n        int bestIdx = -1;\n        int bestGain = -1;\n        for (int idx = 0; idx < C; ++idx) {\n            if (candSelected[idx]) continue;\n            int gain = 0;\n            for (int x : candCover[idx]) {\n                if (!coveredCells[x]) ++gain;\n            }\n            if (gain > bestGain) {\n                bestGain = gain;\n                bestIdx = idx;\n            } else if (gain == bestGain && gain > 0 && bestIdx != -1) {\n                // Tie-break: closer to start (Manhattan)\n                int cellNew = candidateCells[idx];\n                int cellBest = candidateCells[bestIdx];\n                auto [ni, nj] = pos[cellNew];\n                auto [bi, bj] = pos[cellBest];\n                int manNew = abs(ni - si) + abs(nj - sj);\n                int manBest = abs(bi - si) + abs(bj - sj);\n                if (manNew < manBest) bestIdx = idx;\n            }\n        }\n\n        if (bestIdx == -1 || bestGain <= 0) {\n            // Safeguard: directly add some uncovered cell as vantage\n            int uncoveredId = -1;\n            for (int id = 0; id < r; ++id) {\n                if (!coveredCells[id]) {\n                    uncoveredId = id;\n                    break;\n                }\n            }\n            if (uncoveredId == -1) break; // should not happen\n            vantageCells.push_back(uncoveredId);\n            for (int x : coverageAll[uncoveredId]) {\n                if (!coveredCells[x]) {\n                    coveredCells[x] = 1;\n                    ++coveredCount;\n                }\n            }\n        } else {\n            selectCandidate(bestIdx);\n        }\n    }\n\n    // Deduplicate vantages (just in case)\n    sort(vantageCells.begin(), vantageCells.end());\n    vantageCells.erase(unique(vantageCells.begin(), vantageCells.end()), vantageCells.end());\n\n    // ---------- Eliminate redundant vantages using coverage frequencies ----------\n    {\n        int V = (int)vantageCells.size();\n        if (V > 0) {\n            vector<int> freq(r, 0);\n\n            // Base coverage from starting cell (we always start there)\n            for (int c : coverageAll[startId]) freq[c]++;\n\n            // Add contributions from all vantages\n            for (int v : vantageCells) {\n                for (int c : coverageAll[v]) freq[c]++;\n            }\n\n            // Process vantages in ascending order of coverage size (remove small ones first)\n            vector<int> order(V);\n            iota(order.begin(), order.end(), 0);\n            sort(order.begin(), order.end(), [&](int a, int b) {\n                return coverageAll[vantageCells[a]].size() < coverageAll[vantageCells[b]].size();\n            });\n\n            vector<char> removed(V, 0);\n            for (int idx : order) {\n                int v = vantageCells[idx];\n                bool canRemove = true;\n                for (int c : coverageAll[v]) {\n                    if (freq[c] <= 1) { // would leave some cell uncovered\n                        canRemove = false;\n                        break;\n                    }\n                }\n                if (!canRemove) continue;\n                // Remove this vantage\n                removed[idx] = 1;\n                for (int c : coverageAll[v]) {\n                    --freq[c];\n                }\n            }\n\n            vector<int> reduced;\n            reduced.reserve(V);\n            for (int i = 0; i < V; ++i) {\n                if (!removed[i]) reduced.push_back(vantageCells[i]);\n            }\n            vantageCells.swap(reduced);\n        }\n    }\n\n    // ---------- Dijkstra helpers ----------\n    vector<int> dist(r), prevv(r);\n\n    auto dijkstraToDest = [&](int src, int dest) {\n        fill(dist.begin(), dist.end(), INF);\n        fill(prevv.begin(), prevv.end(), -1);\n        priority_queue<pair<int,int>, vector<pair<int,int>>, greater<pair<int,int>>> pq;\n        dist[src] = 0;\n        pq.push({0, src});\n        while (!pq.empty()) {\n            auto [d, u] = pq.top();\n            pq.pop();\n            if (d != dist[u]) continue;\n            if (u == dest) break;\n            for (auto &e : G[u]) {\n                int v = e.to;\n                int nd = d + e.w;\n                if (nd < dist[v]) {\n                    dist[v] = nd;\n                    prevv[v] = u;\n                    pq.push({nd, v});\n                }\n            }\n        }\n    };\n\n    auto appendPath = [&](vector<int> &route, int src, int dest) {\n        if (src == dest) return;\n        dijkstraToDest(src, dest);\n        vector<int> tmp;\n        int x = dest;\n        while (x != src && x != -1) {\n            tmp.push_back(x);\n            x = prevv[x];\n        }\n        for (int i = (int)tmp.size() - 1; i >= 0; --i) {\n            route.push_back(tmp[i]);\n        }\n    };\n\n    auto dijkstraNearestTarget = [&](int src,\n                                     const vector<char> &isTarget,\n                                     const vector<char> &visitedTarget) -> int {\n        fill(dist.begin(), dist.end(), INF);\n        fill(prevv.begin(), prevv.end(), -1);\n        priority_queue<pair<int,int>, vector<pair<int,int>>, greater<pair<int,int>>> pq;\n        dist[src] = 0;\n        pq.push({0, src});\n        int target = -1;\n        while (!pq.empty()) {\n            auto [d, u] = pq.top();\n            pq.pop();\n            if (d != dist[u]) continue;\n            if (isTarget[u] && !visitedTarget[u]) {\n                target = u;\n                break;\n            }\n            for (auto &e : G[u]) {\n                int v = e.to;\n                int nd = d + e.w;\n                if (nd < dist[v]) {\n                    dist[v] = nd;\n                    prevv[v] = u;\n                    pq.push({nd, v});\n                }\n            }\n        }\n        return target;\n    };\n\n    // ---------- Route 1: Greedy nearest neighbor on vantages ----------\n    auto buildRouteGreedyNN = [&](const vector<int> &vantages) -> vector<int> {\n        vector<int> route;\n        route.reserve(2 * r + 5);\n\n        vector<char> isTarget(r, 0), visitedTarget(r, 0);\n        for (int id : vantages) isTarget[id] = 1;\n\n        int remainingTargets = 0;\n        for (int id : vantages) {\n            if (id == startId) {\n                visitedTarget[id] = 1;\n            } else {\n                ++remainingTargets;\n            }\n        }\n\n        route.push_back(startId);\n        int curr = startId;\n\n        while (remainingTargets > 0) {\n            int target = dijkstraNearestTarget(curr, isTarget, visitedTarget);\n            if (target == -1) break; // should not happen (connected component)\n\n            // Reconstruct path curr -> target using prevv from dijkstraNearestTarget\n            vector<int> tmp;\n            int x = target;\n            while (x != curr && x != -1) {\n                tmp.push_back(x);\n                x = prevv[x];\n            }\n            for (int i = (int)tmp.size() - 1; i >= 0; --i) {\n                int node = tmp[i];\n                route.push_back(node);\n                if (isTarget[node] && !visitedTarget[node]) {\n                    visitedTarget[node] = 1;\n                    --remainingTargets;\n                }\n            }\n            curr = target;\n        }\n\n        // Return to start\n        if (curr != startId) {\n            appendPath(route, curr, startId);\n        }\n        return route;\n    };\n\n    vector<int> routeNN = buildRouteGreedyNN(vantageCells);\n    long long timeNN = computeTravelTime(routeNN, cost);\n\n    // ---------- Route 2: TSP over vantages ----------\n    vector<int> routeTSP;\n    long long timeTSP = (1LL << 60);\n\n    if (!vantageCells.empty()) {\n        // Build node list: start + all vantages (without duplicating start)\n        vector<int> nodes;\n        nodes.reserve(vantageCells.size() + 1);\n        nodes.push_back(startId);\n        for (int v : vantageCells) {\n            if (v != startId) nodes.push_back(v);\n        }\n        int K = (int)nodes.size();\n\n        // Distance matrix between nodes (either true shortest-path or Manhattan)\n        vector<vector<int>> distNode(K, vector<int>(K, 0));\n        const int MAX_TSP_REAL_DIST_NODES = 600;\n        bool useRealDist = (K <= MAX_TSP_REAL_DIST_NODES);\n\n        if (useRealDist) {\n            // Map cell id -> node index\n            vector<int> nodeIndex(r, -1);\n            for (int i = 0; i < K; ++i) nodeIndex[nodes[i]] = i;\n\n            // Dijkstra from each node to compute distances to all others\n            for (int i = 0; i < K; ++i) {\n                int src = nodes[i];\n                fill(dist.begin(), dist.end(), INF);\n                dist[src] = 0;\n                priority_queue<pair<int,int>, vector<pair<int,int>>, greater<pair<int,int>>> pq;\n                pq.push({0, src});\n                int remaining = K;\n                while (!pq.empty() && remaining > 0) {\n                    auto [d, u] = pq.top();\n                    pq.pop();\n                    if (d != dist[u]) continue;\n                    int idxU = nodeIndex[u];\n                    if (idxU != -1) {\n                        distNode[i][idxU] = d;\n                        --remaining;\n                    }\n                    for (auto &e : G[u]) {\n                        int v = e.to;\n                        int nd = d + e.w;\n                        if (nd < dist[v]) {\n                            dist[v] = nd;\n                            pq.push({nd, v});\n                        }\n                    }\n                }\n            }\n        } else {\n            // Approximate distances by Manhattan\n            for (int i = 0; i < K; ++i) {\n                auto [xi, yi] = pos[nodes[i]];\n                for (int j = i + 1; j < K; ++j) {\n                    auto [xj, yj] = pos[nodes[j]];\n                    int d = abs(xi - xj) + abs(yi - yj);\n                    distNode[i][j] = distNode[j][i] = d;\n                }\n            }\n        }\n\n        if (K >= 2) {\n            // Initial route: nearest neighbor on distNode\n            vector<int> order(K);\n            vector<char> used(K, 0);\n            order[0] = 0;\n            used[0] = 1;\n            for (int t = 1; t < K; ++t) {\n                int prevIdx = order[t - 1];\n                int best = -1;\n                int bestD = INT_MAX;\n                for (int j = 0; j < K; ++j) {\n                    if (used[j]) continue;\n                    int d = distNode[prevIdx][j];\n                    if (d < bestD) {\n                        bestD = d;\n                        best = j;\n                    }\n                }\n                if (best == -1) best = 0; // safety\n                order[t] = best;\n                used[best] = 1;\n            }\n\n            // 2-opt improvement\n            bool improved = true;\n            while (improved) {\n                improved = false;\n                for (int i = 1; i < K - 1 && !improved; ++i) {\n                    int a = order[i - 1];\n                    int b = order[i];\n                    for (int j = i + 1; j < K; ++j) {\n                        int c = order[j];\n                        int d = (j + 1 < K ? order[j + 1] : order[0]);\n                        int curCost = distNode[a][b] + distNode[c][d];\n                        int newCost = distNode[a][c] + distNode[b][d];\n                        if (newCost < curCost) {\n                            reverse(order.begin() + i, order.begin() + j + 1);\n                            improved = true;\n                            break;\n                        }\n                    }\n                }\n            }\n\n            // Or-opt improvement (move one vertex) for moderate sizes\n            if (K <= 400) {\n                int maxIter = 4;\n                for (int iter = 0; iter < maxIter; ++iter) {\n                    bool anyImproved = false;\n                    for (int i = 1; i < K; ++i) {\n                        int prev = order[i - 1];\n                        int cur = order[i];\n                        int next = (i == K - 1 ? order[0] : order[i + 1]);\n                        for (int j = 0; j < K; ++j) {\n                            if (j == i || j == i - 1) continue;\n                            int a = order[j];\n                            int b = (j == K - 1 ? order[0] : order[j + 1]);\n                            if (a == cur || b == cur) continue;\n\n                            int delta = 0;\n                            // Remove cur from between prev and next\n                            delta -= distNode[prev][cur] + distNode[cur][next] - distNode[prev][next];\n                            // Insert cur between a and b\n                            delta += distNode[a][cur] + distNode[cur][b] - distNode[a][b];\n\n                            if (delta < 0) {\n                                int node = cur;\n                                if (j < i) {\n                                    // remove at i\n                                    for (int k = i; k < K - 1; ++k) order[k] = order[k + 1];\n                                    // insert after j (position j+1)\n                                    for (int k = K - 1; k > j + 1; --k) order[k] = order[k - 1];\n                                    order[j + 1] = node;\n                                } else { // j > i\n                                    // remove at i\n                                    for (int k = i; k < K - 1; ++k) order[k] = order[k + 1];\n                                    // after removal, original index j becomes j-1\n                                    int newJ = j - 1;\n                                    for (int k = K - 1; k > newJ + 1; --k) order[k] = order[k - 1];\n                                    order[newJ + 1] = node;\n                                }\n                                anyImproved = true;\n                                goto NEXT_OR_ITER;\n                            }\n                        }\n                    }\n                NEXT_OR_ITER:\n                    if (!anyImproved) break;\n                }\n\n                // Final small 2-opt pass\n                improved = true;\n                while (improved) {\n                    improved = false;\n                    for (int i = 1; i < K - 1 && !improved; ++i) {\n                        int a = order[i - 1];\n                        int b = order[i];\n                        for (int j = i + 1; j < K; ++j) {\n                            int c = order[j];\n                            int d = (j + 1 < K ? order[j + 1] : order[0]);\n                            int curCost = distNode[a][b] + distNode[c][d];\n                            int newCost = distNode[a][c] + distNode[b][d];\n                            if (newCost < curCost) {\n                                reverse(order.begin() + i, order.begin() + j + 1);\n                                improved = true;\n                                break;\n                            }\n                        }\n                    }\n                }\n            }\n\n            // Build actual route following this order (0..K-1), starting at startId\n            routeTSP.reserve(2 * r + 5);\n            routeTSP.push_back(startId);\n            int curr = startId;\n            for (int idxPos = 1; idxPos < K; ++idxPos) {\n                int nodeIdx = order[idxPos];\n                int dest = nodes[nodeIdx];\n                if (dest == curr) continue;\n                appendPath(routeTSP, curr, dest);\n                curr = dest;\n            }\n            if (curr != startId) {\n                appendPath(routeTSP, curr, startId);\n            }\n            timeTSP = computeTravelTime(routeTSP, cost);\n        }\n    }\n\n    // ---------- Choose the best route among: DFS fallback, NN, TSP ----------\n    vector<int> bestRoute = fallbackRoute;\n    long long bestTime = fallbackTime;\n\n    if (!routeNN.empty() && timeNN < bestTime) {\n        bestTime = timeNN;\n        bestRoute = std::move(routeNN);\n    }\n    if (!routeTSP.empty() && timeTSP < bestTime) {\n        bestTime = timeTSP;\n        bestRoute = std::move(routeTSP);\n    }\n\n    // If route has no movement, add a tiny loop to avoid t=0\n    if ((int)bestRoute.size() == 1) {\n        int u = startId;\n        int v = -1;\n        for (auto &e : G[u]) {\n            v = e.to;\n            break;\n        }\n        if (v != -1) {\n            bestRoute.push_back(v);\n            bestRoute.push_back(u);\n        }\n    }\n\n    // ---------- Convert node sequence to direction string ----------\n    string ans;\n    ans.reserve(bestRoute.size());\n    for (int i = 1; i < (int)bestRoute.size(); ++i) {\n        auto [i1, j1] = pos[bestRoute[i-1]];\n        auto [i2, j2] = pos[bestRoute[i]];\n        if (i2 == i1 - 1 && j2 == j1) ans.push_back('U');\n        else if (i2 == i1 + 1 && j2 == j1) ans.push_back('D');\n        else if (j2 == j1 - 1 && i2 == i1) ans.push_back('L');\n        else if (j2 == j1 + 1 && i2 == i1) ans.push_back('R');\n        else {\n            // Should not happen with valid shortest paths\n        }\n    }\n\n    cout << ans << '\\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    if (!(cin >> N >> M >> K >> R)) return 0;\n\n    // Task requirements d[i][k]\n    vector<vector<int>> d(N, vector<int>(K));\n    for (int i = 0; i < N; ++i) {\n        for (int k = 0; k < K; ++k) cin >> d[i][k];\n    }\n\n    // Dependencies: u -> v\n    vector<vector<int>> out(N);\n    vector<int> indeg(N, 0);\n    for (int e = 0; e < R; ++e) {\n        int u, v;\n        cin >> u >> v;\n        --u; --v;\n        out[u].push_back(v);\n        indeg[v]++;\n    }\n\n    // Precompute depth-from-end (longest path length to any sink)\n    vector<int> depth(N, 0);\n    for (int i = N - 1; i >= 0; --i) {\n        int best = 0;\n        for (int v : out[i]) {\n            best = max(best, depth[v] + 1);\n        }\n        depth[i] = best;\n    }\n\n    // Precompute simple difficulty measure (L1 norm)\n    vector<int> diffL1(N, 0);\n    for (int i = 0; i < N; ++i) {\n        int s = 0;\n        for (int k = 0; k < K; ++k) s += d[i][k];\n        diffL1[i] = s;\n    }\n\n    // Task states\n    const int NOT_STARTED = 0;\n    const int IN_PROGRESS = 1;\n    const int DONE = 2;\n    vector<int> state(N, NOT_STARTED);\n    vector<int> degRem = indeg;\n    int tasksDone = 0;\n\n    // Worker states\n    vector<int> curTask(M, -1);\n    vector<int> startDay(M, -1);\n\n    // Worker skill vectors s_j[k]\n    vector<vector<double>> skill(M, vector<double>(K, 0.0));\n    // History of (task, w_obs) per worker for fitting\n    vector<vector<int>> histTasks(M);\n    vector<vector<double>> histW(M);\n\n    const int    FIT_ITERS = 5;\n    const double LR        = 0.05;\n    const double SKILL_MAX = 100.0;\n\n    // Fitting function for one worker (small batch GD over its history)\n    auto fitWorker = [&](int j) {\n        auto &s  = skill[j];\n        auto &ht = histTasks[j];\n        auto &hw = histW[j];\n        int S = (int)ht.size();\n        if (S == 0) return;\n        for (int it = 0; it < FIT_ITERS; ++it) {\n            for (int idx = 0; idx < S; ++idx) {\n                int ti = ht[idx];\n                double w_obs = hw[idx];\n\n                // Compute w_pred = sum_k max(0, d[ti][k] - s[k])\n                const auto &dv = d[ti];\n                double w_pred = 0.0;\n                for (int k = 0; k < K; ++k) {\n                    double diff = (double)dv[k] - s[k];\n                    if (diff > 0.0) w_pred += diff;\n                }\n\n                double e = w_pred - w_obs;\n                if (e == 0.0) continue;\n                double step = LR * e;\n\n                // Gradient: for dims where d > s, s[k] += step\n                for (int k = 0; k < K; ++k) {\n                    if ((double)dv[k] > s[k]) {\n                        s[k] += step;\n                        if (s[k] < 0.0) s[k] = 0.0;\n                        if (s[k] > SKILL_MAX) s[k] = SKILL_MAX;\n                    }\n                }\n            }\n        }\n    };\n\n    int day = 0;\n    const int MAX_CAND = 400;  // number of candidate tasks per day to consider\n\n    while (true) {\n        day++;\n\n        // Compute available tasks (not started and all prerequisites done)\n        vector<int> available;\n        if (tasksDone < N) {\n            available.reserve(N);\n            for (int i = 0; i < N; ++i) {\n                if (state[i] == NOT_STARTED && degRem[i] == 0) {\n                    available.push_back(i);\n                }\n            }\n        }\n\n        // Collect free workers\n        vector<int> freeWorkers;\n        freeWorkers.reserve(M);\n        for (int j = 0; j < M; ++j) {\n            if (curTask[j] == -1) freeWorkers.push_back(j);\n        }\n\n        vector<pair<int,int>> assigns; // (worker, task)\n\n        if (!freeWorkers.empty() && !available.empty()) {\n            // Sort available tasks by priority: depth desc, diffL1 desc, id asc\n            auto cmpTask = [&](int x, int y) {\n                if (depth[x] != depth[y]) return depth[x] > depth[y];\n                if (diffL1[x] != diffL1[y]) return diffL1[x] > diffL1[y];\n                return x < y;\n            };\n\n            int sz = (int)available.size();\n            if (sz > MAX_CAND) {\n                int limit = MAX_CAND;\n                partial_sort(available.begin(), available.begin() + limit,\n                             available.end(), cmpTask);\n                available.resize(limit);\n                sz = limit;\n            } else {\n                sort(available.begin(), available.end(), cmpTask);\n            }\n\n            // Build all (worker, task) options with predicted cost = t_pred\n            struct Option {\n                double cost;\n                int w;\n                int task;\n            };\n            vector<Option> options;\n            options.reserve(freeWorkers.size() * sz);\n\n            for (int widx = 0; widx < (int)freeWorkers.size(); ++widx) {\n                int j = freeWorkers[widx];\n                const auto &sj = skill[j];\n                for (int tidx = 0; tidx < sz; ++tidx) {\n                    int ti = available[tidx];\n                    const auto &dv = d[ti];\n                    double w_pred = 0.0;\n                    for (int k = 0; k < K; ++k) {\n                        double diff = (double)dv[k] - sj[k];\n                        if (diff > 0.0) w_pred += diff;\n                    }\n                    if (w_pred < 0.0) w_pred = 0.0;\n                    double t_pred = (w_pred < 1.0 ? 1.0 : w_pred);\n                    options.push_back(Option{t_pred, j, ti});\n                }\n            }\n\n            sort(options.begin(), options.end(),\n                 [](const Option &a, const Option &b) {\n                     if (a.cost != b.cost) return a.cost < b.cost;\n                     if (a.w != b.w) return a.w < b.w;\n                     return a.task < b.task;\n                 });\n\n            vector<char> workerUsed(M, 0);\n            vector<char> taskUsed(N, 0);\n            assigns.reserve(freeWorkers.size());\n\n            for (const auto &opt : options) {\n                if ((int)assigns.size() == (int)freeWorkers.size()) break;\n                int j  = opt.w;\n                int ti = opt.task;\n                if (workerUsed[j] || taskUsed[ti]) continue;\n                workerUsed[j] = 1;\n                taskUsed[ti]  = 1;\n                assigns.emplace_back(j, ti);\n            }\n        }\n\n        // Output assignments and update worker/task states\n        int m = (int)assigns.size();\n        cout << m;\n        for (auto &p : assigns) {\n            int j  = p.first;\n            int ti = p.second;\n            cout << ' ' << (j + 1) << ' ' << (ti + 1);\n            curTask[j] = ti;\n            startDay[j] = day;\n            state[ti] = IN_PROGRESS;\n        }\n        cout << '\\n' << flush;\n\n        // Read feedback: list of finished workers\n        int n;\n        if (!(cin >> n)) return 0;\n        if (n == -1) break;\n\n        vector<int> finishedWorkers;\n        finishedWorkers.reserve(n);\n        for (int i = 0; i < n; ++i) {\n            int f;\n            cin >> f;\n            finishedWorkers.push_back(f - 1); // zero-based\n        }\n\n        // Process completions\n        for (int idx = 0; idx < n; ++idx) {\n            int j = finishedWorkers[idx];\n            int ti = (j >= 0 && j < M) ? curTask[j] : -1;\n            if (ti < 0) continue;\n\n            int st = startDay[j];\n            if (st < 1) st = day;  // safety\n            int t_obs = day - st + 1;\n            if (t_obs < 1) t_obs = 1;\n            int w_obs_int = t_obs - 1;\n            if (w_obs_int < 0) w_obs_int = 0;\n            double w_obs = (double)w_obs_int;\n\n            // Record sample for worker j\n            histTasks[j].push_back(ti);\n            histW[j].push_back(w_obs);\n            // Re-fit worker j's skill vector\n            fitWorker(j);\n\n            // Mark task completion\n            state[ti] = DONE;\n            tasksDone++;\n            curTask[j] = -1;\n            startDay[j] = -1;\n\n            // Update indegrees of children\n            for (int v : out[ti]) {\n                degRem[v]--;\n            }\n        }\n    }\n\n    return 0;\n}","ahc006":"#include <bits/stdc++.h>\nusing namespace std;\n\n// ---------------------------------------------------------------\n// Types and globals\n// ---------------------------------------------------------------\n\nstruct TourResult {\n    vector<int> tour; // sequence of node indices, starts and ends with 0 (office)\n    int cost;\n};\n\nstatic int distMat[52][52];   // for TSP up to 51 nodes (0..50)\nstatic int nodeX[52], nodeY[52];\n\nconst int OFFICE_X = 400;\nconst int OFFICE_Y = 400;\n\n// RNG: simple xorshift\nstruct XorShift {\n    uint64_t x;\n    XorShift(uint64_t seed = 88172645463393265ULL) { x = seed; }\n    uint64_t next_u64() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return x;\n    }\n    uint32_t next_u32() { return (uint32_t)next_u64(); }\n    uint32_t next_uint(uint32_t mod) { return (uint32_t)(next_u64() % mod); }\n    double next_double() {\n        return (next_u64() >> 11) * (1.0 / (1ULL << 53));\n    }\n};\n\n// Manhattan distance\ninline int manhattan(int x1, int y1, int x2, int y2) {\n    return abs(x1 - x2) + abs(y1 - y2);\n}\n\n// ---------------------------------------------------------------\n// TSP solver: nearest neighbor + 2-opt\n// Points: X[i], Y[i] for i=0..m-1 correspond to nodes 1..m.\n// Node 0 is the office at (400,400).\n// ---------------------------------------------------------------\nTourResult solve_tsp_points(const vector<int>& X, const vector<int>& Y) {\n    int m = (int)X.size();       // number of non-office nodes (<=50)\n    int nNodes = m + 1;          // nodes 0..m\n\n    // Build node coordinates (0: office)\n    nodeX[0] = OFFICE_X;\n    nodeY[0] = OFFICE_Y;\n    for (int i = 1; i <= m; ++i) {\n        nodeX[i] = X[i - 1];\n        nodeY[i] = Y[i - 1];\n    }\n\n    // Distance matrix\n    for (int i = 0; i <= m; ++i) {\n        for (int j = 0; j <= m; ++j) {\n            distMat[i][j] = manhattan(nodeX[i], nodeY[i], nodeX[j], nodeY[j]);\n        }\n    }\n\n    // Nearest neighbor construction, start at office (0)\n    vector<int> tour;\n    tour.reserve(nNodes + 1);\n    vector<char> used(nNodes, 0);\n    int cur = 0;\n    used[0] = 1;\n    tour.push_back(0);\n    for (int step = 0; step < m; ++step) {\n        int best = -1;\n        int bestDist = INT_MAX;\n        for (int v = 1; v <= m; ++v) {\n            if (!used[v]) {\n                int d = distMat[cur][v];\n                if (d < bestDist) {\n                    bestDist = d;\n                    best = v;\n                }\n            }\n        }\n        used[best] = 1;\n        tour.push_back(best);\n        cur = best;\n    }\n    tour.push_back(0); // return to office\n\n    // 2-opt improvement with fixed endpoints at office\n    int M = (int)tour.size(); // should be m+2\n    bool improved = true;\n    while (improved) {\n        improved = false;\n        for (int i = 1; i <= M - 3; ++i) {\n            int a = tour[i - 1];\n            int b = tour[i];\n            for (int k = i + 1; k <= M - 2; ++k) {\n                int c = tour[k];\n                int d = tour[k + 1];\n                int delta = distMat[a][c] + distMat[b][d]\n                          - distMat[a][b] - distMat[c][d];\n                if (delta < 0) {\n                    reverse(tour.begin() + i, tour.begin() + k + 1);\n                    improved = true;\n                    goto next_iteration;\n                }\n            }\n        }\n        next_iteration:;\n    }\n\n    int cost = 0;\n    for (int i = 0; i < M - 1; ++i) {\n        cost += distMat[tour[i]][tour[i + 1]];\n    }\n\n    TourResult res;\n    res.tour = move(tour);\n    res.cost = cost;\n    return res;\n}\n\n// ---------------------------------------------------------------\n// Evaluate a selection of orders:\n//   selection: vector of indices (0-based) of orders.\n//   Returns total cost of 0->restaurants->0 + 0->destinations->0,\n//   and stores the restaurant and destination tours.\n// ---------------------------------------------------------------\nint evaluate_selection(\n    const vector<int>& selection,\n    const vector<int>& a, const vector<int>& b,\n    const vector<int>& c, const vector<int>& d,\n    vector<int>& outRtour,\n    vector<int>& outDtour\n) {\n    int m = (int)selection.size(); // 50\n    vector<int> XR(m), YR(m), XD(m), YD(m);\n    for (int i = 0; i < m; ++i) {\n        int idx = selection[i];\n        XR[i] = a[idx];\n        YR[i] = b[idx];\n        XD[i] = c[idx];\n        YD[i] = d[idx];\n    }\n\n    TourResult rRes = solve_tsp_points(XR, YR);\n    TourResult dRes = solve_tsp_points(XD, YD);\n\n    outRtour = rRes.tour;\n    outDtour = dRes.tour;\n\n    return rRes.cost + dRes.cost;\n}\n\n// ---------------------------------------------------------------\n// Compute cost of a pickup-delivery route:\n// kind[pos]: 0=pickup, 1=delivery, 2=office (for pos=0 and last)\n// oid[pos]: local order id (0..M-1) if kind is 0 or 1\n// ---------------------------------------------------------------\nint compute_route_cost(\n    int M,\n    const vector<int>& kind,\n    const vector<int>& oid,\n    const vector<int>& rx,\n    const vector<int>& ry,\n    const vector<int>& dx,\n    const vector<int>& dy\n) {\n    int routeSize = 2 * M + 2; // positions 0..routeSize-1\n    auto getCoord = [&](int pos, int &x, int &y) {\n        if (pos == 0 || pos == routeSize - 1) {\n            x = OFFICE_X; y = OFFICE_Y;\n        } else if (kind[pos] == 0) { // pickup -> restaurant\n            int id = oid[pos];\n            x = rx[id]; y = ry[id];\n        } else { // delivery\n            int id = oid[pos];\n            x = dx[id]; y = dy[id];\n        }\n    };\n\n    int total = 0;\n    int px, py;\n    getCoord(0, px, py);\n    for (int pos = 1; pos < routeSize; ++pos) {\n        int cx, cy;\n        getCoord(pos, cx, cy);\n        total += manhattan(px, py, cx, cy);\n        px = cx; py = cy;\n    }\n    return total;\n}\n\n// ---------------------------------------------------------------\n// Main\n// ---------------------------------------------------------------\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    const int N = 1000;\n    vector<int> a(N), b(N), c(N), d(N);\n    for (int i = 0; i < N; ++i) {\n        if (!(cin >> a[i] >> b[i] >> c[i] >> d[i])) {\n            return 0;\n        }\n    }\n\n    auto globalStart = chrono::steady_clock::now();\n    const double TOTAL_LIMIT = 1.90;      // total time limit for safety\n    const double SELECTION_LIMIT = 1.75;  // time for selection phase\n\n    XorShift rng(\n        (uint64_t)chrono::high_resolution_clock::now()\n            .time_since_epoch().count()\n    );\n\n    // -----------------------------------------------------------\n    // Initial selection by single-trip heuristic\n    // -----------------------------------------------------------\n    vector<int> single_trip(N);\n    for (int i = 0; i < N; ++i) {\n        int d0R = manhattan(OFFICE_X, OFFICE_Y, a[i], b[i]);\n        int dRD = manhattan(a[i], b[i], c[i], d[i]);\n        int dD0 = manhattan(c[i], d[i], OFFICE_X, OFFICE_Y);\n        single_trip[i] = d0R + dRD + dD0;\n    }\n\n    vector<int> idx(N);\n    iota(idx.begin(), idx.end(), 0);\n    sort(idx.begin(), idx.end(), [&](int i, int j) {\n        return single_trip[i] < single_trip[j];\n    });\n\n    const int M = 50;\n    vector<int> currentSel(M);\n    for (int i = 0; i < M; ++i) currentSel[i] = idx[i];\n\n    vector<char> inCurrent(N, 0);\n    for (int i = 0; i < M; ++i) inCurrent[currentSel[i]] = 1;\n\n    // Evaluate initial selection\n    vector<int> bestRtour, bestDtour;\n    vector<int> tmpRtour, tmpDtour;\n    int currentCost = evaluate_selection(currentSel, a, b, c, d, tmpRtour, tmpDtour);\n\n    vector<int> bestSel = currentSel;\n    bestRtour = tmpRtour;\n    bestDtour = tmpDtour;\n    int bestCost = currentCost;\n\n    // -----------------------------------------------------------\n    // Hill-climbing on selection (same idea as first version)\n    // -----------------------------------------------------------\n    while (true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - globalStart).count();\n        if (elapsed > SELECTION_LIMIT) break;\n\n        // Pick a random order to remove\n        int posOut = (int)rng.next_uint(M);\n        int outIdx = currentSel[posOut];\n\n        // Pick a random order to insert (not currently selected)\n        int inIdx;\n        do {\n            inIdx = (int)rng.next_uint(N);\n        } while (inCurrent[inIdx]);\n\n        vector<int> candidateSel = currentSel;\n        candidateSel[posOut] = inIdx;\n\n        int candCost = evaluate_selection(candidateSel, a, b, c, d, tmpRtour, tmpDtour);\n\n        // Greedy acceptance\n        if (candCost <= currentCost) {\n            currentSel.swap(candidateSel);\n            currentCost = candCost;\n            inCurrent[outIdx] = 0;\n            inCurrent[inIdx] = 1;\n        }\n\n        // Track global best\n        if (candCost < bestCost) {\n            bestCost = candCost;\n            bestSel = candidateSel;\n            bestRtour = tmpRtour;\n            bestDtour = tmpDtour;\n        }\n    }\n\n    // -----------------------------------------------------------\n    // Build local data for best selection\n    // -----------------------------------------------------------\n    vector<int> globalOfLocal(M);\n    for (int i = 0; i < M; ++i) {\n        globalOfLocal[i] = bestSel[i]; // map local id -> global order index\n    }\n\n    vector<int> rx(M), ry(M), dx(M), dy(M);\n    for (int i = 0; i < M; ++i) {\n        int gi = globalOfLocal[i];\n        rx[i] = a[gi];\n        ry[i] = b[gi];\n        dx[i] = c[gi];\n        dy[i] = d[gi];\n    }\n\n    // Extract sequences of local order ids from TSP tours\n    vector<int> seqP; seqP.reserve(M);\n    vector<int> seqD; seqD.reserve(M);\n\n    // Restaurants tour: [0, r1, ..., rM, 0]\n    for (int i = 1; i < (int)bestRtour.size() - 1; ++i) {\n        int node = bestRtour[i]; // 1..M\n        int local = node - 1;\n        seqP.push_back(local);\n    }\n    // Destinations tour: [0, d1, ..., dM, 0]\n    for (int i = 1; i < (int)bestDtour.size() - 1; ++i) {\n        int node = bestDtour[i];\n        int local = node - 1;\n        seqD.push_back(local);\n    }\n\n    if ((int)seqP.size() != M || (int)seqD.size() != M) {\n        // Fallback: trivial order 0..M-1 (should not normally happen)\n        seqP.clear(); seqD.clear();\n        for (int i = 0; i < M; ++i) {\n            seqP.push_back(i);\n            seqD.push_back(i);\n        }\n    }\n\n    // -----------------------------------------------------------\n    // Build baseline pickup-delivery route: 0, P..., D..., 0\n    // -----------------------------------------------------------\n    int routeSize = 2 * M + 2; // positions 0..routeSize-1\n    vector<int> kind(routeSize), oid(routeSize); // kind: 0=pickup,1=delivery,2=office\n    vector<int> posP(M), posD(M);\n\n    kind[0] = kind[routeSize - 1] = 2;\n    oid[0] = oid[routeSize - 1] = -1;\n\n    // pickups\n    for (int k = 0; k < M; ++k) {\n        int pos = 1 + k;\n        int local = seqP[k];\n        kind[pos] = 0;\n        oid[pos] = local;\n        posP[local] = pos;\n    }\n    // deliveries\n    for (int k = 0; k < M; ++k) {\n        int pos = 1 + M + k;\n        int local = seqD[k];\n        kind[pos] = 1;\n        oid[pos] = local;\n        posD[local] = pos;\n    }\n\n    // Baseline route cost: 0 -> all pickups -> all deliveries -> 0\n    int baselineCost = compute_route_cost(M, kind, oid, rx, ry, dx, dy);\n    vector<int> baselineKind = kind;\n    vector<int> baselineOid = oid;\n\n    // -----------------------------------------------------------\n    // Simulated Annealing on pickup-delivery sequence\n    // -----------------------------------------------------------\n    int currentRouteCost = baselineCost;\n    int bestRouteCost = baselineCost;\n    vector<int> bestKind = kind;\n    vector<int> bestOid = oid;\n\n    auto saStart = chrono::steady_clock::now();\n    double elapsed = chrono::duration<double>(saStart - globalStart).count();\n    double remaining = TOTAL_LIMIT - elapsed;\n\n    if (remaining > 0.05) {\n        const int MAX_ITER = 300000;\n        const int CHECK_INTERVAL = 2048;\n        const double T0 = 2000.0;\n        const double T1 = 5.0;\n\n        for (int it = 0; it < MAX_ITER; ++it) {\n            if ((it & (CHECK_INTERVAL - 1)) == 0) {\n                auto now = chrono::steady_clock::now();\n                double e = chrono::duration<double>(now - globalStart).count();\n                if (e > TOTAL_LIMIT) break;\n            }\n\n            int x = 1 + (int)rng.next_uint(2 * M); // 1..2M\n            int y = 1 + (int)rng.next_uint(2 * M);\n            if (x == y) continue;\n            if (x > y) swap(x, y);\n\n            int kx = kind[x];\n            int ky = kind[y];\n            int oid1 = oid[x];\n            int oid2 = oid[y];\n\n            // never touch offices\n            if (kx == 2 || ky == 2) continue;\n\n            // don't swap pickup and delivery of the same order\n            if (oid1 == oid2) continue;\n\n            // Precedence check\n            bool ok = true;\n            // Order 1\n            int p1 = posP[oid1];\n            int d1 = posD[oid1];\n            if (kx == 0) { // pickup moves to y\n                if (y >= d1) ok = false;\n            } else { // delivery moves to y\n                if (p1 >= y) ok = false;\n            }\n            if (!ok) continue;\n\n            // Order 2\n            int p2 = posP[oid2];\n            int d2 = posD[oid2];\n            if (ky == 0) { // pickup moves to x\n                if (x >= d2) ok = false;\n            } else { // delivery moves to x\n                if (p2 >= x) ok = false;\n            }\n            if (!ok) continue;\n\n            // Temperature schedule\n            double t = (double)it / MAX_ITER;\n            if (t > 1.0) t = 1.0;\n            double T = T0 + (T1 - T0) * t;\n\n            // Helper to get coordinates at a given position (before swap)\n            auto getCoordPos = [&](int pos, int &X, int &Y) {\n                if (pos == 0 || pos == routeSize - 1) {\n                    X = OFFICE_X; Y = OFFICE_Y;\n                } else if (kind[pos] == 0) {\n                    int id = oid[pos];\n                    X = rx[id]; Y = ry[id];\n                } else { // delivery\n                    int id = oid[pos];\n                    X = dx[id]; Y = dy[id];\n                }\n            };\n\n            int deltaCost = 0;\n            if (y == x + 1) {\n                // Adjacent swap: positions x and y=x+1\n                int Ax, Ay, Bx, By, Cx, Cy, Dx_, Dy_;\n                int xPrev = x - 1;\n                int yNext = y + 1;\n\n                getCoordPos(xPrev, Ax, Ay);\n                getCoordPos(x, Bx, By);   // event1\n                getCoordPos(y, Cx, Cy);   // event2\n                getCoordPos(yNext, Dx_, Dy_);\n\n                int before = manhattan(Ax, Ay, Bx, By)\n                           + manhattan(Bx, By, Cx, Cy)\n                           + manhattan(Cx, Cy, Dx_, Dy_);\n\n                int B2x, B2y, C2x, C2y;\n                // New B (at x) is event2\n                if (ky == 0) {\n                    int id = oid2;\n                    B2x = rx[id]; B2y = ry[id];\n                } else {\n                    int id = oid2;\n                    B2x = dx[id]; B2y = dy[id];\n                }\n                // New C (at y) is event1\n                if (kx == 0) {\n                    int id = oid1;\n                    C2x = rx[id]; C2y = ry[id];\n                } else {\n                    int id = oid1;\n                    C2x = dx[id]; C2y = dy[id];\n                }\n\n                int after = manhattan(Ax, Ay, B2x, B2y)\n                          + manhattan(B2x, B2y, C2x, C2y)\n                          + manhattan(C2x, C2y, Dx_, Dy_);\n\n                deltaCost = after - before;\n            } else {\n                // Non-adjacent swap\n                int xPrev = x - 1;\n                int xNext = x + 1;\n                int yPrev = y - 1;\n                int yNext = y + 1;\n\n                int Ax, Ay, Bx, By, Cx, Cy;\n                int Dx_, Dy_, Ex, Ey, Fx, Fy;\n\n                getCoordPos(xPrev, Ax, Ay);\n                getCoordPos(x, Bx, By);\n                getCoordPos(xNext, Cx, Cy);\n\n                getCoordPos(yPrev, Dx_, Dy_);\n                getCoordPos(y, Ex, Ey);\n                getCoordPos(yNext, Fx, Fy);\n\n                int before = manhattan(Ax, Ay, Bx, By)\n                           + manhattan(Bx, By, Cx, Cy)\n                           + manhattan(Dx_, Dy_, Ex, Ey)\n                           + manhattan(Ex, Ey, Fx, Fy);\n\n                int B2x, B2y, E2x, E2y;\n                // New node at x (B2) is event2\n                if (ky == 0) {\n                    int id = oid2;\n                    B2x = rx[id]; B2y = ry[id];\n                } else {\n                    int id = oid2;\n                    B2x = dx[id]; B2y = dy[id];\n                }\n                // New node at y (E2) is event1\n                if (kx == 0) {\n                    int id = oid1;\n                    E2x = rx[id]; E2y = ry[id];\n                } else {\n                    int id = oid1;\n                    E2x = dx[id]; E2y = dy[id];\n                }\n\n                int after = manhattan(Ax, Ay, B2x, B2y)\n                          + manhattan(B2x, B2y, Cx, Cy)\n                          + manhattan(Dx_, Dy_, E2x, E2y)\n                          + manhattan(E2x, E2y, Fx, Fy);\n\n                deltaCost = after - before;\n            }\n\n            if (deltaCost <= 0) {\n                // Always accept improvements\n            } else {\n                double prob = exp(- (double)deltaCost / T);\n                if (rng.next_double() >= prob) {\n                    continue; // reject\n                }\n            }\n\n            // Accept move\n            currentRouteCost += deltaCost;\n\n            // Update positions and route\n            swap(kind[x], kind[y]);\n            swap(oid[x], oid[y]);\n\n            // Update posP/posD for affected orders using old kinds (kx, ky)\n            if (kx == 0) posP[oid1] = y; else posD[oid1] = y;\n            if (ky == 0) posP[oid2] = x; else posD[oid2] = x;\n\n            if (currentRouteCost < bestRouteCost) {\n                bestRouteCost = currentRouteCost;\n                bestKind = kind;\n                bestOid = oid;\n            }\n        }\n    }\n\n    // Recompute exact costs and choose the better of baseline vs SA\n    int saCost = compute_route_cost(M, bestKind, bestOid, rx, ry, dx, dy);\n    vector<int> finalKind, finalOid;\n    int finalCost;\n    if (saCost < baselineCost) {\n        finalKind = bestKind;\n        finalOid = bestOid;\n        finalCost = saCost;\n    } else {\n        finalKind = baselineKind;\n        finalOid = baselineOid;\n        finalCost = baselineCost;\n    }\n    (void)finalCost; // not used further, but kept for clarity\n\n    // -----------------------------------------------------------\n    // Build final path coordinates from final route (kind, oid)\n    // -----------------------------------------------------------\n    vector<pair<int,int>> path;\n    path.reserve(routeSize);\n    for (int pos = 0; pos < routeSize; ++pos) {\n        if (pos == 0 || pos == routeSize - 1) {\n            path.emplace_back(OFFICE_X, OFFICE_Y);\n        } else if (finalKind[pos] == 0) {\n            int local = finalOid[pos];\n            int gi = globalOfLocal[local];\n            path.emplace_back(a[gi], b[gi]);\n        } else {\n            int local = finalOid[pos];\n            int gi = globalOfLocal[local];\n            path.emplace_back(c[gi], d[gi]);\n        }\n    }\n\n    // -----------------------------------------------------------\n    // Output\n    // -----------------------------------------------------------\n    // First line: m and chosen order indices (1-based)\n    cout << M;\n    for (int i = 0; i < M; ++i) {\n        cout << ' ' << (bestSel[i] + 1);\n    }\n    cout << '\\n';\n\n    // Second line: n and route coordinates\n    int n = (int)path.size();\n    cout << n;\n    for (int i = 0; i < n; ++i) {\n        cout << ' ' << path[i].first << ' ' << path[i].second;\n    }\n    cout << '\\n';\n\n    return 0;\n}","ahc007":"#include <bits/stdc++.h>\nusing namespace std;\n\n// ---------- DSU (Union-Find) ----------\nstruct DSU {\n    int n;\n    vector<int> p, r;\n    DSU() {}\n    DSU(int n_) { init(n_); }\n    void init(int n_) {\n        n = n_;\n        p.resize(n);\n        r.assign(n, 0);\n        iota(p.begin(), p.end(), 0);\n    }\n    int find(int x) {\n        if (p[x] == x) return x;\n        return p[x] = find(p[x]);\n    }\n    bool same(int a, int b) {\n        return find(a) == find(b);\n    }\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\n// ---------- XorShift RNG ----------\nstruct XorShift {\n    uint32_t x = 123456789u;\n    uint32_t y = 362436069u;\n    uint32_t z = 521288629u;\n    uint32_t w = 88675123u;\n    uint32_t next() {\n        uint32_t t = x ^ (x << 11);\n        x = y; y = z; z = w;\n        w = w ^ (w >> 19) ^ (t ^ (t >> 8));\n        return w;\n    }\n    uint32_t nextUInt(uint32_t bound) {\n        return next() % bound;\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    const int N = 400;\n    const int M = 1995;\n\n    // ----- Read coordinates -----\n    vector<int> x(N), y(N);\n    for (int i = 0; i < N; i++) {\n        if (!(cin >> x[i] >> y[i])) return 0;\n    }\n\n    // ----- Read edges -----\n    vector<int> u(M), v(M);\n    for (int i = 0; i < M; i++) {\n        cin >> u[i] >> v[i];\n    }\n\n    // ----- Precompute geometric distances d_i -----\n    vector<int> d(M);\n    for (int i = 0; i < M; i++) {\n        int dx = x[u[i]] - x[v[i]];\n        int dy = y[u[i]] - y[v[i]];\n        double dist = sqrt((double)dx * dx + (double)dy * dy);\n        d[i] = (int)llround(dist);\n    }\n\n    // ----- Compute geometric MST (base tree for guaranteed connectivity) -----\n    vector<int> idx(M);\n    iota(idx.begin(), idx.end(), 0);\n    sort(idx.begin(), idx.end(), [&](int a, int b) {\n        if (d[a] != d[b]) return d[a] < d[b];\n        return a < b;\n    });\n\n    vector<char> inTree(M, false);\n    DSU dsu0(N);\n    int used = 0;\n    for (int id : idx) {\n        if (!dsu0.same(u[id], v[id])) {\n            dsu0.unite(u[id], v[id]);\n            inTree[id] = true;\n            used++;\n            if (used == N - 1) break;\n        }\n    }\n\n    // ----- Build adjacency of geometric MST -----\n    vector<vector<pair<int,int>>> adj(N);\n    for (int i = 0; i < M; i++) {\n        if (!inTree[i]) continue;\n        adj[u[i]].push_back({v[i], d[i]});\n        adj[v[i]].push_back({u[i], d[i]});\n    }\n\n    // ----- LCA precomputation for max edge on path in MST -----\n    const int LOG = 9; // 2^9 = 512 > 400\n    vector<int> depth(N, 0);\n    vector<vector<int>> par(LOG, vector<int>(N));\n    vector<vector<int>> mx(LOG, vector<int>(N));\n\n    {\n        queue<int> q;\n        vector<char> vis(N, false);\n        int root = 0;\n        vis[root] = true;\n        depth[root] = 0;\n        par[0][root] = root;\n        mx[0][root] = 0;\n        q.push(root);\n        while (!q.empty()) {\n            int cur = q.front(); q.pop();\n            for (auto [to, w] : adj[cur]) {\n                if (!vis[to]) {\n                    vis[to] = true;\n                    depth[to] = depth[cur] + 1;\n                    par[0][to] = cur;\n                    mx[0][to] = w;\n                    q.push(to);\n                }\n            }\n        }\n        for (int k = 1; k < LOG; k++) {\n            for (int vtx = 0; vtx < N; vtx++) {\n                int p = par[k-1][vtx];\n                par[k][vtx] = par[k-1][p];\n                mx[k][vtx] = max(mx[k-1][vtx], mx[k-1][p]);\n            }\n        }\n    }\n\n    auto getMaxOnPath = [&](int a, int b) -> int {\n        if (a == b) return 0;\n        int res = 0;\n        if (depth[a] < depth[b]) swap(a, b);\n        int diff = depth[a] - depth[b];\n        for (int k = 0; k < LOG; k++) {\n            if (diff & (1 << k)) {\n                res = max(res, mx[k][a]);\n                a = par[k][a];\n            }\n        }\n        if (a == b) return res;\n        for (int k = LOG - 1; k >= 0; k--) {\n            if (par[k][a] != par[k][b]) {\n                res = max(res, mx[k][a]);\n                res = max(res, mx[k][b]);\n                a = par[k][a];\n                b = par[k][b];\n            }\n        }\n        res = max(res, mx[0][a]);\n        res = max(res, mx[0][b]);\n        return res;\n    };\n\n    // ----- Compute H[i] = max d on path in MST between u[i], v[i] (for non-tree edges) -----\n    vector<int> H(M, 0);\n    for (int i = 0; i < M; i++) {\n        if (inTree[i]) continue;\n        H[i] = getMaxOnPath(u[i], v[i]);\n        if (H[i] == 0) H[i] = d[i]; // safety\n    }\n\n    // ----- Monte Carlo over true distributions to estimate \"good\" lengths -----\n    // For each run: sample random lengths, compute MST, store lengths of edges used in MST.\n    XorShift rng;\n    const int S = 1600; // number of simulations\n    vector<vector<int>> chosenLens(M);\n    chosenLens.assign(M, {});\n    for (int i = 0; i < M; i++) {\n        chosenLens[i].reserve(256); // rough heuristic\n    }\n\n    vector<int> sampleLen(M);\n    vector<int> perm(M);\n\n    for (int s = 0; s < S; s++) {\n        for (int i = 0; i < M; i++) {\n            uint32_t range = (uint32_t)(2 * d[i] + 1); // from d[i] to 3*d[i]\n            sampleLen[i] = d[i] + (int)rng.nextUInt(range);\n            perm[i] = i;\n        }\n        sort(perm.begin(), perm.end(), [&](int a, int b) {\n            if (sampleLen[a] != sampleLen[b]) return sampleLen[a] < sampleLen[b];\n            return a < b;\n        });\n        DSU dsu(N);\n        int cnt = 0;\n        for (int eid : perm) {\n            if (!dsu.same(u[eid], v[eid])) {\n                dsu.unite(u[eid], v[eid]);\n                chosenLens[eid].push_back(sampleLen[eid]);\n                cnt++;\n                if (cnt == N - 1) break;\n            }\n        }\n    }\n\n    // ----- Compute per-edge thresholds thr[i] for non-tree edges -----\n    // thr[i] is a length; online, we accept non-tree edge i iff l_i <= thr[i].\n    vector<int> thr(M);\n    for (int i = 0; i < M; i++) {\n        thr[i] = d[i]; // default minimal threshold\n    }\n\n    for (int i = 0; i < M; i++) {\n        if (inTree[i]) continue; // thresholds are only for non-tree edges\n        auto &vec = chosenLens[i];\n        if (vec.empty()) {\n            // Edge almost never appears in MST in simulations; accept only if extremely cheap\n            thr[i] = d[i];\n            continue;\n        }\n        sort(vec.begin(), vec.end());\n        int Hi = H[i];\n        if (Hi <= 0) Hi = d[i];\n        double r = (double)d[i] / (double)Hi;\n        if (r < 1.0) r = 1.0;\n        if (r > 3.0) r = 3.0;\n\n        // Choose quantile factor based on how comparable this edge is to the heaviest tree edge on its path.\n        double qf;\n        if (r <= 1.02) qf = 0.80;\n        else if (r <= 1.20) qf = 0.76;\n        else if (r <= 1.50) qf = 0.72;\n        else if (r <= 1.80) qf = 0.66;\n        else if (r <= 2.20) qf = 0.60;\n        else           qf = 0.54;\n\n        int cnt = (int)vec.size();\n        int idx = (int)(qf * cnt);\n        if (idx >= cnt) idx = cnt - 1;\n        if (idx < 0) idx = 0;\n\n        int t = vec[idx];\n        if (t < d[i]) t = d[i];\n        int maxLen = 3 * d[i];\n        if (t > maxLen) t = maxLen;\n        thr[i] = t;\n    }\n\n    // ----- Online phase -----\n    DSU dsuCur(N);\n\n    for (int i = 0; i < M; i++) {\n        long long l;\n        if (!(cin >> l)) return 0;\n\n        bool take = false;\n\n        if (!dsuCur.same(u[i], v[i])) {\n            if (inTree[i]) {\n                // Tree edge: always accept when it connects different components\n                take = true;\n            } else {\n                // Non-tree edge: accept if its realized length is not too large\n                if (l <= thr[i]) {\n                    take = true;\n                }\n            }\n        } else {\n            take = false; // would form a cycle\n        }\n\n        if (take) {\n            dsuCur.unite(u[i], v[i]);\n        }\n\n        cout << (take ? 1 : 0) << '\\n';\n        cout.flush();\n    }\n\n    return 0;\n}","ahc008":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Pet {\n    int x, y, t;\n};\n\nstruct Human {\n    int x, y;\n};\n\nstatic const int H = 30;\nstatic const int W = 30;\n\nbool inside(int x, int y) {\n    return 1 <= x && x <= H && 1 <= y && y <= W;\n}\n\n// Check whether we are allowed to place a wall at (x,y)\nbool canWallCell(int x, int y,\n                 const vector<Pet> &pets,\n                 const vector<Human> &humans) {\n    if (!inside(x, y)) return false;\n    // Cannot place on a human\n    for (const auto &h : humans) {\n        if (h.x == x && h.y == y) return false;\n    }\n    // Cannot place on or adjacent (4-neighbor) to a pet\n    for (const auto &p : pets) {\n        int dx = abs(p.x - x);\n        int dy = abs(p.y - y);\n        if (dx + dy == 0) return false; // same cell\n        if (dx + dy == 1) return false; // 4-neighbor\n    }\n    return true;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    if (!(cin >> N)) {\n        return 0;\n    }\n    vector<Pet> pets(N);\n    for (int i = 0; i < N; i++) {\n        cin >> pets[i].x >> pets[i].y >> pets[i].t;\n    }\n    int M;\n    cin >> M;\n    vector<Human> humans(M);\n    for (int i = 0; i < M; i++) {\n        cin >> humans[i].x >> humans[i].y;\n    }\n\n    // Grid of walls: true means impassable\n    static bool wall[H + 1][W + 1];\n    for (int i = 1; i <= H; i++) {\n        for (int j = 1; j <= W; j++) wall[i][j] = false;\n    }\n\n    // We will build a vertical wall at column WALL_COL\n    const int WALL_COL = 16; // 1-indexed\n    const int WALK_COL = 17; // walkway column for the builder (to the right of the wall)\n    const int builder = 0;   // index of the builder human\n\n    // Row completion tracking for the wall\n    vector<bool> rowWalled(H + 1, false);\n    int walledCount = 0;\n\n    const int T_PRE = 50; // preparation phase duration\n\n    for (int turn = 0; turn < 300; turn++) {\n        string actions(M, '.');\n\n        // Decide actions for humans\n        if (M > 0) {\n            Human &hb = humans[builder];\n            int hx = hb.x;\n            int hy = hb.y;\n\n            char act = '.';\n\n            if (turn < T_PRE) {\n                // Preparation: move builder horizontally to walkway column\n                if (hy < WALK_COL) act = 'R';\n                else if (hy > WALK_COL) act = 'L';\n                else act = '.';\n            } else {\n                // Building phase\n                if (hy != WALK_COL) {\n                    // Ensure builder is on walkway column\n                    if (hy < WALK_COL) act = 'R';\n                    else if (hy > WALK_COL) act = 'L';\n                } else {\n                    // On walkway column; move up/down and place walls\n                    if (walledCount >= H) {\n                        act = '.';\n                    } else {\n                        // Determine if we can wall at current row\n                        bool thisRowUnwalled = !rowWalled[hx];\n\n                        bool canWallHere = false;\n                        if (thisRowUnwalled && !wall[hx][WALL_COL]) {\n                            if (canWallCell(hx, WALL_COL, pets, humans)) {\n                                canWallHere = true;\n                            }\n                        }\n                        if (thisRowUnwalled && canWallHere) {\n                            // Place wall to the left from (hx, WALK_COL) to (hx, WALL_COL)\n                            act = (WALK_COL > WALL_COL ? 'l' : 'r');\n                            wall[hx][WALL_COL] = true;\n                            rowWalled[hx] = true;\n                            walledCount++;\n                        } else {\n                            // Move to nearest other row that still needs a wall\n                            int bestRow = -1;\n                            int bestDist = INT_MAX;\n                            for (int r = 1; r <= H; r++) {\n                                if (!rowWalled[r] && r != hx) {\n                                    int d = abs(r - hx);\n                                    if (d < bestDist) {\n                                        bestDist = d;\n                                        bestRow = r;\n                                    }\n                                }\n                            }\n                            if (bestRow != -1) {\n                                if (bestRow > hx) act = 'D';\n                                else act = 'U';\n                            } else {\n                                // This row is the only remaining one; wait until it becomes safe\n                                act = '.';\n                            }\n                        }\n                    }\n                }\n            }\n            actions[builder] = act;\n        }\n\n        // Other humans\n        for (int i = 0; i < M; i++) {\n            if (i == builder) continue;\n            Human &h = humans[i];\n            char act = '.';\n            if (turn < T_PRE) {\n                // Move off the wall column if initially on it\n                if (h.y == WALL_COL) {\n                    // Simple: move left (safe, because WALL_COL=16, so >=2)\n                    act = 'L';\n                }\n            } else {\n                act = '.';\n            }\n            actions[i] = act;\n        }\n\n        // Output actions and flush\n        cout << actions << '\\n' << flush;\n\n        // Apply wall placements\n        for (int i = 0; i < M; i++) {\n            char c = actions[i];\n            if (c == 'u' || c == 'd' || c == 'l' || c == 'r') {\n                int x = humans[i].x;\n                int y = humans[i].y;\n                int nx = x, ny = y;\n                if (c == 'u') nx = x - 1;\n                else if (c == 'd') nx = x + 1;\n                else if (c == 'l') ny = y - 1;\n                else if (c == 'r') ny = y + 1;\n                if (inside(nx, ny)) {\n                    wall[nx][ny] = true;\n                }\n            }\n        }\n\n        // Apply human moves\n        for (int i = 0; i < M; i++) {\n            char c = actions[i];\n            if (c == 'U' || c == 'D' || c == 'L' || c == 'R') {\n                int x = humans[i].x;\n                int y = humans[i].y;\n                int nx = x, ny = y;\n                if (c == 'U') nx = x - 1;\n                else if (c == 'D') nx = x + 1;\n                else if (c == 'L') ny = y - 1;\n                else if (c == 'R') ny = y + 1;\n                if (inside(nx, ny) && !wall[nx][ny]) {\n                    humans[i].x = nx;\n                    humans[i].y = ny;\n                }\n            }\n        }\n\n        // Read pets' moves\n        vector<string> pmoves(N);\n        for (int i = 0; i < N; i++) {\n            cin >> pmoves[i];\n        }\n\n        // Apply pets' moves\n        for (int i = 0; i < N; i++) {\n            for (char c : pmoves[i]) {\n                int x = pets[i].x;\n                int y = pets[i].y;\n                int nx = x, ny = y;\n                if (c == 'U') nx = x - 1;\n                else if (c == 'D') nx = x + 1;\n                else if (c == 'L') ny = y - 1;\n                else if (c == 'R') ny = y + 1;\n                if (inside(nx, ny) && !wall[nx][ny]) {\n                    pets[i].x = nx;\n                    pets[i].y = ny;\n                } else {\n                    // According to rules, pets won't try to move into walls,\n                    // but we keep this check for safety.\n                }\n            }\n        }\n    }\n\n    return 0;\n}","ahc009":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const int H = 20;\nstatic const int W = 20;\nstatic const int N = H * W;\nstatic const int MAXL = 200;\n\n// DP arrays\nstatic double alpha_dp[MAXL + 1][N];\nstatic double beta_dp [MAXL + 1][N];\nstatic double prefix_score[MAXL + 1];\n\n// Direction mapping\nint dirIdx[256];\nchar dirChar[4] = {'U', 'D', 'L', 'R'};\n\n// Precomputed next cell for each dir and cell\nint nextCell[4][N];\n\n// Globals\nint start_id, goal_id;\nint L = MAXL;\ndouble forget_p;\n\n// RNG for randomized BFS and hill-climb order\nmt19937 rng(1234567);\n\n// Build adjacency (undirected) from walls\nvector<vector<int>> build_graph(const vector<string> &h, const vector<string> &v) {\n    vector<vector<int>> g(N);\n    auto cell_id = [](int r, int c) { return r * W + c; };\n\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            int id = cell_id(i, j);\n            if (j + 1 < W && h[i][j] == '0') {\n                int nid = cell_id(i, j + 1);\n                g[id].push_back(nid);\n                g[nid].push_back(id);\n            }\n            if (i + 1 < H && v[i][j] == '0') {\n                int nid = cell_id(i + 1, j);\n                g[id].push_back(nid);\n                g[nid].push_back(id);\n            }\n        }\n    }\n    return g;\n}\n\n// Decode direction from 'from' to 'to'\nchar decode_dir(int from, int to) {\n    int r1 = from / W, c1 = from % W;\n    int r2 = to   / W, c2 = to   % W;\n    if (r2 == r1 && c2 == c1 + 1) return 'R';\n    if (r2 == r1 && c2 == c1 - 1) return 'L';\n    if (r2 == r1 + 1 && c2 == c1) return 'D';\n    if (r2 == r1 - 1 && c2 == c1) return 'U';\n    // Should not happen\n    return 'U';\n}\n\n// BFS shortest path, optionally randomized by shuffling adjacency\nvector<char> bfs_shortest_path_any(const vector<vector<int>> &g, bool randomized) {\n    vector<vector<int>> g2;\n    if (randomized) {\n        g2 = g;\n        for (int u = 0; u < N; ++u) {\n            shuffle(g2[u].begin(), g2[u].end(), rng);\n        }\n    } else {\n        // Use adjacency as given\n        g2 = g;\n    }\n\n    vector<int> prev(N, -1);\n    queue<int> q;\n    q.push(start_id);\n    prev[start_id] = start_id;\n\n    while (!q.empty()) {\n        int vtx = q.front(); q.pop();\n        if (vtx == goal_id) break;\n        for (int to : g2[vtx]) {\n            if (prev[to] == -1) {\n                prev[to] = vtx;\n                q.push(to);\n            }\n        }\n    }\n\n    vector<char> path;\n    int cur = goal_id;\n    if (prev[cur] == -1) {\n        // Fallback (should not happen since graph is connected)\n        path.push_back('R');\n        return path;\n    }\n    while (cur != start_id) {\n        int p = prev[cur];\n        path.push_back(decode_dir(p, cur));\n        cur = p;\n    }\n    reverse(path.begin(), path.end());\n    if (path.empty()) path.push_back('R');\n    return path;\n}\n\n// Build a \"goal loop\" pattern: from goal, move to each neighbor and back\nvector<char> build_goal_loop_pattern() {\n    vector<char> pattern;\n    auto rev_dir = [](char c) {\n        if (c == 'U') return 'D';\n        if (c == 'D') return 'U';\n        if (c == 'L') return 'R';\n        return 'L';  // 'R'\n    };\n\n    for (char c : {'U', 'D', 'L', 'R'}) {\n        int d = dirIdx[(unsigned char)c];\n        int dest = nextCell[d][goal_id];\n        if (dest != goal_id) {\n            pattern.push_back(c);\n            pattern.push_back(rev_dir(c));\n        }\n    }\n    if (pattern.empty()) {\n        // Extremely unlikely; safeguard\n        pattern.push_back('U');\n        pattern.push_back('D');\n    }\n    return pattern;\n}\n\n// Evaluate a full route s[1..L]; fills alpha_dp, beta_dp, prefix_score; returns E[S]\ndouble evaluate_route(const vector<char> &s) {\n    const double p = forget_p;\n    const double q = 1.0 - p;\n\n    // Forward DP: alpha_dp, prefix_score\n    memset(alpha_dp, 0, sizeof(alpha_dp));\n    alpha_dp[0][start_id] = 1.0;\n    prefix_score[0] = 0.0;\n\n    for (int t = 1; t <= L; ++t) {\n        memset(alpha_dp[t], 0, sizeof(alpha_dp[t]));\n        prefix_score[t] = prefix_score[t - 1];\n        int d = dirIdx[(unsigned char)s[t]];\n        double reward_weight = 401.0 - t;\n\n        for (int id = 0; id < N; ++id) {\n            double px = alpha_dp[t - 1][id];\n            if (px == 0.0) continue;\n\n            if (id == goal_id) {\n                alpha_dp[t][id] += px;\n                continue;\n            }\n\n            int dest = nextCell[d][id];\n\n            if (dest == id) {\n                // Blocked: stay\n                alpha_dp[t][id] += px;\n            } else if (dest == goal_id) {\n                double moved = px * q;\n                prefix_score[t] += moved * reward_weight;\n                alpha_dp[t][goal_id] += moved;\n                alpha_dp[t][id] += px * p;\n            } else {\n                double moved = px * q;\n                alpha_dp[t][dest] += moved;\n                alpha_dp[t][id]   += px * p;\n            }\n        }\n    }\n\n    double total_score = prefix_score[L];\n\n    // Backward DP: beta_dp\n    memset(beta_dp, 0, sizeof(beta_dp));\n    for (int id = 0; id < N; ++id) beta_dp[L][id] = 0.0;\n\n    for (int t = L - 1; t >= 0; --t) {\n        int d = dirIdx[(unsigned char)s[t + 1]];\n        double reward_weight = 401.0 - (t + 1);\n\n        for (int id = 0; id < N; ++id) {\n            if (id == goal_id) {\n                beta_dp[t][id] = 0.0;\n                continue;\n            }\n            int dest = nextCell[d][id];\n            double immediate = 0.0;\n            double future = 0.0;\n\n            if (dest == id) {\n                future = beta_dp[t + 1][id];\n            } else if (dest == goal_id) {\n                immediate = q * reward_weight;\n                future = p * beta_dp[t + 1][id];\n            } else {\n                future = q * beta_dp[t + 1][dest] + p * beta_dp[t + 1][id];\n            }\n            beta_dp[t][id] = immediate + future;\n        }\n    }\n\n    return total_score;\n}\n\n// Compute E[S] if only step k is changed to newDir, using current DP data\ndouble score_if_change_step(const vector<char> &s, int k, char newDir) {\n    const double p = forget_p;\n    const double q = 1.0 - p;\n\n    double res = prefix_score[k - 1];\n    int d = dirIdx[(unsigned char)newDir];\n\n    for (int id = 0; id < N; ++id) {\n        double px = alpha_dp[k - 1][id];\n        if (px == 0.0) continue;\n        if (id == goal_id) continue;\n\n        int dest = nextCell[d][id];\n        if (dest == id) {\n            res += px * beta_dp[k][id];\n        } else if (dest == goal_id) {\n            res += px * q * (401.0 - k);\n            res += px * p * beta_dp[k][id];\n        } else {\n            res += px * (q * beta_dp[k][dest] + p * beta_dp[k][id]);\n        }\n    }\n    return res;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int si, sj, ti, tj;\n    if (!(cin >> si >> sj >> ti >> tj >> forget_p)) {\n        return 0;\n    }\n    vector<string> h(H), v(H - 1);\n    for (int i = 0; i < H; ++i) cin >> h[i];\n    for (int i = 0; i < H - 1; ++i) cin >> v[i];\n\n    start_id = si * W + sj;\n    goal_id  = ti * W + tj;\n\n    // Direction indices\n    dirIdx['U'] = 0;\n    dirIdx['D'] = 1;\n    dirIdx['L'] = 2;\n    dirIdx['R'] = 3;\n\n    // Precompute nextCell for each dir and cell\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            int id = i * W + j;\n            // Up\n            if (i == 0 || v[i - 1][j] == '1') nextCell[0][id] = id;\n            else                              nextCell[0][id] = (i - 1) * W + j;\n            // Down\n            if (i == H - 1 || v[i][j] == '1') nextCell[1][id] = id;\n            else                               nextCell[1][id] = (i + 1) * W + j;\n            // Left\n            if (j == 0 || h[i][j - 1] == '1') nextCell[2][id] = id;\n            else                              nextCell[2][id] = i * W + (j - 1);\n            // Right\n            if (j == W - 1 || h[i][j] == '1') nextCell[3][id] = id;\n            else                              nextCell[3][id] = i * W + (j + 1);\n        }\n    }\n\n    // Build adjacency for BFS\n    vector<vector<int>> graph = build_graph(h, v);\n\n    // Build goal-loop pattern\n    vector<char> goal_pattern = build_goal_loop_pattern();\n    int goal_pat_len = (int)goal_pattern.size();\n\n    // Generate base BFS paths: 1 canonical + a few randomized\n    vector<vector<char>> basePaths;\n    basePaths.reserve(4);\n    basePaths.push_back(bfs_shortest_path_any(graph, false)); // canonical\n    const int BFS_RANDOM_COUNT = 3;\n    for (int b = 0; b < BFS_RANDOM_COUNT; ++b) {\n        basePaths.push_back(bfs_shortest_path_any(graph, true));\n    }\n\n    // Build candidate routes and pick the best\n    vector<char> bestRoute(L + 1);\n    double bestScore = -1.0;\n\n    for (const auto &path_raw : basePaths) {\n        vector<char> path = path_raw;\n        if (path.empty()) path.push_back('R');\n        int D = (int)path.size();\n        if (D > L) D = L;\n\n        // Type 0: repeat BFS path\n        {\n            vector<char> route(L + 1);\n            for (int t = 1; t <= L; ++t) {\n                route[t] = path[(t - 1) % D];\n            }\n            double sc = evaluate_route(route);\n            if (sc > bestScore) {\n                bestScore = sc;\n                bestRoute = route;\n            }\n        }\n\n        // Type 1: BFS once, then goal pattern\n        {\n            vector<char> route(L + 1);\n            for (int t = 1; t <= L; ++t) {\n                if (t <= D) {\n                    route[t] = path[t - 1];\n                } else {\n                    route[t] = goal_pattern[(t - D - 1) % goal_pat_len];\n                }\n            }\n            double sc = evaluate_route(route);\n            if (sc > bestScore) {\n                bestScore = sc;\n                bestRoute = route;\n            }\n        }\n\n        // Type 2: BFS twice, then goal pattern (if room)\n        {\n            vector<char> route(L + 1);\n            for (int t = 1; t <= L; ++t) {\n                if (t <= D) {\n                    route[t] = path[t - 1];\n                } else if (t <= 2 * D && 2 * D <= L) {\n                    route[t] = path[t - D - 1];\n                } else {\n                    // After two passes (when possible), do goal pattern\n                    int offset = t - min(2 * D, L) - 1;\n                    if (offset < 0) offset = 0;\n                    route[t] = goal_pattern[offset % goal_pat_len];\n                }\n            }\n            double sc = evaluate_route(route);\n            if (sc > bestScore) {\n                bestScore = sc;\n                bestRoute = route;\n            }\n        }\n    }\n\n    // Re-evaluate bestRoute so DP arrays match it\n    bestScore = evaluate_route(bestRoute);\n    vector<char> route = bestRoute;\n\n    // Hill-climbing: DP-based coordinate descent, random order\n    const int MAX_ITER = 5;\n    const double EPS = 1e-9;\n\n    vector<int> order(L);\n    for (int i = 0; i < L; ++i) order[i] = i + 1;\n\n    for (int iter = 0; iter < MAX_ITER; ++iter) {\n        bool improved_any = false;\n        shuffle(order.begin(), order.end(), rng);\n\n        for (int idx = 0; idx < L; ++idx) {\n            int k = order[idx];\n            char orig = route[k];\n            char bestDir = orig;\n            double currScore = bestScore;\n\n            // Try 3 alternative directions\n            for (int di = 0; di < 4; ++di) {\n                char c = dirChar[di];\n                if (c == orig) continue;\n                double newScore = score_if_change_step(route, k, c);\n                if (newScore > currScore + EPS) {\n                    currScore = newScore;\n                    bestDir = c;\n                }\n            }\n\n            if (bestDir != orig) {\n                route[k] = bestDir;\n                bestScore = evaluate_route(route);\n                improved_any = true;\n            }\n        }\n        if (!improved_any) break;\n    }\n\n    // Output final route\n    string out;\n    out.reserve(L);\n    for (int t = 1; t <= L; ++t) out.push_back(route[t]);\n    cout << out << '\\n';\n\n    return 0;\n}","ahc010":"#include <bits/stdc++.h>\nusing namespace std;\n\nconstexpr int N = 30;\nconstexpr int M = 30;\nconstexpr int TOT_STATES = N * M * 4;\n\n// Input and current board\nint baseTile[N][M];   // initial tile types from input (0..7)\nint curTile[N][M];    // current effective tile type (0..7) after rotation\nint curRot[N][M];     // current rotation count (0..3) for each tile\n\n// Stage-1 best (local score)\nint bestLocalRot[N][M];\n// Final best (true score)\nint bestRot[N][M];\n\n// Rotation table: rotTable[t][r] = tile type after rotating t by r times 90deg CCW\nint rotTable[8][4];\n\n// Rail mapping: toTbl[t][d] = exit direction when entering tile type t from direction d\n// d: 0 = left, 1 = up, 2 = right, 3 = down\nint toTbl[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// Whether side d of tile type t has a rail\nbool useSide[8][4];\n\n// For loop detection in computeTrueScore (using precomputed transitions)\nbool visitedState[TOT_STATES];\nint  pathId[TOT_STATES];\nint  pathStep[TOT_STATES];\n\n// Precomputed \"next state\" transition: from (i, j, d) to next state's index, or -1 if dead-end\nint nextStateArr[TOT_STATES];\n\nint di[4] = {0, -1, 0, 1};  // left, up, right, down\nint dj[4] = {-1, 0, 1, 0};\n\nmt19937_64 rng(20240131);\n\n// Encode (i, j, d) into a single index 0..3599\ninline int encodeState(int i, int j, int d) {\n    return ((i * M + j) << 2) | d;  // 0..3599\n}\n\n// Compute local score = number of connected internal edges\nint computeLocalScore() {\n    int connected = 0;\n\n    // Horizontal internal edges: (i,j)-(i,j+1)\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < M - 1; ++j) {\n            int t1 = curTile[i][j];\n            int t2 = curTile[i][j + 1];\n            if (useSide[t1][2] && useSide[t2][0]) connected++;\n        }\n    }\n    // Vertical internal edges: (i,j)-(i+1,j)\n    for (int i = 0; i < N - 1; ++i) {\n        for (int j = 0; j < M; ++j) {\n            int t1 = curTile[i][j];\n            int t2 = curTile[i + 1][j];\n            if (useSide[t1][3] && useSide[t2][1]) connected++;\n        }\n    }\n    return connected;\n}\n\n// Incremental delta of local score when tile (i,j) type changes from oldT to newT\ninline int deltaLocalScoreTile(int i, int j, int oldT, int newT) {\n    int deltaConn = 0;\n\n    // Up neighbor\n    if (i > 0) {\n        int neighbor = curTile[i - 1][j];\n        bool neighborUsedDown = useSide[neighbor][3];\n        bool oldUsedUp = useSide[oldT][1];\n        bool newUsedUp = useSide[newT][1];\n        int before = (oldUsedUp && neighborUsedDown) ? 1 : 0;\n        int after  = (newUsedUp && neighborUsedDown) ? 1 : 0;\n        deltaConn += after - before;\n    }\n\n    // Down neighbor\n    if (i < N - 1) {\n        int neighbor = curTile[i + 1][j];\n        bool neighborUsedUp = useSide[neighbor][1];\n        bool oldUsedDown = useSide[oldT][3];\n        bool newUsedDown = useSide[newT][3];\n        int before = (oldUsedDown && neighborUsedUp) ? 1 : 0;\n        int after  = (newUsedDown && neighborUsedUp) ? 1 : 0;\n        deltaConn += after - before;\n    }\n\n    // Left neighbor\n    if (j > 0) {\n        int neighbor = curTile[i][j - 1];\n        bool neighborUsedRight = useSide[neighbor][2];\n        bool oldUsedLeft = useSide[oldT][0];\n        bool newUsedLeft = useSide[newT][0];\n        int before = (oldUsedLeft && neighborUsedRight) ? 1 : 0;\n        int after  = (newUsedLeft && neighborUsedRight) ? 1 : 0;\n        deltaConn += after - before;\n    }\n\n    // Right neighbor\n    if (j < M - 1) {\n        int neighbor = curTile[i][j + 1];\n        bool neighborUsedLeft = useSide[neighbor][0];\n        bool oldUsedRight = useSide[oldT][2];\n        bool newUsedRight = useSide[newT][2];\n        int before = (oldUsedRight && neighborUsedLeft) ? 1 : 0;\n        int after  = (newUsedRight && neighborUsedLeft) ? 1 : 0;\n        deltaConn += after - before;\n    }\n\n    return deltaConn;\n}\n\n// Build transitions for all states based on curTile\nvoid buildAllTransitions() {\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < M; ++j) {\n            int t = curTile[i][j];\n            for (int d = 0; d < 4; ++d) {\n                int idx = encodeState(i, j, d);\n                int d2 = toTbl[t][d];\n                if (d2 == -1) {\n                    nextStateArr[idx] = -1;\n                    continue;\n                }\n                int ni = i + di[d2];\n                int nj = j + dj[d2];\n                if (ni < 0 || ni >= N || nj < 0 || nj >= M) {\n                    nextStateArr[idx] = -1;\n                } else {\n                    int nd = (d2 + 2) & 3;\n                    nextStateArr[idx] = encodeState(ni, nj, nd);\n                }\n            }\n        }\n    }\n}\n\n// Update transitions only for tile (i,j) based on current curTile[i][j]\ninline void updateTransitionsForTile(int i, int j) {\n    int t = curTile[i][j];\n    for (int d = 0; d < 4; ++d) {\n        int idx = encodeState(i, j, d);\n        int d2 = toTbl[t][d];\n        if (d2 == -1) {\n            nextStateArr[idx] = -1;\n            continue;\n        }\n        int ni = i + di[d2];\n        int nj = j + dj[d2];\n        if (ni < 0 || ni >= N || nj < 0 || nj >= M) {\n            nextStateArr[idx] = -1;\n        } else {\n            int nd = (d2 + 2) & 3;\n            nextStateArr[idx] = encodeState(ni, nj, nd);\n        }\n    }\n}\n\n// Compute true score = product of lengths of two longest loops\nint computeTrueScore() {\n    fill(visitedState, visitedState + TOT_STATES, false);\n    fill(pathId, pathId + TOT_STATES, 0);\n\n    int best1 = 0, best2 = 0;\n    int curPathId = 1;\n\n    for (int s = 0; s < TOT_STATES; ++s) {\n        if (visitedState[s]) continue;\n        int nxt0 = nextStateArr[s];\n        if (nxt0 < 0) {\n            visitedState[s] = true;\n            continue;\n        }\n\n        int cur = s;\n        int len = 0;\n        ++curPathId;\n\n        while (true) {\n            visitedState[cur] = true;\n            pathId[cur] = curPathId;\n            pathStep[cur] = len;\n\n            int nxt = nextStateArr[cur];\n            if (nxt < 0) break;\n            ++len;\n            if (pathId[nxt] == curPathId) {\n                int cycLen = len - pathStep[nxt];\n                if (cycLen >= best1) {\n                    best2 = best1;\n                    best1 = cycLen;\n                } else if (cycLen > best2) {\n                    best2 = cycLen;\n                }\n                break;\n            }\n            if (visitedState[nxt]) break;\n            cur = nxt;\n        }\n    }\n\n    if (best2 == 0) return 0;\n    return best1 * best2;\n}\n\ninline double randDouble() {\n    return (double)(rng() >> 11) * (1.0 / (1ULL << 53));\n}\n\n// For multi-tile moves in SA\nstruct TileChange {\n    int i, j;\n    int oldRot, oldT;\n    int newRot, newT;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // Precompute rotation table\n    int rotMap[8] = {1, 2, 3, 0, 5, 4, 7, 6};\n    for (int t = 0; t < 8; ++t) {\n        rotTable[t][0] = t;\n        for (int r = 1; r < 4; ++r) {\n            rotTable[t][r] = rotMap[ rotTable[t][r - 1] ];\n        }\n    }\n\n    // Precompute useSide\n    for (int t = 0; t < 8; ++t) {\n        for (int d = 0; d < 4; ++d) {\n            useSide[t][d] = (toTbl[t][d] != -1);\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 < M; ++j) {\n            baseTile[i][j] = s[j] - '0';\n        }\n    }\n\n    auto timeStart = chrono::steady_clock::now();\n    const double GLOBAL_TIME_LIMIT = 1.9;  // seconds\n\n    // ===== Stage 1: Multi-start greedy local search on local score =====\n    const int MAX_RUNS = 8;\n    const int MAX_PASS = 10;\n\n    vector<int> order(N * M);\n    iota(order.begin(), order.end(), 0);\n\n    int bestLocalScore = numeric_limits<int>::min();\n\n    for (int run = 0; run < MAX_RUNS; ++run) {\n        // Random initial rotations\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < M; ++j) {\n                int r = (int)(rng() & 3ULL);  // 0..3\n                curRot[i][j] = r;\n                curTile[i][j] = rotTable[ baseTile[i][j] ][r];\n            }\n        }\n\n        int curLocalScore = computeLocalScore();\n\n        for (int pass = 0; pass < MAX_PASS; ++pass) {\n            bool changed = false;\n            shuffle(order.begin(), order.end(), rng);\n\n            for (int idxCell : order) {\n                int i = idxCell / M;\n                int j = idxCell % M;\n\n                int oldRot = curRot[i][j];\n                int oldT = curTile[i][j];\n\n                int bestDelta = 0;\n                int bestR = oldRot;\n                int bestT = oldT;\n\n                // Try all 4 rotations\n                for (int r = 0; r < 4; ++r) {\n                    if (r == oldRot) continue;\n                    int newT = rotTable[ baseTile[i][j] ][r];\n                    if (newT == oldT) continue; // same effective type\n                    int delta = deltaLocalScoreTile(i, j, oldT, newT);\n                    if (delta > bestDelta) {\n                        bestDelta = delta;\n                        bestR = r;\n                        bestT = newT;\n                    }\n                }\n\n                if (bestDelta > 0) {\n                    curRot[i][j] = bestR;\n                    curTile[i][j] = bestT;\n                    curLocalScore += bestDelta;\n                    changed = true;\n                }\n            }\n\n            if (!changed) break;\n        }\n\n        if (curLocalScore > bestLocalScore) {\n            bestLocalScore = curLocalScore;\n            for (int i = 0; i < N; ++i)\n                for (int j = 0; j < M; ++j)\n                    bestLocalRot[i][j] = curRot[i][j];\n        }\n\n        double elapsed = chrono::duration<double>(chrono::steady_clock::now() - timeStart).count();\n        if (elapsed > GLOBAL_TIME_LIMIT * 0.25) {\n            // Keep enough time for Stage 2\n            break;\n        }\n    }\n\n    // Initialize curRot/curTile from best local configuration\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < M; ++j) {\n            curRot[i][j] = bestLocalRot[i][j];\n            curTile[i][j] = rotTable[ baseTile[i][j] ][curRot[i][j]];\n        }\n    }\n\n    // Build transitions for Stage 2\n    buildAllTransitions();\n\n    // Initial true score from Stage-1 result\n    int curScore = computeTrueScore();\n    int bestScore = curScore;\n\n    // Copy as initial best rotations for Stage 2\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < M; ++j)\n            bestRot[i][j] = curRot[i][j];\n\n    // Precompute indices of cross tiles (type 4 or 5) to bias SA moves\n    vector<int> crossIdx;\n    crossIdx.reserve(N * M / 2);\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < M; ++j) {\n            int t0 = baseTile[i][j];\n            if (t0 == 4 || t0 == 5) {\n                crossIdx.push_back(i * M + j);\n            }\n        }\n    }\n\n    // ===== Stage 2: Simulated annealing on true score (single- & multi-tile moves) =====\n    const double T0  = 800.0; // global initial temperature\n    const double T1  = 3.0;   // global final temperature\n    const double TL0 = 6.0;   // local filter initial \"temperature\"\n    const double TL1 = 1.0;   // local filter final \"temperature\"\n\n    while (true) {\n        double elapsed = chrono::duration<double>(chrono::steady_clock::now() - timeStart).count();\n        if (elapsed > GLOBAL_TIME_LIMIT) break;\n        double progress = elapsed / GLOBAL_TIME_LIMIT;\n        if (progress > 1.0) progress = 1.0;\n        double T = T0 + (T1 - T0) * progress;\n        double TL = TL0 + (TL1 - TL0) * progress;\n\n        bool multi = (rng() % 5 == 0); // about 20% multi-tile moves\n\n        if (!multi) {\n            // ---- Single-tile move ----\n            int idxCell;\n            if (!crossIdx.empty() && (rng() % 3 != 0)) {\n                idxCell = crossIdx[ (int)(rng() % crossIdx.size()) ];\n            } else {\n                idxCell = (int)(rng() % (N * M));\n            }\n            int i = idxCell / M;\n            int j = idxCell % M;\n\n            int oldRot = curRot[i][j];\n            int oldT = curTile[i][j];\n            int base = baseTile[i][j];\n\n            int newRot, newT;\n            // Propose a different effective tile type via rotation\n            do {\n                newRot = (int)(rng() & 3ULL);  // 0..3\n                newT = rotTable[base][newRot];\n            } while (newT == oldT);\n\n            int localDelta = deltaLocalScoreTile(i, j, oldT, newT);\n\n            // Local pre-filter: skip strongly bad local moves with high probability\n            bool evaluate = false;\n            if (localDelta >= 0) {\n                evaluate = true;\n            } else {\n                double pLocal = exp((double)localDelta / TL); // localDelta <= -1\n                if (randDouble() < pLocal) evaluate = true;\n            }\n            if (!evaluate) continue;\n\n            // Apply tentative move\n            curRot[i][j] = newRot;\n            curTile[i][j] = newT;\n            updateTransitionsForTile(i, j);\n\n            int newScore = computeTrueScore();\n            int diff = newScore - curScore;\n\n            bool accept = false;\n            if (diff >= 0) {\n                accept = true;\n            } else {\n                double prob = exp((double)diff / T);\n                if (randDouble() < prob) accept = true;\n            }\n\n            if (accept) {\n                curScore = newScore;\n                if (newScore > bestScore) {\n                    bestScore = newScore;\n                    for (int x = 0; x < N; ++x)\n                        for (int y = 0; y < M; ++y)\n                            bestRot[x][y] = curRot[x][y];\n                }\n            } else {\n                // Revert move\n                curRot[i][j] = oldRot;\n                curTile[i][j] = oldT;\n                updateTransitionsForTile(i, j);\n            }\n        } else {\n            // ---- Multi-tile move (2 tiles) ----\n            const int K = 2;\n            TileChange ch[K];\n\n            // Select K distinct tiles (biased to cross tiles)\n            int chosenIdx[K];\n            for (int k = 0; k < K; ++k) {\n                int idxCell;\n                while (true) {\n                    if (!crossIdx.empty() && (rng() % 3 != 0)) {\n                        idxCell = crossIdx[ (int)(rng() % crossIdx.size()) ];\n                    } else {\n                        idxCell = (int)(rng() % (N * M));\n                    }\n                    bool ok = true;\n                    for (int t = 0; t < k; ++t)\n                        if (idxCell == chosenIdx[t]) { ok = false; break; }\n                    if (ok) break;\n                }\n                chosenIdx[k] = idxCell;\n                int i = idxCell / M;\n                int j = idxCell % M;\n                ch[k].i = i;\n                ch[k].j = j;\n                ch[k].oldRot = curRot[i][j];\n                ch[k].oldT   = curTile[i][j];\n            }\n\n            int totalLocalDelta = 0;\n            bool anyChange = false;\n\n            // Propose new rotations and compute approximate local delta\n            for (int k = 0; k < K; ++k) {\n                int i = ch[k].i;\n                int j = ch[k].j;\n                int base = baseTile[i][j];\n                int newRot, newT;\n                int oldT = ch[k].oldT;\n\n                int tries = 0;\n                do {\n                    newRot = (int)(rng() & 3ULL);\n                    newT = rotTable[base][newRot];\n                    ++tries;\n                    if (tries > 8) break;\n                } while (newT == oldT);\n\n                if (newT == oldT) {\n                    // Fallback: skip this multi-move entirely\n                    anyChange = false;\n                    break;\n                }\n\n                ch[k].newRot = newRot;\n                ch[k].newT   = newT;\n                anyChange = true;\n\n                int ld = deltaLocalScoreTile(i, j, oldT, newT);\n                totalLocalDelta += ld;\n            }\n\n            if (!anyChange) continue;\n\n            // Local filter for multi-move\n            bool evaluate = false;\n            if (totalLocalDelta >= 0) {\n                evaluate = true;\n            } else {\n                double pLocal = exp((double)totalLocalDelta / TL);\n                if (randDouble() < pLocal) evaluate = true;\n            }\n            if (!evaluate) continue;\n\n            // Apply tentative multi-move\n            for (int k = 0; k < K; ++k) {\n                int i = ch[k].i;\n                int j = ch[k].j;\n                curRot[i][j] = ch[k].newRot;\n                curTile[i][j] = ch[k].newT;\n                updateTransitionsForTile(i, j);\n            }\n\n            int newScore = computeTrueScore();\n            int diff = newScore - curScore;\n\n            bool accept = false;\n            if (diff >= 0) {\n                accept = true;\n            } else {\n                double prob = exp((double)diff / T);\n                if (randDouble() < prob) accept = true;\n            }\n\n            if (accept) {\n                curScore = newScore;\n                if (newScore > bestScore) {\n                    bestScore = newScore;\n                    for (int x = 0; x < N; ++x)\n                        for (int y = 0; y < M; ++y)\n                            bestRot[x][y] = curRot[x][y];\n                }\n            } else {\n                // Revert multi-move\n                for (int k = 0; k < K; ++k) {\n                    int i = ch[k].i;\n                    int j = ch[k].j;\n                    curRot[i][j] = ch[k].oldRot;\n                    curTile[i][j] = ch[k].oldT;\n                    updateTransitionsForTile(i, j);\n                }\n            }\n        }\n    }\n\n    // ===== Output best rotations =====\n    string out;\n    out.reserve(N * M);\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < M; ++j) {\n            int r = bestRot[i][j] & 3;\n            out.push_back(char('0' + r));\n        }\n    }\n    cout << out << '\\n';\n\n    return 0;\n}","ahc011":"#include <bits/stdc++.h>\nusing namespace std;\n\n// ====== Global constants and types ======\n\nstatic const int MAXN = 10;\n\nint N, T;\n\n// Board representation\nstruct Board {\n    unsigned char a[MAXN][MAXN];\n};\n\n// Directions for graph connectivity (Up, Right, Down, Left)\nconst int DX[4]   = {-1, 0, 1, 0};\nconst int DY[4]   = { 0, 1, 0,-1};\n// Bit masks corresponding to U,R,D,L in that order\nconst int MASK[4] = {2, 4, 8, 1};\n// Opposite directions\nconst int OPP[4]  = {2, 3, 0, 1};\n\nstruct EvalRes {\n    int bestTree;    // size of largest tree component\n    int bestConn;    // size of largest connected component\n    int totalTree;   // sum of sizes of all tree components\n};\n\n// ====== Evaluation of a board configuration ======\n\nEvalRes evaluate(const Board &B) {\n    static bool vis[MAXN][MAXN];\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            vis[i][j] = false;\n\n    int bestTree = 0;\n    int bestConn = 0;\n    int totalTree = 0;\n\n    int qx[MAXN * MAXN];\n    int qy[MAXN * MAXN];\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (B.a[i][j] == 0 || vis[i][j]) continue;\n\n            int v = 0; // vertices in this component\n            int e = 0; // edges in this component\n\n            int head = 0, tail = 0;\n            vis[i][j] = true;\n            qx[tail] = i;\n            qy[tail] = j;\n            ++tail;\n\n            while (head < tail) {\n                int x = qx[head];\n                int y = qy[head];\n                ++head;\n\n                ++v;\n                unsigned char tile = B.a[x][y];\n\n                for (int dir = 0; dir < 4; ++dir) {\n                    if (!(tile & MASK[dir])) continue;\n                    int nx = x + DX[dir];\n                    int ny = y + DY[dir];\n                    if (nx < 0 || nx >= N || ny < 0 || ny >= N) continue;\n                    unsigned char nt = B.a[nx][ny];\n                    if (nt == 0) continue;\n                    if (!(nt & MASK[OPP[dir]])) continue;\n\n                    if (!vis[nx][ny]) {\n                        vis[nx][ny] = true;\n                        qx[tail] = nx;\n                        qy[tail] = ny;\n                        ++tail;\n                    }\n                    // count each undirected edge once\n                    if (x < nx || (x == nx && y < ny)) {\n                        ++e;\n                    }\n                }\n            }\n\n            bestConn = max(bestConn, v);\n            if (e == v - 1) {\n                bestTree = max(bestTree, v);\n                totalTree += v;\n            }\n        }\n    }\n\n    return {bestTree, bestConn, totalTree};\n}\n\n// Convert EvalRes to a scalar score (lexicographic: bestTree > totalTree > bestConn)\ninline long long evalScore(const EvalRes &er) {\n    // N <= 10, sizes <= 99, so these weights keep lexicographic priority.\n    return (long long)er.bestTree * 1000000LL\n         + (long long)er.totalTree * 1000LL\n         + (long long)er.bestConn;\n}\n\n// Comparison of two EvalRes according to the same lexicographic priority\ninline bool betterEval(const EvalRes &a, const EvalRes &b) {\n    if (a.bestTree != b.bestTree) return a.bestTree > b.bestTree;\n    if (a.totalTree != b.totalTree) return a.totalTree > b.totalTree;\n    if (a.bestConn != b.bestConn) return a.bestConn > b.bestConn;\n    return false;\n}\n\n// ====== Sliding puzzle mechanics ======\n\ninline bool legalMove(int r, int c, char mv) {\n    if (mv == 'U') return r > 0;\n    if (mv == 'D') return r + 1 < N;\n    if (mv == 'L') return c > 0;\n    if (mv == 'R') return c + 1 < N;\n    return false;\n}\n\n// Apply move to board and blank position\ninline void applyMove(Board &B, int &r, int &c, char mv) {\n    if (mv == 'U') {\n        swap(B.a[r][c], B.a[r-1][c]);\n        --r;\n    } else if (mv == 'D') {\n        swap(B.a[r][c], B.a[r+1][c]);\n        ++r;\n    } else if (mv == 'L') {\n        swap(B.a[r][c], B.a[r][c-1]);\n        --c;\n    } else if (mv == 'R') {\n        swap(B.a[r][c], B.a[r][c+1]);\n        ++c;\n    }\n}\n\n// Opposite sliding move\ninline char oppositeMove(char mv) {\n    if (mv == 'U') return 'D';\n    if (mv == 'D') return 'U';\n    if (mv == 'L') return 'R';\n    if (mv == 'R') return 'L';\n    return '?';\n}\n\n// ====== Time control ======\n\nusing Clock = chrono::steady_clock;\ninline double nowSec(const Clock::time_point &start) {\n    return chrono::duration<double>(Clock::now() - start).count();\n}\n\n// ====== Depth-limited DFS for lookahead scoring ======\n\nint LOOKAHEAD_DEPTH; // decided from N in main\n\n// Depth-limited DFS to find best reachable score within given depth\n// starting from board B and blank position (br, bc).\n// lastMove: last move applied to reach this state (to avoid immediate reverse),\n// depth: remaining depth to explore (0 means just evaluate this state).\nlong long dfsScore(const Board &B, int br, int bc, char lastMove, int depth) {\n    EvalRes er = evaluate(B);\n    long long best = evalScore(er);\n    if (depth == 0) return best;\n\n    static const char allMoves[4] = {'U', 'D', 'L', 'R'};\n    char cand[4];\n    int cnt = 0;\n    for (int k = 0; k < 4; ++k) {\n        char mv = allMoves[k];\n        if (!legalMove(br, bc, mv)) continue;\n        if (lastMove != '?' && mv == oppositeMove(lastMove)) continue;\n        cand[cnt++] = mv;\n    }\n\n    for (int i = 0; i < cnt; ++i) {\n        char mv = cand[i];\n        Board nb = B;\n        int nbr = br, nbc = bc;\n        applyMove(nb, nbr, nbc, mv);\n        long long sc = dfsScore(nb, nbr, nbc, mv, depth - 1);\n        if (sc > best) best = sc;\n    }\n    return best;\n}\n\n// ====== Main heuristic: multi-start greedy with lookahead ======\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    if (!(cin >> N >> T)) {\n        return 0;\n    }\n\n    Board initialBoard;\n    int initialBlankR = -1, initialBlankC = -1;\n\n    for (int i = 0; i < N; ++i) {\n        string row;\n        cin >> row;\n        for (int j = 0; j < N; ++j) {\n            char ch = row[j];\n            int val;\n            if ('0' <= ch && ch <= '9') val = ch - '0';\n            else val = ch - 'a' + 10;\n            initialBoard.a[i][j] = static_cast<unsigned char>(val);\n            if (val == 0) {\n                initialBlankR = i;\n                initialBlankC = j;\n            }\n        }\n    }\n\n    // Decide lookahead depth depending on N.\n    // Deeper for smaller boards, shallower for largest boards to keep time.\n    if (N <= 7) LOOKAHEAD_DEPTH = 4;\n    else LOOKAHEAD_DEPTH = 3;\n\n    // RNG for tie-breaking\n    mt19937_64 rng(\n        (uint64_t)chrono::high_resolution_clock::now().time_since_epoch().count()\n    );\n\n    auto startTime = Clock::now();\n    const double TIME_LIMIT = 2.8; // seconds, safety margin under 3.0\n\n    EvalRes initialEval = evaluate(initialBoard);\n    int totalTiles = N * N - 1;\n\n    // If initial board is already a full tree, output empty sequence.\n    if (initialEval.bestTree == totalTiles) {\n        cout << \"\\n\";\n        return 0;\n    }\n\n    EvalRes bestOverallEval = initialEval;\n    string bestOverallOps;\n    int bestOverallStep = 0;\n\n    static const char allMoves[4] = {'U', 'D', 'L', 'R'};\n    const int MAX_RUNS = 100; // upper bound; actual runs limited by TIME_LIMIT\n\n    for (int run = 0; run < MAX_RUNS && nowSec(startTime) < TIME_LIMIT; ++run) {\n        Board board = initialBoard;\n        int blankR = initialBlankR;\n        int blankC = initialBlankC;\n\n        string ops;\n        ops.reserve(T);\n\n        EvalRes bestRunEval = initialEval;\n        int bestRunStep = 0;\n        char lastMove = '?';\n\n        for (int step = 0; step < T; ++step) {\n            if (nowSec(startTime) >= TIME_LIMIT) break;\n\n            // Build candidate first moves, avoiding immediate reverse if possible.\n            char cand1[4];\n            int cand1cnt = 0;\n            for (int k = 0; k < 4; ++k) {\n                char mv = allMoves[k];\n                if (!legalMove(blankR, blankC, mv)) continue;\n                if (step > 0 && mv == oppositeMove(lastMove)) continue;\n                cand1[cand1cnt++] = mv;\n            }\n            if (cand1cnt == 0) {\n                // All legal moves are reverse of last; allow them.\n                for (int k = 0; k < 4; ++k) {\n                    char mv = allMoves[k];\n                    if (legalMove(blankR, blankC, mv)) {\n                        cand1[cand1cnt++] = mv;\n                    }\n                }\n                if (cand1cnt == 0) break; // no legal moves (shouldn't happen)\n            }\n\n            long long bestScoreStep = LLONG_MIN;\n            char chosenMove = cand1[0];\n            int tieCount = 0;\n\n            // For each candidate first move, perform depth-limited search.\n            for (int idx = 0; idx < cand1cnt; ++idx) {\n                char d1 = cand1[idx];\n\n                Board b1 = board;\n                int br1 = blankR, bc1 = blankC;\n                applyMove(b1, br1, bc1, d1);\n\n                // We already performed one move (d1); explore up to LOOKAHEAD_DEPTH-1 more.\n                long long sc = dfsScore(b1, br1, bc1, d1, LOOKAHEAD_DEPTH - 1);\n\n                if (sc > bestScoreStep) {\n                    bestScoreStep = sc;\n                    chosenMove = d1;\n                    tieCount = 1;\n                } else if (sc == bestScoreStep) {\n                    ++tieCount;\n                    if (rng() % tieCount == 0) {\n                        chosenMove = d1;\n                    }\n                }\n            }\n\n            // Commit chosen move\n            applyMove(board, blankR, blankC, chosenMove);\n            ops.push_back(chosenMove);\n            lastMove = chosenMove;\n\n            // Evaluate current board and update run-best prefix\n            EvalRes curEval = evaluate(board);\n            if (betterEval(curEval, bestRunEval)) {\n                bestRunEval = curEval;\n                bestRunStep = (int)ops.size();\n                if (bestRunEval.bestTree == totalTiles) {\n                    // Found a full tree; no need to continue this run.\n                    break;\n                }\n            }\n        }\n\n        // Update global best over all runs\n        if (betterEval(bestRunEval, bestOverallEval)) {\n            bestOverallEval = bestRunEval;\n            bestOverallStep = bestRunStep;\n            bestOverallOps = ops.substr(0, bestRunStep);\n            if (bestOverallEval.bestTree == totalTiles) {\n                // Reached optimal S; further improvements only affect K,\n                // but when S < N^2-1 score ignores K, so we can stop.\n                break;\n            }\n        }\n    }\n\n    if (bestOverallStep == 0) {\n        // best is initial board\n        cout << \"\\n\";\n    } else {\n        cout << bestOverallOps << \"\\n\";\n    }\n\n    return 0;\n}","ahc012":"#include <bits/stdc++.h>\nusing namespace std;\n\n// Constants\nstatic const int RADIUS = 10000;   // radius of the cake\nstatic const int BIG    = 100000;  // endpoints for axis-aligned lines\n\n// Pattern of regions: up to 128 bits (we only need <= 100)\nstruct Pattern {\n    uint64_t lo, hi;\n    bool operator==(const Pattern& o) const noexcept {\n        return lo == o.lo && hi == o.hi;\n    }\n};\nstruct PatternHash {\n    size_t operator()(const Pattern& p) const noexcept {\n        uint64_t x = p.lo * 0x9E3779B97F4A7C15ULL;\n        x ^= p.hi + 0x9E3779B97F4A7C15ULL + (x << 6) + (x >> 2);\n        return static_cast<size_t>(x);\n    }\n};\n\n// Line in Ax + By + C = 0 form, plus integer endpoints to output\nstruct Line {\n    long long A, B, C;\n    int px, py, qx, qy;\n};\n\n// Build quantile-based cut positions along one axis.\n//\n// Npoints: number of strawberries\n// Nc: desired number of cuts along this axis\n// sortedCoord: sorted coordinates (x or y) of all strawberries (size Npoints)\n// boundaryCoord: precomputed boundary coordinate for each boundary index 0..Npoints\n// boundaryValid: whether boundary 0..Npoints can be used without hitting any strawberry\n//\n// If we can't pick Nc valid boundaries, we fall back to uniform spacing.\nvector<int> build_quantile_cuts(\n    int Npoints,\n    int Nc,\n    const vector<int> &sortedCoord,\n    const vector<int> &boundaryCoord,\n    const vector<char> &boundaryValid\n) {\n    vector<int> cuts;\n    if (Nc <= 0) return cuts;\n\n    int validCount = 0;\n    for (int b = 0; b <= Npoints; ++b) {\n        if (boundaryValid[b]) ++validCount;\n    }\n\n    if (validCount <= Nc) {\n        // Fallback: uniform spacing in [-RADIUS, RADIUS]\n        cuts.reserve(Nc);\n        for (int i = 1; i <= Nc; ++i) {\n            long long num = 2LL * RADIUS * i;\n            int c = -RADIUS + (int)(num / (Nc + 1)); // floor\n            cuts.push_back(c);\n        }\n        return cuts;\n    }\n\n    cuts.reserve(Nc);\n    int prevB = -1;\n    bool success = true;\n    for (int i = 1; i <= Nc; ++i) {\n        long long target = 1LL * i * Npoints / (Nc + 1); // in [0, Npoints]\n        int bestB = -1;\n        long long bestDist = (1LL << 60);\n\n        // Choose next valid boundary index b > prevB minimizing |b - target|\n        for (int b = prevB + 1; b <= Npoints; ++b) {\n            if (!boundaryValid[b]) continue;\n            long long dist = llabs((long long)b - target);\n            if (dist < bestDist) {\n                bestDist = dist;\n                bestB = b;\n            }\n        }\n        if (bestB == -1) {\n            success = false;\n            break;\n        }\n        prevB = bestB;\n        cuts.push_back(boundaryCoord[bestB]);\n    }\n\n    if (!success || (int)cuts.size() != Nc) {\n        // Fallback: uniform spacing\n        cuts.clear();\n        cuts.reserve(Nc);\n        for (int i = 1; i <= Nc; ++i) {\n            long long num = 2LL * RADIUS * i;\n            int c = -RADIUS + (int)(num / (Nc + 1)); // floor\n            cuts.push_back(c);\n        }\n    }\n\n    return cuts;\n}\n\n// Compute current score (sum_d min(a_d, b_d)) for given patterns and lines.\nlong long compute_score_current(\n    const vector<uint64_t> &patLo,\n    const vector<uint64_t> &patHi,\n    int Lcur,\n    const vector<int> &a,\n    unordered_map<Pattern,int,PatternHash> &mp\n) {\n    int N = (int)patLo.size();\n    mp.clear();\n\n    if (Lcur == 0) {\n        int s = N;\n        int B[11];\n        memset(B, 0, sizeof(B));\n        if (1 <= s && s <= 10) B[s] = 1;\n        long long score = 0;\n        for (int d = 1; d <= 10; ++d) {\n            score += min((long long)a[d], (long long)B[d]);\n        }\n        return score;\n    }\n\n    mp.reserve(N * 2);\n    for (int i = 0; i < N; ++i) {\n        Pattern key{patLo[i], patHi[i]};\n        mp[key] += 1;\n    }\n\n    int B[11];\n    memset(B, 0, sizeof(B));\n    for (auto &kv : mp) {\n        int s = kv.second;\n        if (1 <= s && s <= 10) B[s] += 1;\n    }\n\n    long long score = 0;\n    for (int d = 1; d <= 10; ++d) {\n        score += min((long long)a[d], (long long)B[d]);\n    }\n    return score;\n}\n\n// Evaluate candidate line appended to current lines (patterns).\n// Returns score, or -1 if invalid (passes any strawberry center).\nlong long evaluate_candidate(\n    const Line &cand,\n    const vector<uint64_t> &patLo,\n    const vector<uint64_t> &patHi,\n    int Lcur,\n    const vector<pair<int,int>> &pts,\n    const vector<int> &a,\n    unordered_map<Pattern,int,PatternHash> &mp\n) {\n    int N = (int)pts.size();\n    mp.clear();\n    mp.reserve(N * 2);\n\n    bool invalid = false;\n\n    for (int i = 0; i < N; ++i) {\n        long long x = pts[i].first;\n        long long y = pts[i].second;\n        long long val = cand.A * x + cand.B * y + cand.C;\n        if (val == 0) {\n            invalid = true;\n            break;\n        }\n        Pattern key{patLo[i], patHi[i]};\n        if (val > 0) {\n            int bitpos = Lcur;\n            if (bitpos < 64) {\n                key.lo |= (1ULL << bitpos);\n            } else {\n                key.hi |= (1ULL << (bitpos - 64));\n            }\n        }\n        mp[key] += 1;\n    }\n\n    if (invalid) return -1;\n\n    int B[11];\n    memset(B, 0, sizeof(B));\n    for (auto &kv : mp) {\n        int s = kv.second;\n        if (1 <= s && s <= 10) B[s] += 1;\n    }\n\n    long long score = 0;\n    for (int d = 1; d <= 10; ++d) {\n        score += min((long long)a[d], (long long)B[d]);\n    }\n    return score;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, K;\n    if (!(cin >> N >> K)) return 0;\n    vector<int> a(11);\n    long long sumA = 0;\n    for (int d = 1; d <= 10; ++d) {\n        cin >> a[d];\n        sumA += a[d];\n    }\n    vector<pair<int,int>> pts(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> pts[i].first >> pts[i].second;\n    }\n\n    if (sumA == 0 || K == 0) {\n        cout << 0 << '\\n';\n        return 0;\n    }\n\n    // Average desired piece size\n    double avgD = (double)N / (double)sumA;\n\n    // Poisson fit on attendee-years distribution to tune lambda\n    vector<double> w(11, 0.0);\n    for (int d = 1; d <= 10; ++d) {\n        w[d] = (double)a[d] / (double)sumA;\n    }\n    double bestLambda = avgD;\n    double bestErr = 1e100;\n\n    for (double lambda = 1.0; lambda <= 8.0001; lambda += 0.1) {\n        double P[11];\n        P[0] = exp(-lambda);\n        double sum1to10 = 0.0;\n        for (int k = 1; k <= 10; ++k) {\n            P[k] = P[k-1] * lambda / k;\n            sum1to10 += P[k];\n        }\n        if (sum1to10 <= 0.0) continue;\n        double err = 0.0;\n        for (int d = 1; d <= 10; ++d) {\n            double q = P[d] / sum1to10;\n            double diff = q - w[d];\n            err += diff * diff;\n        }\n        if (err < bestErr) {\n            bestErr = err;\n            bestLambda = lambda;\n        }\n    }\n\n    double lambdaTarget = 0.5 * avgD + 0.5 * bestLambda;\n    lambdaTarget = max(2.0, min(8.0, lambdaTarget));\n\n    int cellsTarget = (int)llround((double)N / lambdaTarget);\n    if (cellsTarget < 1) cellsTarget = 1;\n\n    // Reserve some cuts for greedy improvement\n    int Kextra = min(30, K / 2);   // up to 30 greedy cuts\n    if (Kextra < 0) Kextra = 0;\n    if (Kextra > K) Kextra = K;\n    int KgridLimit = max(0, K - Kextra);\n\n    // Determine grid sizes Nx, Ny with Nx + Ny <= KgridLimit\n    int bestNx = 0, bestNy = 0;\n    if (KgridLimit > 0) {\n        long long maxCellsPossible = 0;\n        for (int Nx = 0; Nx <= KgridLimit; ++Nx) {\n            int Ny = KgridLimit - Nx;\n            long long cells = 1LL * (Nx + 1) * (Ny + 1);\n            if (cells > maxCellsPossible) maxCellsPossible = cells;\n        }\n        if (cellsTarget > (int)maxCellsPossible) cellsTarget = (int)maxCellsPossible;\n\n        long long bestCellErr = (1LL << 60);\n        int bestSquarePenalty = (1 << 30);\n        for (int Nx = 0; Nx <= KgridLimit; ++Nx) {\n            for (int Ny = 0; Ny <= KgridLimit - Nx; ++Ny) {\n                long long cells = 1LL * (Nx + 1) * (Ny + 1);\n                long long err = llabs(cells - (long long)cellsTarget);\n                int squarePenalty = abs(Nx - Ny);\n                if (err < bestCellErr ||\n                    (err == bestCellErr && squarePenalty < bestSquarePenalty)) {\n                    bestCellErr = err;\n                    bestSquarePenalty = squarePenalty;\n                    bestNx = Nx;\n                    bestNy = Ny;\n                }\n            }\n        }\n    } else {\n        bestNx = bestNy = 0;\n    }\n\n    int Nx = bestNx;\n    int Ny = bestNy;\n\n    // Sorted coordinates for boundaries\n    vector<int> xs(N), ys(N);\n    for (int i = 0; i < N; ++i) {\n        xs[i] = pts[i].first;\n        ys[i] = pts[i].second;\n    }\n    sort(xs.begin(), xs.end());\n    sort(ys.begin(), ys.end());\n\n    // Build X boundaries\n    vector<int> xBoundaryCoord(N + 1);\n    vector<char> xBoundaryValid(N + 1, 0);\n    if (N > 0) {\n        int c0 = xs[0] - 1;\n        if (c0 < -RADIUS) c0 = -RADIUS;\n        xBoundaryCoord[0] = c0;\n        xBoundaryValid[0] = 1;\n\n        for (int b = 1; b <= N - 1; ++b) {\n            int left = xs[b-1];\n            int right = xs[b];\n            if (right - left >= 2) {\n                int c = (left + right) / 2;\n                xBoundaryCoord[b] = c;\n                xBoundaryValid[b] = 1;\n            } else {\n                xBoundaryValid[b] = 0;\n            }\n        }\n\n        int cN = xs[N-1] + 1;\n        if (cN > RADIUS) cN = RADIUS;\n        xBoundaryCoord[N] = cN;\n        xBoundaryValid[N] = 1;\n    }\n\n    // Build Y boundaries\n    vector<int> yBoundaryCoord(N + 1);\n    vector<char> yBoundaryValid(N + 1, 0);\n    if (N > 0) {\n        int c0 = ys[0] - 1;\n        if (c0 < -RADIUS) c0 = -RADIUS;\n        yBoundaryCoord[0] = c0;\n        yBoundaryValid[0] = 1;\n\n        for (int b = 1; b <= N - 1; ++b) {\n            int down = ys[b-1];\n            int up   = ys[b];\n            if (up - down >= 2) {\n                int c = (down + up) / 2;\n                yBoundaryCoord[b] = c;\n                yBoundaryValid[b] = 1;\n            } else {\n                yBoundaryValid[b] = 0;\n            }\n        }\n\n        int cN = ys[N-1] + 1;\n        if (cN > RADIUS) cN = RADIUS;\n        yBoundaryCoord[N] = cN;\n        yBoundaryValid[N] = 1;\n    }\n\n    // Quantile-based vertical and horizontal cuts\n    vector<int> xCuts = build_quantile_cuts(N, Nx, xs, xBoundaryCoord, xBoundaryValid);\n    vector<int> yCuts = build_quantile_cuts(N, Ny, ys, yBoundaryCoord, yBoundaryValid);\n\n    // Build initial line set (grid lines)\n    vector<Line> lines;\n    lines.reserve(K);\n    // vertical lines\n    for (int c : xCuts) {\n        Line L;\n        L.A = 1; L.B = 0; L.C = -c;\n        L.px = c; L.py = -BIG;\n        L.qx = c; L.qy =  BIG;\n        lines.push_back(L);\n    }\n    // horizontal lines\n    for (int c : yCuts) {\n        Line L;\n        L.A = 0; L.B = 1; L.C = -c;\n        L.px = -BIG; L.py = c;\n        L.qx =  BIG; L.qy = c;\n        lines.push_back(L);\n    }\n\n    int Lcur = (int)lines.size();\n\n    // Patterns for each strawberry\n    vector<uint64_t> patLo(N, 0), patHi(N, 0);\n    for (int i = 0; i < Lcur; ++i) {\n        const Line &L = lines[i];\n        for (int j = 0; j < N; ++j) {\n            long long x = pts[j].first;\n            long long y = pts[j].second;\n            long long val = L.A * x + L.B * y + L.C;\n            bool side = (val > 0);\n            if (side) {\n                int bitpos = i;\n                if (bitpos < 64) {\n                    patLo[j] |= (1ULL << bitpos);\n                } else {\n                    patHi[j] |= (1ULL << (bitpos - 64));\n                }\n            }\n        }\n    }\n\n    unordered_map<Pattern,int,PatternHash> mpCur, mpCand;\n    mpCur.reserve(N * 2);\n    mpCand.reserve(N * 2);\n\n    long long currentScore = compute_score_current(patLo, patHi, Lcur, a, mpCur);\n\n    // Random engine\n    uint64_t seed = 123456789ULL ^ (uint64_t)N;\n    if (N > 0) {\n        seed ^= (uint64_t)(pts[0].first * 1000003LL) ^ (uint64_t)(pts[0].second * 10007LL);\n    }\n    mt19937_64 rng(seed);\n    uniform_int_distribution<int> coordDist(-RADIUS, RADIUS);\n\n    const pair<int,int> offsets[8] = {\n        {1,0},{-1,0},{0,1},{0,-1},\n        {1,1},{-1,1},{1,-1},{-1,-1}\n    };\n\n    int usedExtra = 0;\n    const int CANDIDATES_PER_STEP = 30;  // evaluated per iteration\n    const int TRY_LIMIT_MULT = 5;        // tries up to CANDIDATES_PER_STEP * this\n\n    while (usedExtra < Kextra) {\n        // Recompute region partition for current lines\n        currentScore = compute_score_current(patLo, patHi, Lcur, a, mpCur);\n\n        // Collect large regions (patterns with many strawberries)\n        vector<pair<int,Pattern>> regions;\n        regions.reserve(mpCur.size());\n        for (auto &kv : mpCur) {\n            regions.emplace_back(kv.second, kv.first);\n        }\n        sort(regions.begin(), regions.end(),\n            [](const pair<int,Pattern> &x, const pair<int,Pattern> &y) {\n                return x.first > y.first;\n            });\n\n        const int MAX_BIG = 6;\n        const int MIN_BIG_SIZE = 8;\n        vector<Pattern> bigPatterns;\n        vector<vector<int>> bigIndices;\n        bigPatterns.reserve(MAX_BIG);\n        bigIndices.reserve(MAX_BIG);\n\n        for (int i = 0; i < (int)regions.size() && (int)bigPatterns.size() < MAX_BIG; ++i) {\n            int cnt = regions[i].first;\n            if (cnt < MIN_BIG_SIZE) break;\n            Pattern pat = regions[i].second;\n            bigPatterns.push_back(pat);\n        }\n\n        if (!bigPatterns.empty()) {\n            bigIndices.resize(bigPatterns.size());\n            for (int i = 0; i < N; ++i) {\n                Pattern p{patLo[i], patHi[i]};\n                for (int k = 0; k < (int)bigPatterns.size(); ++k) {\n                    if (p.lo == bigPatterns[k].lo && p.hi == bigPatterns[k].hi) {\n                        bigIndices[k].push_back(i);\n                        break;\n                    }\n                }\n            }\n        }\n\n        long long bestScoreIter = currentScore;\n        Line bestLine;\n        bool improved = false;\n\n        int validCandidates = 0;\n        int tries = 0;\n        int TRY_LIMIT = CANDIDATES_PER_STEP * TRY_LIMIT_MULT;\n\n        // Precompute cluster sizes for weighted choice\n        vector<int> clusterSizes;\n        int totalClusterSize = 0;\n        if (!bigIndices.empty()) {\n            clusterSizes.resize(bigIndices.size());\n            for (int k = 0; k < (int)bigIndices.size(); ++k) {\n                clusterSizes[k] = (int)bigIndices[k].size();\n                totalClusterSize += clusterSizes[k];\n            }\n        }\n\n        while (validCandidates < CANDIDATES_PER_STEP && tries < TRY_LIMIT) {\n            ++tries;\n            Line cand;\n            bool useCluster = (!bigIndices.empty() && (rng() % 3 != 0)); // ~2/3 cluster-based\n\n            if (useCluster) {\n                // Choose cluster weighted by size\n                if (totalClusterSize < 2) {\n                    useCluster = false;\n                } else {\n                    int r = (int)(rng() % totalClusterSize);\n                    int cid = 0;\n                    while (cid < (int)clusterSizes.size() && r >= clusterSizes[cid]) {\n                        r -= clusterSizes[cid];\n                        ++cid;\n                    }\n                    if (cid >= (int)bigIndices.size() || bigIndices[cid].size() < 2) {\n                        useCluster = false;\n                    } else {\n                        const vector<int> &idxs = bigIndices[cid];\n                        int sz = (int)idxs.size();\n                        int i1 = rng() % sz;\n                        int i2 = rng() % (sz - 1);\n                        if (i2 >= i1) ++i2;\n                        int pIdx = idxs[i1];\n                        int qIdx = idxs[i2];\n                        int x1 = pts[pIdx].first;\n                        int y1 = pts[pIdx].second;\n                        int x2 = pts[qIdx].first;\n                        int y2 = pts[qIdx].second;\n                        auto off = offsets[rng() & 7];\n                        int ox = off.first;\n                        int oy = off.second;\n                        cand.px = x1 + ox;\n                        cand.py = y1 + oy;\n                        cand.qx = x2 + ox;\n                        cand.qy = y2 + oy;\n                        if (cand.px == cand.qx && cand.py == cand.qy) {\n                            // degenerate, fall back to global\n                            useCluster = false;\n                        } else {\n                            long long X1 = cand.px, Y1 = cand.py;\n                            long long X2 = cand.qx, Y2 = cand.qy;\n                            cand.A = Y2 - Y1;\n                            cand.B = X1 - X2;\n                            cand.C = X2 * Y1 - X1 * Y2;\n                        }\n                    }\n                }\n            }\n\n            if (!useCluster) {\n                // Global random line\n                do {\n                    cand.px = coordDist(rng);\n                    cand.py = coordDist(rng);\n                    cand.qx = coordDist(rng);\n                    cand.qy = coordDist(rng);\n                } while (cand.px == cand.qx && cand.py == cand.qy);\n                long long x1 = cand.px, y1 = cand.py;\n                long long x2 = cand.qx, y2 = cand.qy;\n                cand.A = y2 - y1;\n                cand.B = x1 - x2;\n                cand.C = x2 * y1 - x1 * y2;\n                if (cand.A == 0 && cand.B == 0) continue;\n            }\n\n            long long candScore = evaluate_candidate(cand, patLo, patHi, Lcur, pts, a, mpCand);\n            if (candScore < 0) continue; // invalid (passes any strawberry)\n\n            ++validCandidates;\n            if (candScore > bestScoreIter) {\n                bestScoreIter = candScore;\n                bestLine = cand;\n                improved = true;\n            }\n        }\n\n        if (!improved) break;\n\n        // Commit best line\n        lines.push_back(bestLine);\n        int newIndex = Lcur;\n        ++Lcur;\n        ++usedExtra;\n\n        const Line &L = lines.back();\n        for (int j = 0; j < N; ++j) {\n            long long x = pts[j].first;\n            long long y = pts[j].second;\n            long long val = L.A * x + L.B * y + L.C;\n            // val == 0 should not happen (we avoided such lines in evaluate_candidate)\n            bool side = (val > 0);\n            if (side) {\n                if (newIndex < 64) {\n                    patLo[j] |= (1ULL << newIndex);\n                } else {\n                    patHi[j] |= (1ULL << (newIndex - 64));\n                }\n            }\n        }\n\n        currentScore = bestScoreIter;\n        if (Lcur >= K) break;\n    }\n\n    int totalCuts = (int)lines.size();\n    if (totalCuts > K) totalCuts = K;\n\n    cout << totalCuts << '\\n';\n    for (int i = 0; i < totalCuts; ++i) {\n        const Line &L = lines[i];\n        cout << L.px << ' ' << L.py << ' ' << L.qx << ' ' << L.qy << '\\n';\n    }\n\n    return 0;\n}","ahc014":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int MAXN = 65;  // N <= 61\n\nint N, M;\n\n// Board state\nstatic bool hasDot[MAXN][MAXN];      // [x][y]\nstatic bool horUsed[MAXN][MAXN];     // [y][x] edge from (x,y) to (x+1,y)\nstatic bool verUsed[MAXN][MAXN];     // [x][y] edge from (x,y) to (x,y+1)\nstatic bool diagUpUsed[MAXN][MAXN];  // [x][y] edge from (x,y) to (x+1,y+1)\nstatic bool diagDownUsed[MAXN][MAXN];// [x][y] edge from (x,y+1) to (x+1,y)\n\nstatic int rowPrefix[MAXN][MAXN+1];  // [y][i]: dots with x < i\nstatic int colPrefix[MAXN][MAXN+1];  // [x][i]: dots with y < i\nstatic int cellWeight[MAXN][MAXN];   // w(x,y)\n\nconstexpr uint8_t TYPE_AXIS = 0;\nconstexpr uint8_t TYPE_ROT  = 1;\n\n// Candidate rectangle\nstruct Candidate {\n    int weight;\n    uint8_t type;    // 0: axis-aligned, 1: rotated (45\u00b0 square)\n    uint8_t px, py;  // new dot position\n    uint8_t pad;     // padding/alignment\n    union {\n        struct { uint8_t xL, yB, xR, yT; } axis;\n        struct {\n            uint8_t vx[4];  // vertices in cyclic order (Up, Right, Down, Left)\n            uint8_t vy[4];\n        } rot;\n    } u;\n};\n\nbool operator<(const Candidate &a, const Candidate &b) {\n    // priority_queue is max-heap by default; larger weight first\n    return a.weight < b.weight;\n}\n\npriority_queue<Candidate> pq;\n\n// Move record\nstruct Move {\n    int x1, y1, x2, y2, x3, y3, x4, y4;\n};\n\n// Add a dot at (x,y): update hasDot and 1D prefix sums\ninline void addDot(int x, int y) {\n    if (hasDot[x][y]) return;\n    hasDot[x][y] = true;\n    for (int i = x + 1; i <= N; ++i) rowPrefix[y][i] += 1;\n    for (int i = y + 1; i <= N; ++i) colPrefix[x][i] += 1;\n}\n\n// Generate all axis-aligned rectangles where the newly added dot is a vertex\n// and exactly three corners have dots (so the fourth is a candidate new dot).\ninline void updateAxisForNewDot(int x, int y) {\n    for (int x2 = 0; x2 < N; ++x2) {\n        if (x2 == x) continue;\n        int xL = (x2 < x) ? x2 : x;\n        int xR = (x2 < x) ? x : x2;\n        for (int y2 = 0; y2 < N; ++y2) {\n            if (y2 == y) continue;\n            int yB = (y2 < y) ? y2 : y;\n            int yT = (y2 < y) ? y : y2;\n\n            bool BL = hasDot[xL][yB];\n            bool BR = hasDot[xR][yB];\n            bool TR = hasDot[xR][yT];\n            bool TL = hasDot[xL][yT];\n            int cnt = BL + BR + TR + TL;\n            if (cnt != 3) continue;\n\n            int px, py;\n            if (!BL) { px = xL; py = yB; }\n            else if (!BR) { px = xR; py = yB; }\n            else if (!TR) { px = xR; py = yT; }\n            else { px = xL; py = yT; }\n\n            Candidate c;\n            c.weight = cellWeight[px][py];\n            c.type   = TYPE_AXIS;\n            c.px = (uint8_t)px;\n            c.py = (uint8_t)py;\n            c.pad = 0;\n            c.u.axis.xL = (uint8_t)xL;\n            c.u.axis.yB = (uint8_t)yB;\n            c.u.axis.xR = (uint8_t)xR;\n            c.u.axis.yT = (uint8_t)yT;\n            pq.push(c);\n        }\n    }\n}\n\n// Generate rotated (45\u00b0) square rectangles for a newly added dot at (x,y).\n// We consider squares whose vertices are Up, Right, Down, Left around an\n// integer center, and treat (x,y) as each of these four roles in turn.\ninline void updateRotatedForNewDot(int x, int y) {\n    // Orientation 0: new dot is Up\n    {\n        // Up = (x, y)\n        for (int k = 1;; ++k) {\n            int rx = x + k;\n            int ry = y - k;\n            int dx = x;\n            int dy = y - 2 * k;\n            int lx = x - k;\n            int ly = y - k;\n            if (rx >= N || lx < 0 || dy < 0) break;\n\n            int vx[4] = {x, rx, dx, lx};\n            int vy[4] = {y, ry, dy, ly};\n            bool s[4];\n            s[0] = true; // new dot at Up\n            s[1] = hasDot[rx][ry];\n            s[2] = hasDot[dx][dy];\n            s[3] = hasDot[lx][ly];\n\n            int cnt = 0;\n            for (int i = 0; i < 4; ++i) cnt += s[i];\n            if (cnt != 3) continue;\n\n            int miss = -1;\n            for (int i = 0; i < 4; ++i) if (!s[i]) { miss = i; break; }\n            int px = vx[miss], py = vy[miss];\n\n            Candidate c;\n            c.weight = cellWeight[px][py];\n            c.type   = TYPE_ROT;\n            c.px = (uint8_t)px;\n            c.py = (uint8_t)py;\n            c.pad = 0;\n            for (int i = 0; i < 4; ++i) {\n                c.u.rot.vx[i] = (uint8_t)vx[i];\n                c.u.rot.vy[i] = (uint8_t)vy[i];\n            }\n            pq.push(c);\n        }\n    }\n    // Orientation 1: new dot is Right\n    {\n        // Right = (x, y)\n        for (int k = 1;; ++k) {\n            int ux = x - k;\n            int uy = y + k;\n            int dx = x - k;\n            int dy = y - k;\n            int lx = x - 2 * k;\n            int ly = y;\n            if (lx < 0 || ux < 0 || uy >= N || dy < 0) break;\n\n            int vx[4] = {ux, x, dx, lx};\n            int vy[4] = {uy, y, dy, ly};\n            bool s[4];\n            s[1] = true; // new dot at Right\n            s[0] = hasDot[ux][uy];\n            s[2] = hasDot[dx][dy];\n            s[3] = hasDot[lx][ly];\n\n            int cnt = 0;\n            for (int i = 0; i < 4; ++i) cnt += s[i];\n            if (cnt != 3) continue;\n\n            int miss = -1;\n            for (int i = 0; i < 4; ++i) if (!s[i]) { miss = i; break; }\n            int px = vx[miss], py = vy[miss];\n\n            Candidate c;\n            c.weight = cellWeight[px][py];\n            c.type   = TYPE_ROT;\n            c.px = (uint8_t)px;\n            c.py = (uint8_t)py;\n            c.pad = 0;\n            for (int i = 0; i < 4; ++i) {\n                c.u.rot.vx[i] = (uint8_t)vx[i];\n                c.u.rot.vy[i] = (uint8_t)vy[i];\n            }\n            pq.push(c);\n        }\n    }\n    // Orientation 2: new dot is Down\n    {\n        // Down = (x, y)\n        for (int k = 1;; ++k) {\n            int ux = x;\n            int uy = y + 2 * k;\n            int rx = x + k;\n            int ry = y + k;\n            int lx = x - k;\n            int ly = y + k;\n            if (uy >= N || rx >= N || lx < 0) break;\n\n            int vx[4] = {ux, rx, x, lx};\n            int vy[4] = {uy, ry, y, ly};\n            bool s[4];\n            s[2] = true; // new dot at Down\n            s[0] = hasDot[ux][uy];\n            s[1] = hasDot[rx][ry];\n            s[3] = hasDot[lx][ly];\n\n            int cnt = 0;\n            for (int i = 0; i < 4; ++i) cnt += s[i];\n            if (cnt != 3) continue;\n\n            int miss = -1;\n            for (int i = 0; i < 4; ++i) if (!s[i]) { miss = i; break; }\n            int px = vx[miss], py = vy[miss];\n\n            Candidate c;\n            c.weight = cellWeight[px][py];\n            c.type   = TYPE_ROT;\n            c.px = (uint8_t)px;\n            c.py = (uint8_t)py;\n            c.pad = 0;\n            for (int i = 0; i < 4; ++i) {\n                c.u.rot.vx[i] = (uint8_t)vx[i];\n                c.u.rot.vy[i] = (uint8_t)vy[i];\n            }\n            pq.push(c);\n        }\n    }\n    // Orientation 3: new dot is Left\n    {\n        // Left = (x, y)\n        for (int k = 1;; ++k) {\n            int ux = x + k;\n            int uy = y + k;\n            int rx = x + 2 * k;\n            int ry = y;\n            int dx = x + k;\n            int dy = y - k;\n            if (rx >= N || uy >= N || dy < 0) break;\n\n            int vx[4] = {ux, rx, dx, x};\n            int vy[4] = {uy, ry, dy, y};\n            bool s[4];\n            s[3] = true; // new dot at Left\n            s[0] = hasDot[ux][uy];\n            s[1] = hasDot[rx][ry];\n            s[2] = hasDot[dx][dy];\n\n            int cnt = 0;\n            for (int i = 0; i < 4; ++i) cnt += s[i];\n            if (cnt != 3) continue;\n\n            int miss = -1;\n            for (int i = 0; i < 4; ++i) if (!s[i]) { miss = i; break; }\n            int px = vx[miss], py = vy[miss];\n\n            Candidate c;\n            c.weight = cellWeight[px][py];\n            c.type   = TYPE_ROT;\n            c.px = (uint8_t)px;\n            c.py = (uint8_t)py;\n            c.pad = 0;\n            for (int i = 0; i < 4; ++i) {\n                c.u.rot.vx[i] = (uint8_t)vx[i];\n                c.u.rot.vy[i] = (uint8_t)vy[i];\n            }\n            pq.push(c);\n        }\n    }\n}\n\n// Validate an axis-aligned candidate rectangle\ninline bool validateAxis(const Candidate &c) {\n    int px = c.px, py = c.py;\n    if (hasDot[px][py]) return false;\n\n    const auto &ax = c.u.axis;\n    int xL = ax.xL, xR = ax.xR;\n    int yB = ax.yB, yT = ax.yT;\n\n    bool isCorner =\n        (px == xL && py == yB) ||\n        (px == xR && py == yB) ||\n        (px == xR && py == yT) ||\n        (px == xL && py == yT);\n    if (!isCorner) return false;\n\n    if (!(px == xL && py == yB) && !hasDot[xL][yB]) return false;\n    if (!(px == xR && py == yB) && !hasDot[xR][yB]) return false;\n    if (!(px == xR && py == yT) && !hasDot[xR][yT]) return false;\n    if (!(px == xL && py == yT) && !hasDot[xL][yT]) return false;\n\n    // No extra dots on perimeter interior (horizontal/vertical edges)\n    if (xR - xL > 1) {\n        int sumBottom = rowPrefix[yB][xR] - rowPrefix[yB][xL + 1];\n        if (sumBottom > 0) return false;\n        int sumTop = rowPrefix[yT][xR] - rowPrefix[yT][xL + 1];\n        if (sumTop > 0) return false;\n    }\n    if (yT - yB > 1) {\n        int sumLeft  = colPrefix[xL][yT] - colPrefix[xL][yB + 1];\n        if (sumLeft > 0) return false;\n        int sumRight = colPrefix[xR][yT] - colPrefix[xR][yB + 1];\n        if (sumRight > 0) return false;\n    }\n\n    // No edges already used\n    for (int x = xL; x < xR; ++x) {\n        if (horUsed[yB][x]) return false;\n        if (horUsed[yT][x]) return false;\n    }\n    for (int y = yB; y < yT; ++y) {\n        if (verUsed[xL][y]) return false;\n        if (verUsed[xR][y]) return false;\n    }\n\n    return true;\n}\n\n// Mark edges of an axis-aligned rectangle as used\ninline void markEdgesAxis(const Candidate &c) {\n    const auto &ax = c.u.axis;\n    int xL = ax.xL, xR = ax.xR;\n    int yB = ax.yB, yT = ax.yT;\n    for (int x = xL; x < xR; ++x) {\n        horUsed[yB][x] = true;\n        horUsed[yT][x] = true;\n    }\n    for (int y = yB; y < yT; ++y) {\n        verUsed[xL][y] = true;\n        verUsed[xR][y] = true;\n    }\n}\n\n// Validate a rotated (45\u00b0 square) candidate rectangle\ninline bool validateRot(const Candidate &c) {\n    int px = c.px, py = c.py;\n    if (hasDot[px][py]) return false;\n\n    const auto &rt = c.u.rot;\n\n    // New point must be one of the four vertices\n    int idx = -1;\n    for (int i = 0; i < 4; ++i) {\n        if (rt.vx[i] == px && rt.vy[i] == py) {\n            idx = i;\n            break;\n        }\n    }\n    if (idx == -1) return false;\n\n    // Other three vertices must currently have dots\n    for (int i = 0; i < 4; ++i) {\n        if (i == idx) continue;\n        int vx = rt.vx[i], vy = rt.vy[i];\n        if (!hasDot[vx][vy]) return false;\n    }\n\n    // Check edges: no extra dots on interior points and no used diagonal segments\n    for (int e = 0; e < 4; ++e) {\n        int x1 = rt.vx[e];\n        int y1 = rt.vy[e];\n        int x2 = rt.vx[(e + 1) & 3];\n        int y2 = rt.vy[(e + 1) & 3];\n\n        int dx = x2 - x1;\n        int dy = y2 - y1;\n        int steps = abs(dx);\n        if (steps == 0) return false; // degenerate, shouldn't happen\n\n        int sxStep = (dx > 0) ? 1 : -1;\n        int syStep = (dy > 0) ? 1 : -1;\n\n        // Interior dots\n        for (int i = 1; i < steps; ++i) {\n            int qx = x1 + sxStep * i;\n            int qy = y1 + syStep * i;\n            if (hasDot[qx][qy]) return false;\n        }\n\n        bool slopeUp = ((long long)dx * dy > 0); // slope +1 if dx,dy same sign\n        if (slopeUp) {\n            int sx = min(x1, x2);\n            int sy = min(y1, y2);\n            for (int i = 0; i < steps; ++i) {\n                if (diagUpUsed[sx + i][sy + i]) return false;\n            }\n        } else {\n            int sx = min(x1, x2);\n            int sy = max(y1, y2);\n            for (int i = 0; i < steps; ++i) {\n                int bx = sx + i;\n                int by = sy - 1 - i; // segment from (bx,by+1) to (bx+1,by)\n                if (diagDownUsed[bx][by]) return false;\n            }\n        }\n    }\n\n    return true;\n}\n\n// Mark edges of a rotated (45\u00b0 square) rectangle as used\ninline void markEdgesRot(const Candidate &c) {\n    const auto &rt = c.u.rot;\n\n    for (int e = 0; e < 4; ++e) {\n        int x1 = rt.vx[e];\n        int y1 = rt.vy[e];\n        int x2 = rt.vx[(e + 1) & 3];\n        int y2 = rt.vy[(e + 1) & 3];\n\n        int dx = x2 - x1;\n        int dy = y2 - y1;\n        int steps = abs(dx);\n        bool slopeUp = ((long long)dx * dy > 0);\n\n        if (slopeUp) {\n            int sx = min(x1, x2);\n            int sy = min(y1, y2);\n            for (int i = 0; i < steps; ++i) {\n                diagUpUsed[sx + i][sy + i] = true;\n            }\n        } else {\n            int sx = min(x1, x2);\n            int sy = max(y1, y2);\n            for (int i = 0; i < steps; ++i) {\n                int bx = sx + i;\n                int by = sy - 1 - i;\n                diagDownUsed[bx][by] = true;\n            }\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> M;\n    vector<pair<int,int>> initial(M);\n    for (int i = 0; i < M; ++i) {\n        int x, y;\n        cin >> x >> y;\n        initial[i] = {x, y};\n    }\n\n    // Precompute weights\n    int c = (N - 1) / 2;\n    for (int x = 0; x < N; ++x) {\n        for (int y = 0; y < N; ++y) {\n            int dx = x - c;\n            int dy = y - c;\n            cellWeight[x][y] = dx * dx + dy * dy + 1;\n        }\n    }\n\n    // Add initial dots and generate initial candidates\n    for (int i = 0; i < M; ++i) {\n        int x = initial[i].first;\n        int y = initial[i].second;\n        addDot(x, y);\n        updateAxisForNewDot(x, y);\n        updateRotatedForNewDot(x, y);\n    }\n\n    vector<Move> moves;\n\n    auto start_time = chrono::steady_clock::now();\n    const double TIME_LIMIT = 4.8; // safety margin\n\n    int iter = 0;\n    while (!pq.empty()) {\n        if ((iter & 0xFF) == 0) {\n            auto now = chrono::steady_clock::now();\n            double elapsed = chrono::duration<double>(now - start_time).count();\n            if (elapsed > TIME_LIMIT) break;\n        }\n        ++iter;\n\n        Candidate cand = pq.top();\n        pq.pop();\n\n        if (cand.type == TYPE_AXIS) {\n            if (!validateAxis(cand)) continue;\n\n            // Commit axis-aligned rectangle\n            markEdgesAxis(cand);\n            int px = cand.px;\n            int py = cand.py;\n            addDot(px, py);\n            updateAxisForNewDot(px, py);\n            updateRotatedForNewDot(px, py);\n\n            const auto &ax = cand.u.axis;\n            int xL = ax.xL, xR = ax.xR;\n            int yB = ax.yB, yT = ax.yT;\n\n            int ax0 = xL, ay0 = yB;\n            int bx0 = xR, by0 = yB;\n            int cx0 = xR, cy0 = yT;\n            int dx0 = xL, dy0 = yT;\n\n            Move m;\n            if (px == ax0 && py == ay0) {\n                m = {ax0, ay0, bx0, by0, cx0, cy0, dx0, dy0};\n            } else if (px == bx0 && py == by0) {\n                m = {bx0, by0, cx0, cy0, dx0, dy0, ax0, ay0};\n            } else if (px == cx0 && py == cy0) {\n                m = {cx0, cy0, dx0, dy0, ax0, ay0, bx0, by0};\n            } else {\n                m = {dx0, dy0, ax0, ay0, bx0, by0, cx0, cy0};\n            }\n            moves.push_back(m);\n\n        } else { // TYPE_ROT\n            if (!validateRot(cand)) continue;\n\n            // Commit rotated rectangle\n            markEdgesRot(cand);\n            int px = cand.px;\n            int py = cand.py;\n            addDot(px, py);\n            updateAxisForNewDot(px, py);\n            updateRotatedForNewDot(px, py);\n\n            const auto &rt = cand.u.rot;\n            int idx = 0;\n            for (; idx < 4; ++idx) {\n                if (rt.vx[idx] == px && rt.vy[idx] == py) break;\n            }\n            if (idx == 4) idx = 0; // fallback, shouldn't happen\n\n            int x1 = rt.vx[idx],           y1 = rt.vy[idx];\n            int x2 = rt.vx[(idx + 1) & 3], y2 = rt.vy[(idx + 1) & 3];\n            int x3 = rt.vx[(idx + 2) & 3], y3 = rt.vy[(idx + 2) & 3];\n            int x4 = rt.vx[(idx + 3) & 3], y4 = rt.vy[(idx + 3) & 3];\n            moves.push_back({x1, y1, x2, y2, x3, y3, x4, y4});\n        }\n    }\n\n    // Output\n    cout << moves.size() << '\\n';\n    for (const auto &m : moves) {\n        cout << m.x1 << ' ' << m.y1 << ' '\n             << m.x2 << ' ' << m.y2 << ' '\n             << m.x3 << ' ' << m.y3 << ' '\n             << m.x4 << ' ' << m.y4 << '\\n';\n    }\n\n    return 0;\n}","ahc015":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const int N = 10;\n\n// Monte Carlo samples\nstatic const int K1 = 3; // samples for 2-step lookahead (early game)\nstatic const int K2 = 5; // samples for 1-step lookahead (later game)\n\nstruct Board {\n    uint8_t a[N][N];\n    Board() { memset(a, 0, sizeof(a)); }\n};\n\n// Tilt directions: 0 = F, 1 = B, 2 = L, 3 = R\nvoid tilt(Board &b, int dir) {\n    if (dir == 0) { // F: move toward row 0\n        for (int c = 0; c < N; c++) {\n            int pos = 0;\n            for (int r = 0; r < N; r++) {\n                uint8_t v = b.a[r][c];\n                if (v) {\n                    if (pos != r) b.a[pos][c] = v;\n                    pos++;\n                }\n            }\n            for (int r = pos; r < N; r++) b.a[r][c] = 0;\n        }\n    } else if (dir == 1) { // B: move toward row 9\n        for (int c = 0; c < N; c++) {\n            int pos = N - 1;\n            for (int r = N - 1; r >= 0; r--) {\n                uint8_t v = b.a[r][c];\n                if (v) {\n                    if (pos != r) b.a[pos][c] = v;\n                    pos--;\n                }\n            }\n            for (int r = pos; r >= 0; r--) b.a[r][c] = 0;\n        }\n    } else if (dir == 2) { // L: move toward col 0\n        for (int r = 0; r < N; r++) {\n            int pos = 0;\n            for (int c = 0; c < N; c++) {\n                uint8_t v = b.a[r][c];\n                if (v) {\n                    if (pos != c) b.a[r][pos] = v;\n                    pos++;\n                }\n            }\n            for (int c = pos; c < N; c++) b.a[r][c] = 0;\n        }\n    } else { // R: move toward col 9\n        for (int r = 0; r < N; r++) {\n            int pos = N - 1;\n            for (int c = N - 1; c >= 0; c--) {\n                uint8_t v = b.a[r][c];\n                if (v) {\n                    if (pos != c) b.a[r][pos] = v;\n                    pos--;\n                }\n            }\n            for (int c = pos; c >= 0; c--) b.a[r][c] = 0;\n        }\n    }\n}\n\n// Sum of squared sizes of same-color connected components (4-neighbor)\nlong long evaluate(const Board &b) {\n    static uint32_t vis[N][N];\n    static uint32_t curMark = 1;\n    curMark++;\n\n    static const int dr[4] = {1, -1, 0, 0};\n    static const int dc[4] = {0, 0, 1, -1};\n    int qx[100], qy[100];\n    long long score = 0;\n\n    for (int r = 0; r < N; r++) {\n        for (int c = 0; c < N; c++) {\n            uint8_t color = b.a[r][c];\n            if (color != 0 && vis[r][c] != curMark) {\n                int head = 0, tail = 0;\n                qx[tail] = r;\n                qy[tail] = c;\n                tail++;\n                vis[r][c] = curMark;\n                int cnt = 0;\n\n                while (head < tail) {\n                    int x = qx[head];\n                    int y = qy[head];\n                    head++;\n                    cnt++;\n\n                    for (int k = 0; k < 4; k++) {\n                        int nx = x + dr[k];\n                        int ny = y + dc[k];\n                        if (0 <= nx && nx < N && 0 <= ny && ny < N) {\n                            if (b.a[nx][ny] == color && vis[nx][ny] != curMark) {\n                                vis[nx][ny] = curMark;\n                                qx[tail] = nx;\n                                qy[tail] = ny;\n                                tail++;\n                            }\n                        }\n                    }\n                }\n                score += 1LL * cnt * cnt;\n            }\n        }\n    }\n    return score;\n}\n\n// Find p-th empty cell (1-based) in front-to-back, left-to-right order\npair<int,int> findPos(const Board &b, int p) {\n    int cnt = 0;\n    for (int r = 0; r < N; r++) {\n        for (int c = 0; c < N; c++) {\n            if (b.a[r][c] == 0) {\n                cnt++;\n                if (cnt == p) return {r, c};\n            }\n        }\n    }\n    return {-1, -1}; // should not happen\n}\n\n// Choose a random empty cell uniformly from current board\npair<int,int> randomEmptyCell(const Board &b, mt19937_64 &rng) {\n    int empties = 0;\n    for (int r = 0; r < N; r++) {\n        for (int c = 0; c < N; c++) {\n            if (b.a[r][c] == 0) empties++;\n        }\n    }\n    // Should never be called with empties == 0\n    uint64_t x = rng();\n    int k = (int)(x % empties); // 0..empties-1\n    int cnt = 0;\n    for (int r = 0; r < N; r++) {\n        for (int c = 0; c < N; c++) {\n            if (b.a[r][c] == 0) {\n                if (cnt == k) return {r, c};\n                cnt++;\n            }\n        }\n    }\n    return {0, 0}; // fallback, should not occur\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // Read flavor sequence\n    vector<int> f(100);\n    for (int i = 0; i < 100; i++) {\n        if (!(cin >> f[i])) return 0;\n    }\n\n    Board cur;\n    const char DIR_CH[4] = {'F', 'B', 'L', 'R'};\n    mt19937_64 rng(712367821ull); // fixed seed for deterministic behavior\n\n    for (int t = 0; t < 100; t++) {\n        int p;\n        if (!(cin >> p)) return 0;\n\n        // Place current candy\n        auto [r, c] = findPos(cur, p);\n        if (r == -1) return 0; // safety\n        cur.a[r][c] = (uint8_t)f[t];\n\n        long long bestScore = LLONG_MIN;\n        int bestDir = 0;\n        Board bestBoard;\n\n        int remain = 99 - t; // number of future candies after this step\n\n        if (t <= 39 && remain >= 2) {\n            // Early game: 2-step lookahead with K1 samples\n            for (int dir0 = 0; dir0 < 4; dir0++) {\n                Board b1 = cur;\n                tilt(b1, dir0);\n                long long S0 = evaluate(b1);\n                long long sum1 = 0;\n                long long sum2 = 0;\n\n                for (int s = 0; s < K1; s++) {\n                    // Step t+1 simulation\n                    Board sim1 = b1;\n                    auto [r1, c1] = randomEmptyCell(sim1, rng);\n                    sim1.a[r1][c1] = (uint8_t)f[t + 1];\n\n                    long long best1 = LLONG_MIN;\n                    Board b2best;\n\n                    for (int dir1 = 0; dir1 < 4; dir1++) {\n                        Board b2 = sim1;\n                        tilt(b2, dir1);\n                        long long sc1 = evaluate(b2);\n                        if (sc1 > best1) {\n                            best1 = sc1;\n                            b2best = b2;\n                        }\n                    }\n                    sum1 += best1;\n\n                    // Step t+2 simulation\n                    Board sim2 = b2best;\n                    auto [r2, c2] = randomEmptyCell(sim2, rng);\n                    sim2.a[r2][c2] = (uint8_t)f[t + 2];\n\n                    long long best2 = LLONG_MIN;\n                    for (int dir2 = 0; dir2 < 4; dir2++) {\n                        Board b3 = sim2;\n                        tilt(b3, dir2);\n                        long long sc2 = evaluate(b3);\n                        if (sc2 > best2) {\n                            best2 = sc2;\n                        }\n                    }\n                    sum2 += best2;\n                }\n\n                // Approximate S0 + E[S1] + E[S2]\n                long long scoreValue = S0 * K1 + sum1 + sum2;\n\n                if (scoreValue > bestScore) {\n                    bestScore = scoreValue;\n                    bestDir = dir0;\n                    bestBoard = b1;\n                }\n            }\n        } else if (remain >= 1) {\n            // Mid/Late game: 1-step lookahead with K2 samples\n            for (int dir0 = 0; dir0 < 4; dir0++) {\n                Board b1 = cur;\n                tilt(b1, dir0);\n                long long S0 = evaluate(b1);\n                long long sum1 = 0;\n\n                for (int s = 0; s < K2; s++) {\n                    Board sim1 = b1;\n                    auto [r1, c1] = randomEmptyCell(sim1, rng);\n                    sim1.a[r1][c1] = (uint8_t)f[t + 1];\n\n                    long long best1 = LLONG_MIN;\n                    for (int dir1 = 0; dir1 < 4; dir1++) {\n                        Board b2 = sim1;\n                        tilt(b2, dir1);\n                        long long sc1 = evaluate(b2);\n                        if (sc1 > best1) {\n                            best1 = sc1;\n                        }\n                    }\n                    sum1 += best1;\n                }\n\n                // Approximate S0 + E[S1]\n                long long scoreValue = S0 * K2 + sum1;\n\n                if (scoreValue > bestScore) {\n                    bestScore = scoreValue;\n                    bestDir = dir0;\n                    bestBoard = b1;\n                }\n            }\n        } else {\n            // Last step: no future candies; only immediate score matters\n            for (int dir0 = 0; dir0 < 4; dir0++) {\n                Board b1 = cur;\n                tilt(b1, dir0);\n                long long S0 = evaluate(b1);\n                if (S0 > bestScore) {\n                    bestScore = S0;\n                    bestDir = dir0;\n                    bestBoard = b1;\n                }\n            }\n        }\n\n        cur = bestBoard;\n        cout << DIR_CH[bestDir] << '\\n' << flush;\n    }\n\n    return 0;\n}","ahc016":"#include <bits/stdc++.h>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int M;\n    double eps;\n    if (!(cin >> M >> eps)) return 0;\n\n    bool noNoise = (eps < 0.0005);  // eps is multiple of 0.01, so this catches eps=0\n\n    int N = 4;\n    int L = 0;\n\n    if (noNoise) {\n        // eps = 0: choose minimum N s.t. L >= M\n        while (N < 100) {\n            L = N * (N - 1) / 2;\n            if (L >= M) break;\n            ++N;\n        }\n        L = N * (N - 1) / 2;\n    } else {\n        // eps > 0: choose N using linear + quadratic (SNR-based) constraints\n        const double baseC0 = 6.0;\n        const double baseC1 = 60.0;\n        double L1 = (baseC0 + baseC1 * eps) * M;\n\n        const double r0 = 4.0;\n        double den = 1.0 - 2.0 * eps;\n        den *= den;\n        double L2;\n        if (den < 1e-12) {\n            // When eps is very close to 0.5, separation becomes impossible in 1D;\n            // effectively we just want the max L.\n            L2 = 1e18;\n        } else {\n            double alpha2 = (r0 * r0 * eps * (1.0 - eps)) / den;\n            L2 = alpha2 * (M + 1.0) * (M + 1.0);\n        }\n\n        double targetL = max(L1, L2);\n        // Need at least M+1 distinct total edge counts.\n        if (targetL < M + 1.0) targetL = M + 1.0;\n        // Cap by max possible L with N <= 100\n        if (targetL > 4950.0) targetL = 4950.0;\n\n        N = 4;\n        while (N < 100) {\n            L = N * (N - 1) / 2;\n            if ((double)L >= targetL) break;\n            ++N;\n        }\n        L = N * (N - 1) / 2;\n    }\n\n    // Decide edge counts m_k\n    vector<int> mEdges(M);\n\n    if (noNoise) {\n        // eps = 0: use m_k = k, since L >= M\n        for (int k = 0; k < M; ++k) {\n            mEdges[k] = k;\n        }\n    } else {\n        // eps > 0: spread m_k roughly evenly across 1..L-1\n        for (int k = 0; k < M; ++k) {\n            long long num = 1LL * (k + 1) * L;\n            int mk = (int)(num / (M + 1));  // floor\n            if (mk <= 0) mk = 1;\n            if (mk >= L) mk = L - 1;\n            mEdges[k] = mk;\n        }\n        // Ensure strictly increasing\n        if (mEdges[0] <= 0) mEdges[0] = 1;\n        for (int k = 1; k < M; ++k) {\n            if (mEdges[k] <= mEdges[k - 1]) {\n                mEdges[k] = mEdges[k - 1] + 1;\n                if (mEdges[k] >= L) mEdges[k] = L - 1;\n            }\n        }\n    }\n\n    // Precompute expected noisy edge counts for eps > 0\n    vector<double> mu;\n    double a = 1.0 - 2.0 * eps;\n    double b = eps * L;\n    if (!noNoise) {\n        mu.resize(M);\n        for (int k = 0; k < M; ++k) {\n            mu[k] = a * (double)mEdges[k] + b;\n        }\n    }\n\n    // Output N and graphs (as bitstrings of length L)\n    cout << N << '\\n';\n    for (int k = 0; k < M; ++k) {\n        int mk = mEdges[k];\n        string s(L, '0');\n        for (int i = 0; i < mk; ++i) s[i] = '1';\n        cout << s << '\\n';\n    }\n    cout.flush();\n\n    // For eps = 0, build direct map from edge count to graph index\n    vector<int> edgeToIndex;\n    if (noNoise) {\n        edgeToIndex.assign(L + 1, -1);\n        for (int k = 0; k < M; ++k) {\n            int mk = mEdges[k];\n            if (0 <= mk && mk <= L) edgeToIndex[mk] = k;\n        }\n    }\n\n    // Answer 100 queries\n    for (int q = 0; q < 100; ++q) {\n        string H;\n        if (!(cin >> H)) return 0;\n\n        // Count edges in H\n        int mPrime = 0;\n        for (char c : H) if (c == '1') ++mPrime;\n\n        int bestK = 0;\n\n        if (noNoise) {\n            // Exact decoding by edge count\n            if (mPrime >= 0 && mPrime <= L && edgeToIndex[mPrime] != -1) {\n                bestK = edgeToIndex[mPrime];\n            } else {\n                // Very unlikely fallback: choose nearest in mEdges[k]\n                int bestDiff = INT_MAX;\n                for (int k = 0; k < M; ++k) {\n                    int diff = abs(mPrime - mEdges[k]);\n                    if (diff < bestDiff) {\n                        bestDiff = diff;\n                        bestK = k;\n                    }\n                }\n            }\n        } else {\n            // eps > 0: choose k with mu[k] closest to mPrime\n            double bestDiff = fabs((double)mPrime - mu[0]);\n            bestK = 0;\n            for (int k = 1; k < M; ++k) {\n                double diff = fabs((double)mPrime - mu[k]);\n                if (diff < bestDiff) {\n                    bestDiff = diff;\n                    bestK = k;\n                }\n            }\n        }\n\n        cout << bestK << '\\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 id;\n    int w;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, D, K;\n    if (!(cin >> N >> M >> D >> K)) return 0;\n\n    vector<int> U(M), V(M), W(M);\n    for (int i = 0; i < M; i++) {\n        cin >> U[i] >> V[i] >> W[i];\n        --U[i];\n        --V[i];\n    }\n    // Coordinates (unused)\n    for (int i = 0; i < N; i++) {\n        int x, y;\n        cin >> x >> y;\n    }\n\n    // Build adjacency list\n    vector<vector<AdjEdge>> g(N);\n    for (int i = 0; i < M; i++) {\n        int u = U[i], v = V[i], w = W[i];\n        g[u].push_back({v, i, w});\n        g[v].push_back({u, i, w});\n    }\n\n    mt19937_64 rng(123456789);\n\n    // ---------------------- Step 1: Betweenness-like centrality -------------------------\n    int S_c = min(N, 60); // number of sampled sources for centrality\n    vector<int> perm(N);\n    iota(perm.begin(), perm.end(), 0);\n    shuffle(perm.begin(), perm.end(), rng);\n    vector<int> sources_c(S_c);\n    for (int i = 0; i < S_c; i++) sources_c[i] = perm[i];\n\n    vector<double> central(M, 0.0);\n\n    const long long INFLL = (1LL << 60);\n    vector<long long> distLL(N);\n    vector<int> parent_v(N), parent_e(N);\n    vector<int> order;\n    order.reserve(N);\n\n    using PQItem = pair<long long, int>;\n\n    for (int s : sources_c) {\n        fill(distLL.begin(), distLL.end(), INFLL);\n        fill(parent_v.begin(), parent_v.end(), -1);\n        fill(parent_e.begin(), parent_e.end(), -1);\n        order.clear();\n\n        priority_queue<PQItem, vector<PQItem>, greater<PQItem>> pq;\n        distLL[s] = 0;\n        pq.emplace(0, s);\n\n        while (!pq.empty()) {\n            auto [d, v] = pq.top();\n            pq.pop();\n            if (d != distLL[v]) continue;\n            order.push_back(v);\n            for (const auto &e : g[v]) {\n                int to = e.to;\n                long long nd = d + e.w;\n                if (nd < distLL[to]) {\n                    distLL[to] = nd;\n                    parent_v[to] = v;\n                    parent_e[to] = e.id;\n                    pq.emplace(nd, to);\n                }\n            }\n        }\n\n        // Tree DP to accumulate centrality\n        vector<int> sz(N, 1);\n        for (int i = (int)order.size() - 1; i >= 0; --i) {\n            int v = order[i];\n            int pv = parent_v[v];\n            if (pv == -1) continue;\n            int eid = parent_e[v];\n            central[eid] += sz[v];\n            sz[pv] += sz[v];\n        }\n    }\n\n    // ---------------------- Step 2: Alternative-path detour per edge ---------------------\n    vector<long long> altDiff(M, 1); // altDist - W[e], clamped\n    const long long INF_COST = 1000000000LL;\n    const long long ALT_CLAMP = 10000000LL; // clamp alternative detour to this\n\n    for (int eid = 0; eid < M; eid++) {\n        int src = U[eid];\n        int tgt = V[eid];\n\n        // Run Dijkstra from src, skipping edge eid\n        fill(distLL.begin(), distLL.end(), INF_COST);\n        priority_queue<PQItem, vector<PQItem>, greater<PQItem>> pq;\n        distLL[src] = 0;\n        pq.emplace(0, src);\n\n        long long limit = (long long)W[eid] + ALT_CLAMP;\n        if (limit > INF_COST) limit = INF_COST;\n\n        long long alt = INF_COST;\n\n        while (!pq.empty()) {\n            auto [d, v] = pq.top();\n            pq.pop();\n            if (d != distLL[v]) continue;\n            if (d > limit) break; // beyond clamp, we don't care exact value\n            if (v == tgt) {\n                alt = d;\n                break;\n            }\n            for (const auto &ed : g[v]) {\n                if (ed.id == eid) continue; // skip this edge in both directions\n                int to = ed.to;\n                long long nd = d + ed.w;\n                if (nd < distLL[to] && nd <= limit) {\n                    distLL[to] = nd;\n                    pq.emplace(nd, to);\n                }\n            }\n        }\n\n        if (alt > limit) alt = limit;\n        if (alt > INF_COST) alt = INF_COST;\n        long long delta = alt - (long long)W[eid];\n        if (delta < 1) delta = 1;\n        if (delta > ALT_CLAMP) delta = ALT_CLAMP;\n        altDiff[eid] = delta;\n    }\n\n    // ---------------------- Step 3: Edge importance modes & normalization ---------------\n    const int MODES = 3;\n    vector<vector<double>> rawImp(MODES, vector<double>(M));\n    vector<double> maxImp(MODES, 0.0);\n\n    for (int i = 0; i < M; i++) {\n        double cen = central[i] + 1.0;\n        double wlen = (double)W[i];\n        double ad = (double)altDiff[i];\n\n        // Mode 0: central * edge length\n        rawImp[0][i] = cen * wlen;\n        // Mode 1: central * alternative detour\n        rawImp[1][i] = cen * ad;\n        // Mode 2: hybrid: central * (0.5*wlen + 0.5*min(ad, 5*wlen))\n        double ad_lim = min(ad, wlen * 5.0);\n        rawImp[2][i] = cen * (0.5 * wlen + 0.5 * ad_lim);\n\n        for (int m = 0; m < MODES; m++) {\n            if (rawImp[m][i] > maxImp[m]) maxImp[m] = rawImp[m][i];\n        }\n    }\n\n    vector<vector<double>> weightModes(MODES, vector<double>(M));\n    for (int m = 0; m < MODES; m++) {\n        double scale = (maxImp[m] > 0.0 ? maxImp[m] / 1000.0 : 1.0);\n        if (scale == 0.0) scale = 1.0;\n        for (int i = 0; i < M; i++) {\n            weightModes[m][i] = rawImp[m][i] / scale;\n        }\n    }\n\n    // ---------------------- Step 4: Capacities per day ----------------------------------\n    vector<int> cap(D);\n    int base = M / D;\n    int rem = M % D;\n    for (int d = 0; d < D; d++) {\n        cap[d] = base + (d < rem ? 1 : 0);\n        // cap[d] <= ceil(M/D) <= K guaranteed\n    }\n\n    // ---------------------- Step 5: Schedule builder (greedy + local search) -----------\n    auto buildSchedule = [&](const vector<double> &weight) -> vector<int> {\n        vector<int> day_cnt(D, 0);\n        vector<double> day_sum(D, 0.0);\n        vector<vector<double>> vds(N, vector<double>(D, 0.0));\n        vector<int> r(M, -1);\n\n        // Initial greedy assignment\n        vector<int> ids(M);\n        iota(ids.begin(), ids.end(), 0);\n        sort(ids.begin(), ids.end(), [&](int a, int b) {\n            return weight[a] > weight[b];\n        });\n\n        const double INIT_ALPHA = 10.0; // local vertex concurrency weight\n        const double INIT_BETA  = 1.0;  // per-day balance weight\n\n        for (int idx = 0; idx < M; idx++) {\n            int e = ids[idx];\n            int u = U[e], v = V[e];\n\n            int bestD = -1;\n            double bestScore = 1e300;\n\n            for (int d = 0; d < D; d++) {\n                if (day_cnt[d] >= cap[d]) continue;\n                double localConcur = vds[u][d] + vds[v][d];\n                double score = INIT_ALPHA * localConcur + INIT_BETA * day_sum[d];\n                if (score < bestScore) {\n                    bestScore = score;\n                    bestD = d;\n                }\n            }\n\n            if (bestD == -1) {\n                // Fallback (should not happen): allocate to any day with free capacity\n                for (int d = 0; d < D; d++) {\n                    if (day_cnt[d] < cap[d]) {\n                        bestD = d;\n                        break;\n                    }\n                }\n            }\n\n            r[e] = bestD;\n            day_cnt[bestD]++;\n            day_sum[bestD] += weight[e];\n            vds[u][bestD] += weight[e];\n            vds[v][bestD] += weight[e];\n        }\n\n        // Local search: minimize ALPHA2*sum_{v,d} vds^2 + BETA2*sum_d day_sum^2\n        const double ALPHA2 = 1.0;\n        const double BETA2  = 0.03; // concurrency more important than day balance\n\n        int ITER = min(700000, 250 * M);\n        uniform_int_distribution<int> distEdge(0, M - 1);\n\n        for (int it = 0; it < ITER; ++it) {\n            int e1 = distEdge(rng);\n            int e2 = distEdge(rng);\n            if (e1 == e2) continue;\n            int d1 = r[e1], d2 = r[e2];\n            if (d1 == d2) continue;\n\n            int u1 = U[e1], v1 = V[e1];\n            int u2 = U[e2], v2 = V[e2];\n            double w1 = weight[e1], w2 = weight[e2];\n\n            // Day-sum component\n            double S1 = day_sum[d1], S2 = day_sum[d2];\n            double nS1 = S1 - w1 + w2;\n            double nS2 = S2 - w2 + w1;\n            double deltaDay = BETA2 * ((nS1 * nS1 + nS2 * nS2) - (S1 * S1 + S2 * S2));\n\n            // Vertex-day component\n            int vs[8];\n            int ds[8];\n            double dW[8];\n            int cnt = 0;\n\n            auto addChange = [&](int v, int d, double delta) {\n                for (int i = 0; i < cnt; i++) {\n                    if (vs[i] == v && ds[i] == d) {\n                        dW[i] += delta;\n                        return;\n                    }\n                }\n                vs[cnt] = v;\n                ds[cnt] = d;\n                dW[cnt] = delta;\n                cnt++;\n            };\n\n            // e1: d1 -> d2\n            addChange(u1, d1, -w1);\n            addChange(u1, d2, +w1);\n            addChange(v1, d1, -w1);\n            addChange(v1, d2, +w1);\n            // e2: d2 -> d1\n            addChange(u2, d2, -w2);\n            addChange(u2, d1, +w2);\n            addChange(v2, d2, -w2);\n            addChange(v2, d1, +w2);\n\n            double deltaVertex = 0.0;\n            double newVals[8];\n            for (int i = 0; i < cnt; i++) {\n                int v = vs[i];\n                int d = ds[i];\n                double oldS = vds[v][d];\n                double newS = oldS + dW[i];\n                newVals[i] = newS;\n                deltaVertex += ALPHA2 * (newS * newS - oldS * oldS);\n            }\n\n            double deltaScore = deltaVertex + deltaDay;\n\n            if (deltaScore < -1e-9) {\n                // Accept swap\n                day_sum[d1] = nS1;\n                day_sum[d2] = nS2;\n                for (int i = 0; i < cnt; i++) {\n                    vds[vs[i]][ds[i]] = newVals[i];\n                }\n                swap(r[e1], r[e2]);\n            }\n        }\n\n        return r;\n    };\n\n    // ---------------------- Step 6: Build schedules for all modes -----------------------\n    vector<vector<int>> schedules(MODES);\n    for (int m = 0; m < MODES; m++) {\n        schedules[m] = buildSchedule(weightModes[m]);\n    }\n\n    // ---------------------- Step 7: Approximate evaluation of schedules ----------------\n    // Sample sources for evaluation (possibly reusing perm)\n    int S_eval = min(N, 18);\n    vector<int> evalSources(S_eval);\n    for (int i = 0; i < S_eval; i++) evalSources[i] = perm[i];\n\n    // Precompute shortest paths in the full graph from each eval source\n    const int INF = 1000000000;\n    vector<vector<int>> baseDist(S_eval, vector<int>(N, INF));\n    for (int si = 0; si < S_eval; si++) {\n        int s = evalSources[si];\n        fill(distLL.begin(), distLL.end(), INFLL);\n        priority_queue<PQItem, vector<PQItem>, greater<PQItem>> pq;\n        distLL[s] = 0;\n        pq.emplace(0, s);\n\n        while (!pq.empty()) {\n            auto [d, v] = pq.top();\n            pq.pop();\n            if (d != distLL[v]) continue;\n            for (const auto &e : g[v]) {\n                int to = e.to;\n                long long nd = d + e.w;\n                if (nd < distLL[to]) {\n                    distLL[to] = nd;\n                    pq.emplace(nd, to);\n                }\n            }\n        }\n        for (int v = 0; v < N; v++) {\n            long long dv = distLL[v];\n            if (dv >= INF_COST) dv = INF_COST;\n            baseDist[si][v] = (int)dv;\n        }\n    }\n\n    auto evaluateSchedule = [&](const vector<int> &r) -> double {\n        vector<long long> distEval(N);\n        double totalDelta = 0.0;\n\n        for (int si = 0; si < S_eval; si++) {\n            int s = evalSources[si];\n            const vector<int> &orig = baseDist[si];\n\n            for (int dday = 0; dday < D; dday++) {\n                fill(distEval.begin(), distEval.end(), (long long)INF);\n                priority_queue<PQItem, vector<PQItem>, greater<PQItem>> pq;\n                distEval[s] = 0;\n                pq.emplace(0, s);\n\n                while (!pq.empty()) {\n                    auto [cd, v] = pq.top();\n                    pq.pop();\n                    if (cd != distEval[v]) continue;\n                    for (const auto &e : g[v]) {\n                        if (r[e.id] == dday) continue; // edge under repair this day\n                        int to = e.to;\n                        long long nd = cd + e.w;\n                        if (nd < distEval[to] && nd < INF) {\n                            distEval[to] = nd;\n                            pq.emplace(nd, to);\n                        }\n                    }\n                }\n\n                for (int v = 0; v < N; v++) {\n                    if (v == s) continue;\n                    int o = orig[v];\n                    long long cur = distEval[v];\n                    int nd = (cur >= INF ? INF : (int)cur);\n                    long long delta = (long long)nd - o;\n                    if (delta < 0) delta = 0; // should not happen, but be safe\n                    totalDelta += (double)delta;\n                }\n            }\n        }\n        return totalDelta; // denominator (S_eval*(N-1)*D) is common, so we omit\n    };\n\n    int bestIdx = 0;\n    double bestScore = evaluateSchedule(schedules[0]);\n    for (int m = 1; m < MODES; m++) {\n        double sc = evaluateSchedule(schedules[m]);\n        if (sc < bestScore) {\n            bestScore = sc;\n            bestIdx = m;\n        }\n    }\n\n    // ---------------------- Output best schedule ---------------------------------------\n    const vector<int> &best = schedules[bestIdx];\n    for (int i = 0; i < M; i++) {\n        cout << (best[i] + 1);\n        if (i + 1 != M) cout << ' ';\n    }\n    cout << '\\n';\n\n    return 0;\n}","ahc019":"#include <bits/stdc++.h>\nusing namespace std;\n\n// ----------------------------\n// Basic structures\n// ----------------------------\nstruct Coord {\n    int x, y, z;\n};\n\nstruct Rot {\n    int p[3]; // permutation of axes: 0=x,1=y,2=z\n    int s[3]; // sign for each axis: +1 or -1\n};\n\nconst int MAXS = 250; // upper bound for number of shared cubes (safe for D<=14)\nstatic bool adjSmall[MAXS][MAXS]; // adjacency in small puzzle\n\n// ----------------------------\n// Generate all 24 proper rotations (determinant +1) of the cube\n// ----------------------------\nvector<Rot> generate_rotations() {\n    vector<Rot> rots;\n    vector<int> perm = {0, 1, 2};\n    auto parity = [](const vector<int>& p) -> int {\n        int inv = 0;\n        for (int i = 0; i < 3; i++) {\n            for (int j = i + 1; j < 3; j++) {\n                if (p[i] > p[j]) inv++;\n            }\n        }\n        return (inv % 2 == 0) ? 1 : -1;\n    };\n\n    do {\n        int ps = parity(perm); // +1 for even, -1 for odd\n        for (int mask = 0; mask < 8; mask++) {\n            int s0 = (mask & 1) ? -1 : 1;\n            int s1 = (mask & 2) ? -1 : 1;\n            int s2 = (mask & 4) ? -1 : 1;\n            int det = ps * s0 * s1 * s2;\n            if (det == 1) { // proper rotation\n                Rot r;\n                r.p[0] = perm[0]; r.p[1] = perm[1]; r.p[2] = perm[2];\n                r.s[0] = s0;      r.s[1] = s1;      r.s[2] = s2;\n                rots.push_back(r);\n            }\n        }\n    } while (next_permutation(perm.begin(), perm.end()));\n    return rots; // should have size 24\n}\n\n// ----------------------------\n// Canonical shape representation from cell IDs\n// coords are given as cell IDs in [0, D^3)\n// preRot[r][id] = rotated (x,y,z) for rotation r\n// ----------------------------\nvector<array<int,3>> canonical_from_ids(\n    const vector<int>& ids,\n    const vector<vector<array<int,3>>>& preRot\n) {\n    vector<array<int,3>> best;\n    bool first = true;\n    int R = (int)preRot.size();\n    for (int r = 0; r < R; r++) {\n        const auto& tab = preRot[r];\n        vector<array<int,3>> coords;\n        coords.reserve(ids.size());\n        int minx = INT_MAX, miny = INT_MAX, minz = INT_MAX;\n        for (int id : ids) {\n            const auto& q = tab[id];\n            coords.push_back(q);\n            minx = min(minx, q[0]);\n            miny = min(miny, q[1]);\n            minz = min(minz, q[2]);\n        }\n        for (auto &q : coords) {\n            q[0] -= minx;\n            q[1] -= miny;\n            q[2] -= minz;\n        }\n        sort(coords.begin(), coords.end());\n        if (first || coords < best) {\n            best = coords;\n            first = false;\n        }\n    }\n    return best;\n}\n\n// ----------------------------\n// Main\n// ----------------------------\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int D;\n    if (!(cin >> D)) return 0;\n\n    // Read silhouettes: f[t][z][x], r[t][z][y]\n    vector<string> f[2], r[2];\n    for (int t = 0; t < 2; t++) {\n        f[t].resize(D);\n        r[t].resize(D);\n        for (int z = 0; z < D; z++) cin >> f[t][z];\n        for (int z = 0; z < D; z++) cin >> r[t][z];\n    }\n\n    // Build minimal-volume occupancy for each puzzle\n    vector<Coord> cells[2]; // occupied cells per puzzle\n\n    for (int t = 0; t < 2; t++) {\n        for (int z = 0; z < D; z++) {\n            vector<int> rows, cols;\n            for (int x = 0; x < D; x++) if (f[t][z][x] == '1') rows.push_back(x);\n            for (int y = 0; y < D; y++) if (r[t][z][y] == '1') cols.push_back(y);\n            int Rcnt = (int)rows.size();\n            int Ccnt = (int)cols.size();\n            if (Rcnt == 0 || Ccnt == 0) continue; // shouldn't happen by constraints\n\n            if (Rcnt <= Ccnt) {\n                // Use Ccnt cubes, one per column\n                for (int j = 0; j < Ccnt; j++) {\n                    int x = rows[j % Rcnt];\n                    int y = cols[j];\n                    cells[t].push_back({x, y, z});\n                }\n            } else {\n                // Use Rcnt cubes, one per row\n                for (int i = 0; i < Rcnt; i++) {\n                    int x = rows[i];\n                    int y = cols[i % Ccnt];\n                    cells[t].push_back({x, y, z});\n                }\n            }\n        }\n    }\n\n    int V0 = (int)cells[0].size();\n    int V1 = (int)cells[1].size();\n\n    // Decide which puzzle is \"small\" and which is \"big\" by volume\n    int small = 0, big = 1;\n    if (V0 > V1) {\n        small = 1;\n        big = 0;\n        swap(V0, V1);\n    }\n    int S = (int)cells[small].size(); // shared count (all cubes in small puzzle)\n    int T = (int)cells[big].size();\n\n    // Positions and cell IDs\n    vector<Coord> posSmall(S), posBigAll(T);\n    for (int i = 0; i < S; i++) posSmall[i] = cells[small][i];\n    for (int i = 0; i < T; i++) posBigAll[i] = cells[big][i];\n\n    auto encode = [D](int x, int y, int z) {\n        return x * D * D + y * D + z;\n    };\n    int D3 = D * D * D;\n\n    vector<int> cellIdSmall(S), cellIdBigAll(T);\n    for (int i = 0; i < S; i++) {\n        cellIdSmall[i] = encode(posSmall[i].x, posSmall[i].y, posSmall[i].z);\n    }\n    for (int i = 0; i < T; i++) {\n        cellIdBigAll[i] = encode(posBigAll[i].x, posBigAll[i].y, posBigAll[i].z);\n    }\n\n    // Build adjacency in the small puzzle\n    vector<int> idxSmall(D3, -1);\n    for (int i = 0; i < S; i++) {\n        idxSmall[cellIdSmall[i]] = i;\n    }\n\n    for (int i = 0; i < S; i++)\n        for (int j = 0; j < S; j++)\n            adjSmall[i][j] = false;\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 k = 0; k < S; k++) {\n        int x = posSmall[k].x;\n        int y = posSmall[k].y;\n        int z = posSmall[k].z;\n        for (int d = 0; d < 6; d++) {\n            int nx = x + dx[d];\n            int ny = y + dy[d];\n            int nz = z + dz[d];\n            if (nx < 0 || nx >= D || ny < 0 || ny >= D || nz < 0 || nz >= D) continue;\n            int nid = encode(nx, ny, nz);\n            int j = idxSmall[nid];\n            if (j >= 0) {\n                adjSmall[k][j] = adjSmall[j][k] = true;\n            }\n        }\n    }\n\n    // Convert adjacency matrix to neighbor lists\n    vector<vector<int>> neighbors(S);\n    for (int i = 0; i < S; i++) {\n        for (int j = i + 1; j < S; j++) {\n            if (adjSmall[i][j]) {\n                neighbors[i].push_back(j);\n                neighbors[j].push_back(i);\n            }\n        }\n    }\n\n    // Precompute all rotations and rotated coordinates for each cell ID\n    vector<Rot> rots = generate_rotations();\n    int R = (int)rots.size(); // should be 24\n    vector<vector<array<int,3>>> preRot(R, vector<array<int,3>>(D3));\n\n    for (int id = 0; id < D3; id++) {\n        int x = id / (D * D);\n        int rem = id % (D * D);\n        int y = rem / D;\n        int z = rem % D;\n        int src[3] = {x, y, z};\n        for (int rIdx = 0; rIdx < R; rIdx++) {\n            const Rot &rt = rots[rIdx];\n            array<int,3> q;\n            q[0] = rt.s[0] * src[ rt.p[0] ];\n            q[1] = rt.s[1] * src[ rt.p[1] ];\n            q[2] = rt.s[2] * src[ rt.p[2] ];\n            preRot[rIdx][id] = q;\n        }\n    }\n\n    // Initialize RNG with deterministic seed based on input\n    uint64_t seed = 1234567u ^ (uint64_t)D;\n    for (int t = 0; t < 2; t++) {\n        for (int z = 0; z < D; z++) {\n            for (int x = 0; x < D; x++) {\n                if (f[t][z][x] == '1') {\n                    seed ^= ((uint64_t)(t+1) << 48) ^ ((uint64_t)(z+1) << 32) ^ ((uint64_t)(x+1) << 16);\n                }\n                if (r[t][z][x] == '1') {\n                    seed ^= ((uint64_t)(t+3) << 40) ^ ((uint64_t)(z+5) << 24) ^ ((uint64_t)(x+7) << 8);\n                }\n            }\n        }\n    }\n    mt19937_64 rng(seed);\n\n    // Helper: shapesMatch for given node set and mapped big IDs\n    auto shapesMatch = [&](const vector<int>& nodes,\n                           const vector<int>& cellIdBigMapped) -> bool {\n        vector<int> idsSmall, idsBig;\n        idsSmall.reserve(nodes.size());\n        idsBig.reserve(nodes.size());\n        for (int idx : nodes) {\n            idsSmall.push_back(cellIdSmall[idx]);\n            idsBig.push_back(cellIdBigMapped[idx]);\n        }\n        auto repSmall = canonical_from_ids(idsSmall, preRot);\n        auto repBig   = canonical_from_ids(idsBig, preRot);\n        return repSmall == repBig;\n    };\n\n    // Clustering for a given mapping small->big\n    auto clusterForMapping = [&](const vector<int>& match)\n        -> pair<double, vector<vector<int>>> {\n        vector<int> cellIdBigMapped(S);\n        for (int i = 0; i < S; i++) {\n            cellIdBigMapped[i] = cellIdBigAll[ match[i] ];\n        }\n\n        vector<char> visited(S, false);\n        vector<vector<int>> clusters;\n        clusters.reserve(S);\n\n        for (int i = 0; i < S; i++) {\n            if (visited[i]) continue;\n\n            vector<int> cluster;\n            cluster.push_back(i);\n            visited[i] = true;\n\n            while (true) {\n                vector<int> cand;\n                for (int u : cluster) {\n                    for (int v : neighbors[u]) {\n                        if (!visited[v]) cand.push_back(v);\n                    }\n                }\n                sort(cand.begin(), cand.end());\n                cand.erase(unique(cand.begin(), cand.end()), cand.end());\n                bool added = false;\n                for (int v : cand) {\n                    vector<int> candidate = cluster;\n                    candidate.push_back(v);\n                    if (shapesMatch(candidate, cellIdBigMapped)) {\n                        cluster.push_back(v);\n                        visited[v] = true;\n                        added = true;\n                    }\n                }\n                if (!added) break;\n            }\n\n            clusters.push_back(cluster);\n        }\n\n        double sumInv = 0.0;\n        for (auto &cl : clusters) {\n            sumInv += 1.0 / (double)cl.size();\n        }\n        return {sumInv, clusters};\n    };\n\n    double bestScore = 1e100;\n    vector<vector<int>> bestClusters;\n    vector<int> bestMatch;\n\n    // ---------- Attempt 1: nearest-neighbor mapping ----------\n    {\n        vector<int> match(S, -1);\n        vector<char> used(T, false);\n        for (int i = 0; i < S; i++) {\n            const Coord &cs = posSmall[i];\n            int bestJ = -1;\n            int bestDist = INT_MAX;\n            for (int j = 0; j < T; j++) {\n                if (used[j]) continue;\n                const Coord &cb = posBigAll[j];\n                int dist = abs(cs.x - cb.x) + abs(cs.y - cb.y) + abs(cs.z - cb.z);\n                if (dist < bestDist) {\n                    bestDist = dist;\n                    bestJ = j;\n                }\n            }\n            if (bestJ == -1) {\n                bestJ = 0;\n                while (used[bestJ]) bestJ++;\n            }\n            match[i] = bestJ;\n            used[bestJ] = true;\n        }\n        auto res = clusterForMapping(match);\n        if (res.first < bestScore) {\n            bestScore = res.first;\n            bestClusters = move(res.second);\n            bestMatch = match;\n        }\n    }\n\n    // ---------- Attempt 2: lexicographic mapping by (x,y,z) ----------\n    {\n        vector<int> idxS(S), idxB(T);\n        iota(idxS.begin(), idxS.end(), 0);\n        iota(idxB.begin(), idxB.end(), 0);\n        sort(idxS.begin(), idxS.end(), [&](int a, int b) {\n            const Coord &A = posSmall[a], &B = posSmall[b];\n            if (A.x != B.x) return A.x < B.x;\n            if (A.y != B.y) return A.y < B.y;\n            return A.z < B.z;\n        });\n        sort(idxB.begin(), idxB.end(), [&](int a, int b) {\n            const Coord &A = posBigAll[a], &B = posBigAll[b];\n            if (A.x != B.x) return A.x < B.x;\n            if (A.y != B.y) return A.y < B.y;\n            return A.z < B.z;\n        });\n        vector<int> match(S, -1);\n        for (int k = 0; k < S; k++) {\n            match[idxS[k]] = idxB[k];\n        }\n        auto res = clusterForMapping(match);\n        if (res.first < bestScore) {\n            bestScore = res.first;\n            bestClusters = move(res.second);\n            bestMatch = match;\n        }\n    }\n\n    // ---------- Attempt 3: lexicographic mapping by (z,x,y) ----------\n    {\n        vector<int> idxS(S), idxB(T);\n        iota(idxS.begin(), idxS.end(), 0);\n        iota(idxB.begin(), idxB.end(), 0);\n        sort(idxS.begin(), idxS.end(), [&](int a, int b) {\n            const Coord &A = posSmall[a], &B = posSmall[b];\n            if (A.z != B.z) return A.z < B.z;\n            if (A.x != B.x) return A.x < B.x;\n            return A.y < B.y;\n        });\n        sort(idxB.begin(), idxB.end(), [&](int a, int b) {\n            const Coord &A = posBigAll[a], &B = posBigAll[b];\n            if (A.z != B.z) return A.z < B.z;\n            if (A.x != B.x) return A.x < B.x;\n            return A.y < B.y;\n        });\n        vector<int> match(S, -1);\n        for (int k = 0; k < S; k++) {\n            match[idxS[k]] = idxB[k];\n        }\n        auto res = clusterForMapping(match);\n        if (res.first < bestScore) {\n            bestScore = res.first;\n            bestClusters = move(res.second);\n            bestMatch = match;\n        }\n    }\n\n    // ---------- Random mappings ----------\n    const int RANDOM_ATTEMPTS = 8;\n    for (int att = 0; att < RANDOM_ATTEMPTS; att++) {\n        vector<int> smallOrder(S), bigPerm(T);\n        iota(smallOrder.begin(), smallOrder.end(), 0);\n        iota(bigPerm.begin(),  bigPerm.end(),  0);\n        shuffle(smallOrder.begin(), smallOrder.end(), rng);\n        shuffle(bigPerm.begin(),  bigPerm.end(),  rng);\n\n        vector<int> match(S, -1);\n        for (int k = 0; k < S; k++) {\n            int si = smallOrder[k];\n            int bi = bigPerm[k];\n            match[si] = bi;\n        }\n\n        auto res = clusterForMapping(match);\n        if (res.first < bestScore) {\n            bestScore = res.first;\n            bestClusters = move(res.second);\n            bestMatch = match;\n        }\n    }\n\n    // Now build final block assignments using bestMatch and bestClusters\n    vector<int> b0(D3, 0), b1(D3, 0);\n    int blockCount = 0;\n\n    auto setCell = [&](int puzzle, const Coord& c, int id) {\n        int idx = encode(c.x, c.y, c.z);\n        if (puzzle == 0) b0[idx] = id;\n        else b1[idx] = id;\n    };\n\n    // Shared blocks from clusters\n    for (const auto& cluster : bestClusters) {\n        ++blockCount;\n        for (int idx : cluster) {\n            const Coord &cs = posSmall[idx];\n            const Coord &cb = posBigAll[ bestMatch[idx] ];\n            setCell(small, cs, blockCount);\n            setCell(big,   cb, blockCount);\n        }\n    }\n\n    // Big-only blocks for cubes in big puzzle that are not shared\n    vector<char> usedBig(T, false);\n    for (int i = 0; i < S; i++) {\n        usedBig[ bestMatch[i] ] = true;\n    }\n    for (int j = 0; j < T; j++) {\n        if (usedBig[j]) continue;\n        ++blockCount;\n        const Coord &cb = posBigAll[j];\n        setCell(big, cb, blockCount);\n    }\n\n    // Output\n    cout << blockCount << '\\n';\n\n    auto output_grid = [&](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 idx = x * D * D + y * D + z;\n                    if (!first) cout << ' ';\n                    first = false;\n                    cout << b[idx];\n                }\n            }\n        }\n        cout << '\\n';\n    };\n\n    // Puzzle 0 grid then puzzle 1 grid\n    output_grid(b0);\n    output_grid(b1);\n\n    return 0;\n}","ahc020":"#include <bits/stdc++.h>\nusing namespace std;\nusing ll = long long;\n\nconst int MAXN = 105;   // N <= 100\nconst int MAXM = 305;   // M <= 300\nconst int MAXK = 5005;  // K <= 5000\nconst ll INFLL = (1LL << 60);\n\n// ----- Graph and data -----\nstruct Edge {\n    int u, v;\n    ll w;\n};\n\nint N, M, K;\nll vx[MAXN], vy[MAXN];\nll ax_arr[MAXK], ay_arr[MAXK];\nEdge edges[MAXM];\nvector<pair<int,int>> adj[MAXN];  // (to, edgeIndex)\n\n// All-pairs shortest paths (Dijkstra from each node)\nll distAll[MAXN][MAXN];    // distAll[s][v]\nint parEdge[MAXN][MAXN];   // parent edge index from s to v\n\n// Residents' candidate stations sorted by squared distance (within radius 5000)\nvector<pair<ll,int>> residentCand[MAXK];\n\n// For greedy coverage: residents each station can cover\nvector<int> stationRes[MAXN];  // stationRes[v] = list of residents k covered by v\n\n// ----- Steiner tree / evaluation buffers -----\nll maxd2_arr[MAXN];\nbool used_arr[MAXN];\nbool isReq[MAXN];\nbool usedEdgeUnion[MAXM];\nbool aliveEdge[MAXM];\n\nll keyArr[MAXN];\nint prArr[MAXN];\nbool inArr[MAXN];\nint reqNodesArr[MAXN];\nint metricU[MAXN], metricV[MAXN];\n\n// DSU for MST\nint dsu_p[MAXN], dsu_rnk[MAXN];\nvector<int> ordEdges;  // edges sorted by weight\n\ninline void dsu_reset(int n) {\n    for (int i = 1; i <= n; ++i) {\n        dsu_p[i] = i;\n        dsu_rnk[i] = 0;\n    }\n}\nint dsu_find(int x) {\n    return dsu_p[x] == x ? x : (dsu_p[x] = dsu_find(dsu_p[x]));\n}\nbool dsu_unite(int a, int b) {\n    a = dsu_find(a);\n    b = dsu_find(b);\n    if (a == b) return false;\n    if (dsu_rnk[a] < dsu_rnk[b]) swap(a, b);\n    dsu_p[b] = a;\n    if (dsu_rnk[a] == dsu_rnk[b]) ++dsu_rnk[a];\n    return true;\n}\n\n// Global best solution\nll bestCostGlobal = (1LL << 62);\nint P_best[MAXN];\nchar B_best[MAXM];\n\n// Temporary buffers for evaluation\nint P_tmp[MAXN];\nchar B_tmp[MAXM];\n\n// Evaluate solution for given open[1..N].\n// openFlag[v] = 1 if station v can be used as broadcast center.\n// Returns true if all residents can be covered (each within radius <=5000).\n// On success, fills P_out[1..N], B_out[0..M-1], and cost_out.\nbool evaluate_solution(const char openFlag[], ll &cost_out, int P_out[], char B_out[]) {\n    const ll R2max = 5000LL * 5000LL;\n\n    // Residents -> nearest open station within radius 5000\n    for (int i = 1; i <= N; ++i) {\n        maxd2_arr[i] = 0;\n        used_arr[i] = false;\n    }\n\n    for (int k = 0; k < K; ++k) {\n        bool assigned = false;\n        const auto &cand = residentCand[k];\n        for (size_t idx = 0; idx < cand.size(); ++idx) {\n            ll d2 = cand[idx].first;\n            if (d2 > R2max) break;\n            int v = cand[idx].second;\n            if (openFlag[v]) {\n                assigned = true;\n                used_arr[v] = true;\n                if (maxd2_arr[v] < d2) maxd2_arr[v] = d2;\n                break;\n            }\n        }\n        if (!assigned) {\n            // Some resident cannot be covered\n            return false;\n        }\n    }\n\n    // Compute P_i and broadcasting cost\n    ll broadcastCost = 0;\n    for (int i = 1; i <= N; ++i) {\n        if (maxd2_arr[i] > 0) {\n            long double sr = sqrtl((long double)maxd2_arr[i]);\n            ll r = (ll)sr;\n            if (r * r < maxd2_arr[i]) ++r;\n            if (r > 5000) r = 5000;\n            P_out[i] = (int)r;\n            broadcastCost += r * r;\n        } else {\n            P_out[i] = 0;\n        }\n    }\n\n    // Build required node set: station 1 + all stations with assigned residents\n    for (int i = 1; i <= N; ++i) isReq[i] = false;\n    int R = 0;\n    isReq[1] = true;\n    reqNodesArr[R++] = 1;\n    for (int i = 2; i <= N; ++i) {\n        if (used_arr[i]) {\n            isReq[i] = true;\n            reqNodesArr[R++] = i;\n        }\n    }\n\n    // No edges needed if only root is required\n    for (int j = 0; j < M; ++j) B_out[j] = 0;\n    if (R <= 1) {\n        cost_out = broadcastCost;\n        return true;\n    }\n\n    // Metric MST on required nodes (Prim) using distAll\n    for (int i = 0; i < R; ++i) {\n        keyArr[i] = INFLL;\n        prArr[i] = -1;\n        inArr[i] = false;\n    }\n    keyArr[0] = 0;\n    int metricCnt = 0;\n    for (int it = 0; it < R; ++it) {\n        int u = -1;\n        ll best = INFLL;\n        for (int i = 0; i < R; ++i) if (!inArr[i] && keyArr[i] < best) {\n            best = keyArr[i];\n            u = i;\n        }\n        if (u == -1) break;  // should not happen\n        inArr[u] = true;\n        if (prArr[u] != -1) {\n            metricU[metricCnt] = u;\n            metricV[metricCnt] = prArr[u];\n            ++metricCnt;\n        }\n        int vu = reqNodesArr[u];\n        for (int i = 0; i < R; ++i) if (!inArr[i]) {\n            int vv = reqNodesArr[i];\n            ll w = distAll[vu][vv];\n            if (w < keyArr[i]) {\n                keyArr[i] = w;\n                prArr[i] = u;\n            }\n        }\n    }\n\n    // Union of shortest paths for metric MST edges\n    for (int j = 0; j < M; ++j) usedEdgeUnion[j] = false;\n    for (int idx = 0; idx < metricCnt; ++idx) {\n        int a = reqNodesArr[metricU[idx]];\n        int b = reqNodesArr[metricV[idx]];\n        int cur = b;\n        while (cur != a) {\n            int eid = parEdge[a][cur];\n            if (eid < 0) break;  // safety\n            usedEdgeUnion[eid] = true;\n            const Edge &E = edges[eid];\n            cur = E.u ^ E.v ^ cur;\n        }\n    }\n\n    // MST over union edges (Steiner tree approximation)\n    dsu_reset(N);\n    for (int j = 0; j < M; ++j) aliveEdge[j] = false;\n    ll edgeCost = 0;\n    for (int idx = 0; idx < (int)ordEdges.size(); ++idx) {\n        int e = ordEdges[idx];\n        if (!usedEdgeUnion[e]) continue;\n        int u = edges[e].u;\n        int v = edges[e].v;\n        if (dsu_unite(u, v)) {\n            aliveEdge[e] = true;\n            edgeCost += edges[e].w;\n        }\n    }\n\n    for (int j = 0; j < M; ++j) {\n        B_out[j] = aliveEdge[j] ? 1 : 0;\n    }\n\n    cost_out = broadcastCost + edgeCost;\n    return true;\n}\n\n// Greedy removal: try to close stations in 'order'.\n// open[] is modified in place, curCost is updated if closures accepted.\n// covCount[k] is number of open stations covering resident k (using residentCand/stationRes).\nvoid greedy_removal(char open[], ll &curCost, const vector<int> &order, int covCount[]) {\n    for (int idx = 0; idx < (int)order.size(); ++idx) {\n        int v = order[idx];\n        if (!open[v]) continue;\n\n        // Quick coverage check: if some resident is only covered by v, can't close v\n        bool fail = false;\n        const auto &resList = stationRes[v];\n        for (int i = 0; i < (int)resList.size(); ++i) {\n            int k = resList[i];\n            if (covCount[k] == 1) {\n                fail = true;\n                break;\n            }\n        }\n        if (fail) continue;\n\n        // Tentatively close v\n        open[v] = 0;\n        for (int i = 0; i < (int)resList.size(); ++i) {\n            int k = resList[i];\n            --covCount[k];\n        }\n\n        ll cost2;\n        if (!evaluate_solution(open, cost2, P_tmp, B_tmp)) {\n            // Should not happen, but revert safely\n            open[v] = 1;\n            for (int i = 0; i < (int)resList.size(); ++i) {\n                int k = resList[i];\n                ++covCount[k];\n            }\n            continue;\n        }\n\n        // Update global best\n        if (cost2 < bestCostGlobal) {\n            bestCostGlobal = cost2;\n            for (int i = 1; i <= N; ++i) P_best[i] = P_tmp[i];\n            for (int j = 0; j < M; ++j) B_best[j] = B_tmp[j];\n        }\n\n        if (cost2 <= curCost) {\n            curCost = cost2;  // keep v closed\n        } else {\n            // Revert closure\n            open[v] = 1;\n            for (int i = 0; i < (int)resList.size(); ++i) {\n                int k = resList[i];\n                ++covCount[k];\n            }\n        }\n    }\n}\n\n// Greedy cover: choose a small set of stations covering all residents (ignoring edge cost).\n// Uses stationRes[v]; sets openCov[v] to 1 for chosen stations.\nvoid build_greedy_cover(char openCov[]) {\n    vector<char> covered(K, 0);\n    int uncovered = K;\n    for (int i = 1; i <= N; ++i) openCov[i] = 0;\n\n    while (uncovered > 0) {\n        int bestStation = -1;\n        int bestGain = -1;\n        for (int v = 1; v <= N; ++v) if (!openCov[v]) {\n            int gain = 0;\n            const auto &lis = stationRes[v];\n            for (int idx = 0; idx < (int)lis.size(); ++idx) {\n                int k = lis[idx];\n                if (!covered[k]) ++gain;\n            }\n            if (gain > bestGain) {\n                bestGain = gain;\n                bestStation = v;\n            }\n        }\n        if (bestStation == -1) break;  // safety; should not happen\n        openCov[bestStation] = 1;\n        const auto &lis = stationRes[bestStation];\n        for (int idx = 0; idx < (int)lis.size(); ++idx) {\n            int k = lis[idx];\n            if (!covered[k]) {\n                covered[k] = 1;\n                --uncovered;\n            }\n        }\n    }\n}\n\n// Simulated annealing on open[] and covCount[] starting from curCost.\n// Updates global best solution using evaluate_solution.\nvoid simulated_annealing(char open[], int covCount[], ll &curCost, int steps, mt19937_64 &rng) {\n    uniform_int_distribution<int> distV(1, N);\n    uniform_real_distribution<double> distReal(0.0, 1.0);\n\n    const double T0 = 1e7;\n    const double T1 = 1e4;\n\n    for (int step = 0; step < steps; ++step) {\n        int v = distV(rng);\n        const auto &resList = stationRes[v];\n\n        bool closing = (open[v] != 0);\n        if (closing) {\n            // Quick coverage check\n            bool fail = false;\n            for (int i = 0; i < (int)resList.size(); ++i) {\n                int k = resList[i];\n                if (covCount[k] == 1) {  // only v covers k\n                    fail = true;\n                    break;\n                }\n            }\n            if (fail) continue;\n\n            // Apply closure\n            open[v] = 0;\n            for (int i = 0; i < (int)resList.size(); ++i) {\n                int k = resList[i];\n                --covCount[k];\n            }\n\n            ll newCost;\n            if (!evaluate_solution(open, newCost, P_tmp, B_tmp)) {\n                // Should not happen; revert\n                open[v] = 1;\n                for (int i = 0; i < (int)resList.size(); ++i) {\n                    int k = resList[i];\n                    ++covCount[k];\n                }\n                continue;\n            }\n\n            if (newCost < bestCostGlobal) {\n                bestCostGlobal = newCost;\n                for (int i = 1; i <= N; ++i) P_best[i] = P_tmp[i];\n                for (int j = 0; j < M; ++j) B_best[j] = B_tmp[j];\n            }\n\n            ll delta = newCost - curCost;\n            double t = (double)step / (double)steps;\n            double T = T0 * pow(T1 / T0, t);\n            if (delta <= 0) {\n                curCost = newCost;\n            } else {\n                double prob = exp(- (double)delta / T);\n                double r = distReal(rng);\n                if (r < prob) {\n                    curCost = newCost;\n                } else {\n                    // Reject move: revert\n                    open[v] = 1;\n                    for (int i = 0; i < (int)resList.size(); ++i) {\n                        int k = resList[i];\n                        ++covCount[k];\n                    }\n                }\n            }\n        } else {\n            // Opening v\n            open[v] = 1;\n            for (int i = 0; i < (int)resList.size(); ++i) {\n                int k = resList[i];\n                ++covCount[k];\n            }\n\n            ll newCost;\n            if (!evaluate_solution(open, newCost, P_tmp, B_tmp)) {\n                // Should not happen; revert\n                open[v] = 0;\n                for (int i = 0; i < (int)resList.size(); ++i) {\n                    int k = resList[i];\n                    --covCount[k];\n                }\n                continue;\n            }\n\n            if (newCost < bestCostGlobal) {\n                bestCostGlobal = newCost;\n                for (int i = 1; i <= N; ++i) P_best[i] = P_tmp[i];\n                for (int j = 0; j < M; ++j) B_best[j] = B_tmp[j];\n            }\n\n            ll delta = newCost - curCost;\n            double t = (double)step / (double)steps;\n            double T = T0 * pow(T1 / T0, t);\n            if (delta <= 0) {\n                curCost = newCost;\n            } else {\n                double prob = exp(- (double)delta / T);\n                double r = distReal(rng);\n                if (r < prob) {\n                    curCost = newCost;\n                } else {\n                    // Reject move: revert\n                    open[v] = 0;\n                    for (int i = 0; i < (int)resList.size(); ++i) {\n                        int k = resList[i];\n                        --covCount[k];\n                    }\n                }\n            }\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> M >> K;\n    for (int i = 1; i <= N; ++i) {\n        cin >> vx[i] >> vy[i];\n    }\n    for (int j = 0; j < M; ++j) {\n        int u, v;\n        ll w;\n        cin >> u >> v >> w;\n        edges[j] = {u, v, w};\n    }\n    for (int k = 0; k < K; ++k) {\n        cin >> ax_arr[k] >> ay_arr[k];\n    }\n\n    // Build adjacency\n    for (int i = 1; i <= N; ++i) adj[i].clear();\n    for (int j = 0; j < M; ++j) {\n        int u = edges[j].u;\n        int v = edges[j].v;\n        adj[u].push_back({v, j});\n        adj[v].push_back({u, j});\n    }\n\n    // All-pairs shortest paths (Dijkstra from each source)\n    for (int s = 1; s <= N; ++s) {\n        for (int i = 1; i <= N; ++i) {\n            distAll[s][i] = INFLL;\n            parEdge[s][i] = -1;\n        }\n        distAll[s][s] = 0;\n        priority_queue<pair<ll,int>, vector<pair<ll,int>>, greater<pair<ll,int>>> pq;\n        pq.push({0, s});\n        while (!pq.empty()) {\n            auto [d, v] = pq.top();\n            pq.pop();\n            if (d != distAll[s][v]) continue;\n            for (auto &pr : adj[v]) {\n                int to = pr.first;\n                int eidx = pr.second;\n                ll nd = d + edges[eidx].w;\n                if (nd < distAll[s][to]) {\n                    distAll[s][to] = nd;\n                    parEdge[s][to] = eidx;\n                    pq.push({nd, to});\n                }\n            }\n        }\n    }\n\n    // Distance from 1 in the original graph\n    ll distFrom1[MAXN];\n    for (int i = 1; i <= N; ++i) {\n        distFrom1[i] = distAll[1][i];\n    }\n\n    // Precompute resident candidate lists (within radius 5000)\n    const ll R2max = 5000LL * 5000LL;\n    for (int k = 0; k < K; ++k) {\n        auto &cand = residentCand[k];\n        cand.clear();\n        cand.reserve(N);\n        for (int v = 1; v <= N; ++v) {\n            ll dx = vx[v] - ax_arr[k];\n            ll dy = vy[v] - ay_arr[k];\n            ll d2 = dx * dx + dy * dy;\n            if (d2 <= R2max) {\n                cand.emplace_back(d2, v);\n            }\n        }\n        sort(cand.begin(), cand.end(),\n             [](const pair<ll,int> &a, const pair<ll,int> &b){ return a.first < b.first; });\n    }\n\n    // Build stationRes (residents each station can cover)\n    for (int v = 1; v <= N; ++v) stationRes[v].clear();\n    for (int k = 0; k < K; ++k) {\n        const auto &cand = residentCand[k];\n        for (size_t idx = 0; idx < cand.size(); ++idx) {\n            int v = cand[idx].second;\n            stationRes[v].push_back(k);\n        }\n    }\n\n    // Precompute global edge order by weight\n    ordEdges.resize(M);\n    iota(ordEdges.begin(), ordEdges.end(), 0);\n    sort(ordEdges.begin(), ordEdges.end(),\n         [&](int a, int b){ return edges[a].w < edges[b].w; });\n\n    // Precompute removal order: vertices sorted by decreasing distFrom1\n    vector<int> order;\n    order.reserve(N);\n    for (int i = 1; i <= N; ++i) order.push_back(i);\n    sort(order.begin(), order.end(),\n         [&](int a, int b){ return distFrom1[a] > distFrom1[b]; });\n\n    mt19937_64 rng((uint64_t)chrono::steady_clock::now().time_since_epoch().count());\n\n    // Coverage counters per scenario\n    static int covCount1[MAXK], covCount2[MAXK];\n\n    // ----- Scenario 1: all stations open + greedy removal -----\n    static char open1[MAXN];\n    for (int i = 1; i <= N; ++i) open1[i] = 1;\n    for (int k = 0; k < K; ++k) {\n        covCount1[k] = (int)residentCand[k].size();  // all candidates open\n    }\n\n    ll cost1;\n    bool ok1 = evaluate_solution(open1, cost1, P_tmp, B_tmp);\n    if (!ok1) {\n        // Fallback: trivial legal solution (extremely unlikely needed)\n        for (int i = 1; i <= N; ++i) P_best[i] = 5000;\n        for (int j = 0; j < M; ++j) B_best[j] = 1;\n        bestCostGlobal = 0;\n        cout << P_best[1];\n        for (int i = 2; i <= N; ++i) cout << ' ' << P_best[i];\n        cout << '\\n';\n        if (M > 0) {\n            cout << (int)B_best[0];\n            for (int j = 1; j < M; ++j) cout << ' ' << (int)B_best[j];\n        }\n        cout << '\\n';\n        return 0;\n    }\n    bestCostGlobal = cost1;\n    for (int i = 1; i <= N; ++i) P_best[i] = P_tmp[i];\n    for (int j = 0; j < M; ++j) B_best[j] = B_tmp[j];\n\n    greedy_removal(open1, cost1, order, covCount1);\n\n    // ----- Scenario 2: greedy coverage + greedy removal -----\n    static char open2[MAXN];\n    build_greedy_cover(open2);\n\n    for (int k = 0; k < K; ++k) {\n        int cnt = 0;\n        const auto &cand = residentCand[k];\n        for (size_t idx = 0; idx < cand.size(); ++idx) {\n            int v = cand[idx].second;\n            if (open2[v]) ++cnt;\n        }\n        covCount2[k] = cnt;\n    }\n\n    ll cost2;\n    bool ok2 = evaluate_solution(open2, cost2, P_tmp, B_tmp);\n    if (ok2) {\n        if (cost2 < bestCostGlobal) {\n            bestCostGlobal = cost2;\n            for (int i = 1; i <= N; ++i) P_best[i] = P_tmp[i];\n            for (int j = 0; j < M; ++j) B_best[j] = B_tmp[j];\n        }\n        greedy_removal(open2, cost2, order, covCount2);\n    } else {\n        // In case greedy cover produced something odd, fall back to scenario 1 state\n        for (int i = 1; i <= N; ++i) open2[i] = open1[i];\n        for (int k = 0; k < K; ++k) covCount2[k] = covCount1[k];\n        cost2 = cost1;\n    }\n\n    // ----- Simulated annealing: two runs from different starts -----\n    const int SA_STEPS_PER_RUN = 2200;  // total ~4400 per case\n\n    simulated_annealing(open1, covCount1, cost1, SA_STEPS_PER_RUN, rng);\n    simulated_annealing(open2, covCount2, cost2, SA_STEPS_PER_RUN, rng);\n\n    // ----- Output best solution -----\n    cout << P_best[1];\n    for (int i = 2; i <= N; ++i) {\n        cout << ' ' << P_best[i];\n    }\n    cout << '\\n';\n\n    if (M > 0) {\n        cout << (int)B_best[0];\n        for (int j = 1; j < M; ++j) {\n            cout << ' ' << (int)B_best[j];\n        }\n    }\n    cout << '\\n';\n\n    return 0;\n}","ahc021":"#include <bits/stdc++.h>\nusing namespace std;\n\n// ---------------- Structures ----------------\n\nstruct Edge {\n    int u, v; // indices of nodes\n};\n\nstruct Op {\n    short x1, y1, x2, y2; // coordinates of swapped cells\n};\n\n// ---------------- Simple RNG (xorshift) ----------------\n\nstruct XorShift {\n    uint64_t x;\n    XorShift(uint64_t seed = 123456789) : x(seed) {}\n    uint64_t operator()() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return x;\n    }\n    int next_int(int n) { // 0..n-1\n        return (int)(operator()() % (uint64_t)n);\n    }\n};\n\n// ---------------- Violation computation ----------------\n\n// Compute total number of violations E\nint computeE(const vector<int> &a, const vector<Edge> &dEdges) {\n    int E = 0;\n    for (const auto &e : dEdges) {\n        if (a[e.u] > a[e.v]) ++E;\n    }\n    return E;\n}\n\n// Delta E for swapping two neighboring nodes u, v\nint deltaE_for_swap(const vector<int> &a, int u, int v,\n                    const vector<Edge> &dEdges,\n                    const vector<vector<int>> &nodeEdgeIds) {\n    int valU = a[u];\n    int valV = a[v];\n\n    int edges[16];\n    int cnt = 0;\n\n    // collect incident edges of u\n    for (int id : nodeEdgeIds[u]) {\n        edges[cnt++] = id;\n    }\n    // add incident edges of v, avoiding duplicates\n    for (int id : nodeEdgeIds[v]) {\n        bool dup = false;\n        for (int i = 0; i < cnt; ++i) {\n            if (edges[i] == id) {\n                dup = true;\n                break;\n            }\n        }\n        if (!dup) edges[cnt++] = id;\n    }\n\n    int delta = 0;\n    for (int i = 0; i < cnt; ++i) {\n        const Edge &e = dEdges[edges[i]];\n        int aIdx = e.u;\n        int bIdx = e.v;\n\n        int beforeA = a[aIdx];\n        int beforeB = a[bIdx];\n        bool before = (beforeA > beforeB);\n\n        int afterA = (aIdx == u ? valV : (aIdx == v ? valU : beforeA));\n        int afterB = (bIdx == u ? valV : (bIdx == v ? valU : beforeB));\n        bool after = (afterA > afterB);\n\n        delta += (int)after - (int)before;\n    }\n    return delta;\n}\n\n// ---------------- One heuristic run ----------------\n\n// Performs one run (starting from \"initial\"); returns operations and final E.\nvoid run_single(const vector<int> &initial,\n                const vector<Edge> &dEdges,\n                const vector<Edge> &adjEdges,\n                const vector<vector<int>> &nodeEdgeIds,\n                const vector<int> &posX,\n                const vector<int> &posY,\n                XorShift &rng,\n                vector<Op> &opsOut,\n                int &EOut) {\n    const int maxK = 10000;\n    vector<int> a = initial;\n\n    vector<Op> ops;\n    ops.reserve(maxK);\n\n    int K = 0;\n    int E = computeE(a, dEdges);\n\n    // ---------- Stage 1: bubble along parent-child edges (heapify-like) ----------\n    // Swap whenever parent > child, regardless of global E. This aggressively\n    // pushes large numbers downward and small numbers upward in the DAG.\n    const int limitStage1   = maxK * 8 / 10; // up to 8000 swaps\n    const int E_threshold   = 30;            // stop Stage1 early if already low\n    const int recalc_interval = 256;\n\n    if (E > 0) {\n        int dM = (int)dEdges.size();\n        bool done = false;\n        while (K < limitStage1 && !done) {\n            bool swappedPass = false;\n            int start = rng.next_int(dM); // random starting position\n\n            for (int t = 0; t < dM && K < limitStage1; ++t) {\n                const Edge &ed = dEdges[(start + t) % dM];\n                int u = ed.u;\n                int v = ed.v;\n                if (a[u] > a[v]) {\n                    swap(a[u], a[v]);\n                    ops.push_back(Op{(short)posX[u], (short)posY[u],\n                                     (short)posX[v], (short)posY[v]});\n                    ++K;\n                    swappedPass = true;\n\n                    if ((K % recalc_interval == 0) || K >= limitStage1) {\n                        E = computeE(a, dEdges);\n                        if (E == 0 || E <= E_threshold || K >= limitStage1) {\n                            done = true;\n                            break;\n                        }\n                    }\n                }\n            }\n            if (!swappedPass) {\n                // No violating parent-child edge => E = 0\n                E = 0;\n                done = true;\n                break;\n            }\n        }\n    }\n\n    // ---------- Stage 2: greedy + small random kicks on all adjacent swaps ----------\n    if (E != 0 && K < maxK) {\n        E = computeE(a, dEdges); // ensure E is up-to-date\n        int M = (int)adjEdges.size();\n\n        const int maxKickMoves  = 25; // maximum number of uphill moves\n        const int maxKickDelta  = 4;  // allow \u0394E up to +4 in kicks\n        const int maxKickTrials = 80; // trials to find a candidate edge per kick\n\n        int kicksUsed = 0;\n\n        while (K < maxK && E > 0) {\n            bool improved = false;\n            int start = rng.next_int(M);\n\n            // Greedy step: find any swap with delta < 0\n            for (int t = 0; t < M && K < maxK; ++t) {\n                const Edge &edge = adjEdges[(start + t) % M];\n                int u = edge.u;\n                int v = edge.v;\n\n                int delta = deltaE_for_swap(a, u, v, dEdges, nodeEdgeIds);\n                if (delta < 0) {\n                    swap(a[u], a[v]);\n                    ops.push_back(Op{(short)posX[u], (short)posY[u],\n                                     (short)posX[v], (short)posY[v]});\n                    ++K;\n                    E += delta;\n                    improved = true;\n                    break;\n                }\n            }\n\n            if (improved) continue;\n\n            // Local minimum w.r.t. single-swap E-improvement\n            if (kicksUsed >= maxKickMoves) break;\n\n            bool kicked = false;\n            for (int trials = 0; trials < maxKickTrials && K < maxK; ++trials) {\n                int idx = rng.next_int(M);\n                const Edge &edge = adjEdges[idx];\n                int u = edge.u;\n                int v = edge.v;\n\n                int delta = deltaE_for_swap(a, u, v, dEdges, nodeEdgeIds);\n\n                // Allow small uphill/neutral moves to escape local minima\n                if (delta <= maxKickDelta) {\n                    swap(a[u], a[v]);\n                    ops.push_back(Op{(short)posX[u], (short)posY[u],\n                                     (short)posX[v], (short)posY[v]});\n                    ++K;\n                    E += delta;\n                    if (delta > 0) ++kicksUsed;\n                    kicked = true;\n                    break;\n                }\n            }\n\n            if (!kicked) break; // couldn't find a reasonable kick move\n        }\n    }\n\n    opsOut.swap(ops);\n    EOut = E;\n}\n\n// ---------------- Main ----------------\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    const int N = 30;\n    const int numNodes = N * (N + 1) / 2;\n\n    // Read input and build id / coordinate mapping\n    vector<int> a0(numNodes);\n    vector<int> posX(numNodes), posY(numNodes);\n    vector<vector<int>> id(N);\n    int cur = 0;\n    for (int x = 0; x < N; ++x) {\n        id[x].resize(x + 1);\n        for (int y = 0; y <= x; ++y) {\n            id[x][y] = cur;\n            posX[cur] = x;\n            posY[cur] = y;\n            int v;\n            cin >> v;\n            a0[cur] = v;\n            ++cur;\n        }\n    }\n\n    // Build DAG edges (parent -> child)\n    vector<Edge> dEdges;\n    dEdges.reserve(2 * (N - 1) * N / 2);\n    for (int x = 0; x < N - 1; ++x) {\n        for (int y = 0; y <= x; ++y) {\n            int p = id[x][y];\n            int c1 = id[x + 1][y];\n            int c2 = id[x + 1][y + 1];\n            dEdges.push_back(Edge{p, c1});\n            dEdges.push_back(Edge{p, c2});\n        }\n    }\n\n    // For each node, list incident DAG edges (indices into dEdges)\n    vector<vector<int>> nodeEdgeIds(numNodes);\n    for (int ei = 0; ei < (int)dEdges.size(); ++ei) {\n        int u = dEdges[ei].u;\n        int v = dEdges[ei].v;\n        nodeEdgeIds[u].push_back(ei);\n        nodeEdgeIds[v].push_back(ei);\n    }\n\n    // Build adjacency edges of triangular grid (undirected)\n    const int dx[6] = {-1, -1, 0, 0, 1, 1};\n    const int dy[6] = {-1, 0, -1, 1, 0, 1};\n    vector<Edge> adjEdges;\n    adjEdges.reserve(3 * numNodes); // rough upper bound\n\n    for (int x = 0; x < N; ++x) {\n        for (int y = 0; y <= x; ++y) {\n            int u = id[x][y];\n            for (int dir = 0; dir < 6; ++dir) {\n                int nx = x + dx[dir];\n                int ny = y + dy[dir];\n                if (nx < 0 || nx >= N) continue;\n                if (ny < 0 || ny > nx) continue;\n                int v = id[nx][ny];\n                if (v > u) { // avoid duplicates (treat undirected)\n                    adjEdges.push_back(Edge{u, v});\n                }\n            }\n        }\n    }\n\n    // Seed RNG with time-based seed\n    uint64_t seed = chrono::high_resolution_clock::now().time_since_epoch().count();\n    XorShift rng(seed);\n\n    // Multiple restarts; keep the best result\n    const int MAX_RESTARTS = 6;\n    vector<Op> bestOps;\n    int bestE = INT_MAX;\n    int bestK = INT_MAX;\n\n    for (int iter = 0; iter < MAX_RESTARTS; ++iter) {\n        vector<Op> curOps;\n        int curE;\n        run_single(a0, dEdges, adjEdges, nodeEdgeIds, posX, posY,\n                   rng, curOps, curE);\n        int curK = (int)curOps.size();\n\n        if (curE < bestE || (curE == bestE && curK < bestK)) {\n            bestE = curE;\n            bestK = curK;\n            bestOps = std::move(curOps);\n        }\n    }\n\n    // Output\n    cout << bestOps.size() << '\\n';\n    for (const auto &op : bestOps) {\n        cout << op.x1 << ' ' << op.y1 << ' '\n             << op.x2 << ' ' << op.y2 << '\\n';\n    }\n\n    return 0;\n}","toyota2023summer-final":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Cell {\n    int r, c, dist;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int D, N;\n    if (!(cin >> D >> N)) return 0;\n\n    const int er = 0;\n    const int ec = (D - 1) / 2;\n\n    vector<vector<bool>> isObstacle(D, vector<bool>(D, false));\n    for (int k = 0; k < N; ++k) {\n        int r, c;\n        cin >> r >> c;\n        isObstacle[r][c] = true;\n    }\n\n    // 1. Static BFS distances from entrance (considering only obstacles).\n    vector<vector<int>> dist(D, vector<int>(D, -1));\n    {\n        queue<pair<int,int>> q;\n        dist[er][ec] = 0;\n        q.push({er, ec});\n        const int dr[4] = {1, -1, 0, 0};\n        const int dc[4] = {0, 0, 1, -1};\n        while (!q.empty()) {\n            auto [r, c] = q.front();\n            q.pop();\n            for (int d = 0; d < 4; ++d) {\n                int nr = r + dr[d];\n                int nc = c + dc[d];\n                if (nr < 0 || nr >= D || nc < 0 || nc >= D) continue;\n                if (isObstacle[nr][nc]) continue;\n                if (dist[nr][nc] != -1) continue;\n                dist[nr][nc] = dist[r][c] + 1;\n                q.push({nr, nc});\n            }\n        }\n    }\n\n    // 2. Collect storeable cells (non-entrance, non-obstacle) with distances.\n    vector<Cell> cells;\n    cells.reserve(D * D);\n    for (int r = 0; r < D; ++r) {\n        for (int c = 0; c < D; ++c) {\n            if (r == er && c == ec) continue;\n            if (isObstacle[r][c]) continue;\n            cells.push_back({r, c, dist[r][c]});\n        }\n    }\n    int M = (int)cells.size(); // D^2 - 1 - N\n\n    // 3. Sort cells by distance from entrance, then row, then column.\n    sort(cells.begin(), cells.end(), [](const Cell &a, const Cell &b) {\n        if (a.dist != b.dist) return a.dist < b.dist;\n        if (a.r != b.r) return a.r < b.r;\n        return a.c < b.c;\n    });\n\n    // Occupancy and labels.\n    vector<vector<bool>> hasContainer(D, vector<bool>(D, false));\n    vector<vector<int>>  labelGrid(D, vector<int>(D, -1));\n    vector<bool> usedIndex(M, false);          // whether cells[i] already has a container\n    vector<int> assignedIdxOfLabel(M, -1);     // index of cell for each label (if assigned)\n\n    // BFS to count reachable empty cells (excluding entrance) from entrance,\n    // with current hasContainer + isObstacle.\n    auto bfs_count_reachable_empty = [&]() -> int {\n        vector<vector<char>> vis(D, vector<char>(D, 0));\n        queue<pair<int,int>> q;\n        vis[er][ec] = 1;\n        q.push({er, ec});\n        const int dr[4] = {1, -1, 0, 0};\n        const int dc[4] = {0, 0, 1, -1};\n\n        while (!q.empty()) {\n            auto [r, c] = q.front();\n            q.pop();\n            for (int d = 0; d < 4; ++d) {\n                int nr = r + dr[d];\n                int nc = c + dc[d];\n                if (nr < 0 || nr >= D || nc < 0 || nc >= D) continue;\n                if (vis[nr][nc]) continue;\n                if (isObstacle[nr][nc]) continue;\n                if (hasContainer[nr][nc]) continue;\n                vis[nr][nc] = 1;\n                q.push({nr, nc});\n            }\n        }\n\n        int cnt = 0;\n        for (int r = 0; r < D; ++r) {\n            for (int c = 0; c < D; ++c) {\n                if (r == er && c == ec) continue;\n                if (isObstacle[r][c]) continue;\n                if (hasContainer[r][c]) continue;\n                if (vis[r][c]) ++cnt;\n            }\n        }\n        return cnt;\n    };\n\n    auto is_safe_index = [&](int idx, int placed) -> bool {\n        const Cell &cell = cells[idx];\n        int r = cell.r, c = cell.c;\n        hasContainer[r][c] = true;\n        int reachableEmpty = bfs_count_reachable_empty();\n        hasContainer[r][c] = false;\n        int emptiesAfter = M - (placed + 1);\n        return reachableEmpty == emptiesAfter;\n    };\n\n    // 4. Storage phase: choose safe index minimizing crossings, then |i - t|.\n    for (int step = 0; step < M; ++step) {\n        int t;\n        cin >> t;\n\n        int bestIdx   = -1;\n        int bestInv   = INT_MAX;\n        int bestDelta = INT_MAX;\n\n        for (int i = 0; i < M; ++i) {\n            if (usedIndex[i]) continue;\n            if (!is_safe_index(i, step)) continue;\n\n            // Count \"crossings\" with already-placed labels.\n            int inv = 0;\n            // Smaller labels placed deeper than i.\n            for (int l = 0; l < t; ++l) {\n                int idxL = assignedIdxOfLabel[l];\n                if (idxL != -1 && idxL > i) ++inv;\n            }\n            // Larger labels placed shallower than i.\n            for (int l = t + 1; l < M; ++l) {\n                int idxL = assignedIdxOfLabel[l];\n                if (idxL != -1 && idxL < i) ++inv;\n            }\n\n            int delta = abs(i - t);\n\n            if (inv < bestInv ||\n                (inv == bestInv && delta < bestDelta)) {\n                bestInv   = inv;\n                bestDelta = delta;\n                bestIdx   = i;\n            }\n        }\n\n        // Fallback: if somehow no safe index is found (should be extremely rare),\n        // pick any free index.\n        if (bestIdx == -1) {\n            for (int i = 0; i < M; ++i) {\n                if (!usedIndex[i]) {\n                    bestIdx = i;\n                    break;\n                }\n            }\n        }\n\n        usedIndex[bestIdx] = true;\n        assignedIdxOfLabel[t] = bestIdx;\n\n        int r = cells[bestIdx].r;\n        int c = cells[bestIdx].c;\n        hasContainer[r][c] = true;\n        labelGrid[r][c] = t;\n\n        cout << r << ' ' << c << '\\n' << flush;\n    }\n\n    // 5. Retrieval phase: always remove the smallest label currently accessible.\n    auto bfs_reachable_empty = [&](vector<vector<char>> &vis) {\n        vis.assign(D, vector<char>(D, 0));\n        queue<pair<int,int>> q;\n        vis[er][ec] = 1;\n        q.push({er, ec});\n        const int dr[4] = {1, -1, 0, 0};\n        const int dc[4] = {0, 0, 1, -1};\n        while (!q.empty()) {\n            auto [r, c] = q.front();\n            q.pop();\n            for (int d = 0; d < 4; ++d) {\n                int nr = r + dr[d];\n                int nc = c + dc[d];\n                if (nr < 0 || nr >= D || nc < 0 || nc >= D) continue;\n                if (vis[nr][nc]) continue;\n                if (isObstacle[nr][nc]) continue;\n                if (hasContainer[nr][nc]) continue;\n                vis[nr][nc] = 1;\n                q.push({nr, nc});\n            }\n        }\n    };\n\n    const int dr4[4] = {1, -1, 0, 0};\n    const int dc4[4] = {0, 0, 1, -1};\n    vector<vector<char>> vis;\n\n    for (int step = 0; step < M; ++step) {\n        bfs_reachable_empty(vis);\n\n        int bestLabel = INT_MAX;\n        int bestR = -1, bestC = -1;\n\n        for (int r = 0; r < D; ++r) {\n            for (int c = 0; c < D; ++c) {\n                if (!hasContainer[r][c]) continue;\n                bool accessible = false;\n                for (int d = 0; d < 4; ++d) {\n                    int nr = r + dr4[d];\n                    int nc = c + dc4[d];\n                    if (nr < 0 || nr >= D || nc < 0 || nc >= D) continue;\n                    if (isObstacle[nr][nc]) continue;\n                    if (hasContainer[nr][nc]) continue; // neighbor must be empty\n                    if (vis[nr][nc]) {\n                        accessible = true;\n                        break;\n                    }\n                }\n                if (!accessible) continue;\n                int lbl = labelGrid[r][c];\n                if (lbl < bestLabel) {\n                    bestLabel = lbl;\n                    bestR = r;\n                    bestC = c;\n                }\n            }\n        }\n\n        // Fallback (should not happen if storage kept empties connected).\n        if (bestR == -1) {\n            for (int r = 0; r < D && bestR == -1; ++r)\n                for (int c = 0; c < D && bestR == -1; ++c)\n                    if (hasContainer[r][c]) {\n                        bestR = r;\n                        bestC = c;\n                    }\n        }\n\n        cout << bestR << ' ' << bestC << '\\n';\n        hasContainer[bestR][bestC] = false;\n        labelGrid[bestR][bestC] = -1;\n    }\n\n    cout.flush();\n    return 0;\n}","ahc024":"#include <bits/stdc++.h>\nusing namespace std;\n\n// Constants (from problem)\nconst int MAXM = 100;\nconst int MAXN = 50;\n\nint n, m; // n = 50, m = 100\n\n// Grids\nvector<vector<int>> orig_grid;\nvector<vector<int>> cur_grid;\n\n// Original adjacency matrix: adj_orig[a][b] = true iff colors a and b are adjacent in the original map\nbool adj_orig[MAXM + 1][MAXM + 1];\n\n// Current adjacency as edge counts (for each unordered pair a<b): number of edges between colors a and b\nint edgeCount[MAXM + 1][MAXM + 1];\n\n// Number of outside-adjacency edges for each cell (i,j)\nint outsideAdjEdges[MAXN][MAXN];\n\n// Whether color c may touch color 0 (i.e., had adjacency with 0 in original)\nbool allowedZeroAdj[MAXM + 1];\n\n// Directions for 4-neighborhood\nconst int DX[4] = {1, -1, 0, 0};\nconst int DY[4] = {0, 0, 1, -1};\n\n// Compute adjacency matrix for a given grid (used only for the original grid)\nvoid computeAdj(const vector<vector<int>> &g, bool adj[MAXM + 1][MAXM + 1]) {\n    for (int i = 0; i <= m; i++) {\n        for (int j = 0; j <= m; j++) {\n            adj[i][j] = false;\n        }\n    }\n\n    // Internal adjacency in the grid\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            int a = g[i][j];\n            if (i + 1 < n) {\n                int b = g[i + 1][j];\n                if (a != b) adj[a][b] = adj[b][a] = true;\n            }\n            if (j + 1 < n) {\n                int b = g[i][j + 1];\n                if (a != b) adj[a][b] = adj[b][a] = true;\n            }\n        }\n    }\n\n    // Adjacency with outside (color 0) via boundary cells\n    for (int i = 0; i < n; i++) {\n        int c1 = g[i][0];\n        if (c1 != 0) adj[0][c1] = adj[c1][0] = true;\n        int c2 = g[i][n - 1];\n        if (c2 != 0) adj[0][c2] = adj[c2][0] = true;\n    }\n    for (int j = 1; j < n - 1; j++) {\n        int c1 = g[0][j];\n        if (c1 != 0) adj[0][c1] = adj[c1][0] = true;\n        int c2 = g[n - 1][j];\n        if (c2 != 0) adj[0][c2] = adj[c2][0] = true;\n    }\n}\n\n// Initialize edgeCount[a][b] from a given grid\nvoid initAdjCounts(const vector<vector<int>> &g) {\n    for (int i = 0; i <= m; i++) {\n        for (int j = 0; j <= m; j++) {\n            edgeCount[i][j] = 0;\n        }\n    }\n\n    // Internal edges in the grid\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            int a = g[i][j];\n            if (i + 1 < n) {\n                int b = g[i + 1][j];\n                if (a != b) {\n                    int x = min(a, b), y = max(a, b);\n                    edgeCount[x][y]++;\n                }\n            }\n            if (j + 1 < n) {\n                int b = g[i][j + 1];\n                if (a != b) {\n                    int x = min(a, b), y = max(a, b);\n                    edgeCount[x][y]++;\n                }\n            }\n        }\n    }\n\n    // Outside adjacency (between color 0 and each boundary cell's color)\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            int c = g[i][j];\n            int outE = outsideAdjEdges[i][j];\n            if (outE > 0 && c != 0) {\n                int x = 0, y = c;\n                // 0 < c always\n                edgeCount[x][y] += outE;\n            }\n        }\n    }\n}\n\n// Check that after removing cell (x, y) from color 'col',\n// the remaining cells of 'col' stay connected.\n//\n// cur[x][y] must already be recolored to something != col before calling.\nbool checkColorConnectivityAfterRemoval(int x, int y, int col, const vector<vector<int>> &grid) {\n    // Collect same-color neighbors of (x, y)\n    pair<int,int> nbrs[4];\n    int k = 0;\n    for (int dir = 0; dir < 4; dir++) {\n        int nx = x + DX[dir];\n        int ny = y + DY[dir];\n        if (nx < 0 || nx >= n || ny < 0 || ny >= n) continue;\n        if (grid[nx][ny] == col) {\n            nbrs[k++] = {nx, ny};\n        }\n    }\n    if (k <= 1) {\n        // Vertex with degree <=1 in its color component cannot be articulation\n        return true;\n    }\n\n    // BFS from first neighbor, check if we can reach all other neighbors\n    static vector<char> vis;\n    int N = n * n;\n    if ((int)vis.size() != N) vis.assign(N, 0);\n    else fill(vis.begin(), vis.end(), 0);\n\n    auto idx_of = [&](int xx, int yy) { return xx * n + yy; };\n\n    queue<pair<int,int>> q;\n    q.push(nbrs[0]);\n    vis[idx_of(nbrs[0].first, nbrs[0].second)] = 1;\n\n    bool reached[4] = {false,false,false,false};\n    reached[0] = true;\n    int reachedCnt = 1;\n\n    while (!q.empty() && reachedCnt < k) {\n        auto [cx, cy] = q.front(); q.pop();\n        for (int dir = 0; dir < 4; dir++) {\n            int nx = cx + DX[dir];\n            int ny = cy + DY[dir];\n            if (nx < 0 || nx >= n || ny < 0 || ny >= n) continue;\n            if (grid[nx][ny] != col) continue;\n            int idx = idx_of(nx, ny);\n            if (vis[idx]) continue;\n            vis[idx] = 1;\n            q.emplace(nx, ny);\n\n            // Check if this is one of the neighbors of (x,y)\n            for (int t = 1; t < k; t++) {\n                if (!reached[t] && nbrs[t].first == nx && nbrs[t].second == ny) {\n                    reached[t] = true;\n                    reachedCnt++;\n                    break;\n                }\n            }\n        }\n    }\n    return (reachedCnt == k);\n}\n\n// Try to change cell (x, y) from its current color to 0.\n// Constraints enforced:\n//  - keep at least one cell of each non-zero color\n//  - keep connectivity of the removed color\n//  - keep adjacency matrix identical to the original (via edgeCount checks)\n//  - keep 0-region connected (by requiring new 0 to be boundary or adjacent to an existing 0)\nbool tryChangeToZero(int x, int y,\n                     vector<vector<int>> &grid,\n                     vector<int> &countColor,\n                     mt19937_64 &rng) {\n    int oldCol = grid[x][y];\n    if (oldCol == 0) return false;\n    if (countColor[oldCol] <= 1) return false; // don't delete last cell of a color\n\n    // Condition for 0 connectivity: new 0 must be on boundary or adjacent to an existing 0\n    bool boundary = (x == 0 || x == n - 1 || y == 0 || y == n - 1);\n    bool adjZero = false;\n    if (!boundary) {\n        for (int dir = 0; dir < 4; dir++) {\n            int nx = x + DX[dir];\n            int ny = y + DY[dir];\n            if (nx < 0 || nx >= n || ny < 0 || ny >= n) continue;\n            if (grid[nx][ny] == 0) {\n                adjZero = true;\n                break;\n            }\n        }\n    }\n    if (!boundary && !adjZero) return false;\n\n    // Quick filter: if recoloring to 0 would put 0 adjacent to a color d that\n    // never touched 0 in the original, reject early.\n    for (int dir = 0; dir < 4; dir++) {\n        int nx = x + DX[dir];\n        int ny = y + DY[dir];\n        if (nx < 0 || nx >= n || ny < 0 || ny >= n) continue;\n        int d = grid[nx][ny];\n        if (!allowedZeroAdj[d]) {\n            return false;\n        }\n    }\n\n    // Count same-color neighbors (for potential connectivity check)\n    pair<int,int> nbrs[4];\n    int k = 0;\n    for (int dir = 0; dir < 4; dir++) {\n        int nx = x + DX[dir];\n        int ny = y + DY[dir];\n        if (nx < 0 || nx >= n || ny < 0 || ny >= n) continue;\n        if (grid[nx][ny] == oldCol) {\n            nbrs[k++] = {nx, ny};\n        }\n    }\n\n    // Tentatively recolor to 0\n    grid[x][y] = 0;\n    countColor[oldCol]--;\n    countColor[0]++;\n\n    bool ok = true;\n\n    // If degree in color component >= 2, check connectivity via neighbor test\n    if (k >= 2) {\n        if (!checkColorConnectivityAfterRemoval(x, y, oldCol, grid)) {\n            ok = false;\n        }\n    }\n\n    // If connectivity failed, revert and return\n    if (!ok) {\n        grid[x][y] = oldCol;\n        countColor[oldCol]++;\n        countColor[0]--;\n        return false;\n    }\n\n    // Incremental adjacency update\n    struct Delta {\n        int a, b, d;\n    };\n    static vector<Delta> deltas;\n    deltas.clear();\n\n    auto addDelta = [&](int a, int b, int delta) {\n        if (a == b) return; // we don't track same-color adjacency\n        if (a > b) swap(a, b);\n        for (auto &dd : deltas) {\n            if (dd.a == a && dd.b == b) {\n                dd.d += delta;\n                return;\n            }\n        }\n        deltas.push_back({a, b, delta});\n    };\n\n    int newCol = 0;\n\n    // Internal neighbors\n    for (int dir = 0; dir < 4; dir++) {\n        int nx = x + DX[dir];\n        int ny = y + DY[dir];\n        if (nx < 0 || nx >= n || ny < 0 || ny >= n) continue;\n        int d = grid[nx][ny]; // after recolor: grid[x][y] = 0; neighbor unchanged\n\n        // Remove old adjacency oldCol-d if existed\n        if (d != oldCol) {\n            int a = min(oldCol, d), b = max(oldCol, d);\n            addDelta(a, b, -1);\n        }\n        // Add new adjacency 0-d if d != 0\n        if (d != 0) {\n            int a = 0, b = d;\n            addDelta(a, b, +1);\n        }\n    }\n\n    // Outside adjacency edges\n    int outE = outsideAdjEdges[x][y];\n    if (outE > 0) {\n        // Before: oldCol had 'outE' adjacency edges with 0 (outside)\n        // After: 0-0 edges (ignored)\n        int a = 0, b = oldCol;\n        addDelta(a, b, -outE);\n    }\n\n    // Apply deltas to edgeCount\n    for (auto &dd : deltas) {\n        edgeCount[dd.a][dd.b] += dd.d;\n    }\n\n    // Check adjacency for affected pairs only\n    for (auto &dd : deltas) {\n        int a = dd.a, b = dd.b;\n        bool curAdj = (edgeCount[a][b] > 0);\n        if (curAdj != adj_orig[a][b]) {\n            ok = false;\n            break;\n        }\n    }\n\n    if (!ok) {\n        // Revert edge counts\n        for (auto &dd : deltas) {\n            edgeCount[dd.a][dd.b] -= dd.d;\n        }\n        // Revert color\n        grid[x][y] = oldCol;\n        countColor[oldCol]++;\n        countColor[0]--;\n        return false;\n    }\n\n    // Successful recolor\n    return true;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> n >> m;\n    orig_grid.assign(n, vector<int>(n));\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            cin >> orig_grid[i][j];\n        }\n    }\n\n    // Precompute outside adjacency edges for each cell\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            int cnt = 0;\n            if (i == 0) cnt++;\n            if (i == n - 1) cnt++;\n            if (j == 0) cnt++;\n            if (j == n - 1) cnt++;\n            outsideAdjEdges[i][j] = cnt;\n        }\n    }\n\n    // Compute original adjacency matrix\n    computeAdj(orig_grid, adj_orig);\n\n    // Colors that may touch 0\n    for (int c = 0; c <= m; c++) {\n        allowedZeroAdj[c] = adj_orig[0][c];\n    }\n    allowedZeroAdj[0] = true;\n\n    // Initialize current grid and color counts\n    cur_grid = orig_grid;\n    vector<int> countColor(m + 1, 0);\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            countColor[cur_grid[i][j]]++;\n        }\n    }\n\n    // Initialize edge counts\n    initAdjCounts(cur_grid);\n\n    // Random engine for shuffling\n    uint64_t seed = chrono::steady_clock::now().time_since_epoch().count();\n    mt19937_64 rng(seed);\n\n    const double TIME_LIMIT = 1.9;\n    auto start_time = chrono::steady_clock::now();\n\n    int Ncells = n * n;\n    vector<int> candidates;\n    vector<char> inQueue(Ncells, 0);\n\n    bool improved = true;\n    while (improved) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        if (elapsed > TIME_LIMIT) break;\n\n        improved = false;\n        candidates.clear();\n\n        // Collect frontier cells: non-zero cells that are on boundary or adjacent to 0\n        for (int x = 0; x < n; x++) {\n            for (int y = 0; y < n; y++) {\n                if (cur_grid[x][y] == 0) continue;\n                bool boundary = (x == 0 || x == n - 1 || y == 0 || y == n - 1);\n                bool adjZero = false;\n                if (!boundary) {\n                    for (int dir = 0; dir < 4; dir++) {\n                        int nx = x + DX[dir];\n                        int ny = y + DY[dir];\n                        if (nx < 0 || nx >= n || ny < 0 || ny >= n) continue;\n                        if (cur_grid[nx][ny] == 0) {\n                            adjZero = true;\n                            break;\n                        }\n                    }\n                }\n                if (boundary || adjZero) {\n                    candidates.push_back(x * n + y);\n                }\n            }\n        }\n\n        if (candidates.empty()) break;\n\n        shuffle(candidates.begin(), candidates.end(), rng);\n        fill(inQueue.begin(), inQueue.end(), 0);\n        deque<int> q;\n        for (int idx : candidates) {\n            if (!inQueue[idx]) {\n                inQueue[idx] = 1;\n                q.push_back(idx);\n            }\n        }\n\n        int iter = 0;\n        while (!q.empty()) {\n            if ((iter & 0xFF) == 0) { // check time every 256 steps\n                auto now2 = chrono::steady_clock::now();\n                double elapsed2 = chrono::duration<double>(now2 - start_time).count();\n                if (elapsed2 > TIME_LIMIT) break;\n            }\n            iter++;\n\n            int idx = q.front();\n            q.pop_front();\n            inQueue[idx] = 0;\n            int x = idx / n;\n            int y = idx % n;\n            if (cur_grid[x][y] == 0) continue;\n\n            if (tryChangeToZero(x, y, cur_grid, countColor, rng)) {\n                improved = true;\n                // Neighbors may now become removable\n                for (int dir = 0; dir < 4; dir++) {\n                    int nx = x + DX[dir];\n                    int ny = y + DY[dir];\n                    if (nx < 0 || nx >= n || ny < 0 || ny >= n) continue;\n                    if (cur_grid[nx][ny] == 0) continue;\n                    int idx2 = nx * n + ny;\n                    if (!inQueue[idx2]) {\n                        inQueue[idx2] = 1;\n                        if (rng() & 1) q.push_front(idx2);\n                        else q.push_back(idx2);\n                    }\n                }\n            }\n        }\n    }\n\n    // Output final grid\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            if (j) cout << ' ';\n            cout << cur_grid[i][j];\n        }\n        cout << '\\n';\n    }\n\n    return 0;\n}","ahc025":"#include <bits/stdc++.h>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, D, Q;\n    if (!(cin >> N >> D >> Q)) return 0;\n\n    // Store pairwise queries and results\n    vector<int> A(Q), B(Q);   // items in each query\n    vector<int> Y(Q);         // label: +1 if A[q] heavier, -1 if B[q] heavier, 0 if '='\n\n    vector<int> matchCount(N, 0);\n    static bool used[100][100];  // N <= 100, symmetric\n\n    mt19937 rng(712367821);\n\n    vector<int> order(N);\n    iota(order.begin(), order.end(), 0);\n\n    // ---- Query phase: perform exactly Q pairwise comparisons ----\n    for (int q = 0; q < Q; ++q) {\n        // Choose a pair (a, b) that keeps match counts balanced and avoids repeats\n        sort(order.begin(), order.end(), [&](int i, int j) {\n            if (matchCount[i] != matchCount[j]) return matchCount[i] < matchCount[j];\n            return i < j;\n        });\n\n        int a = -1, b = -1;\n        bool found = false;\n        int K = min(N, 10);\n\n        // Try to find a new pair among the K least-used items\n        for (int attempt = 0; attempt < K * 5 && !found; ++attempt) {\n            int ui = rng() % K;\n            int vi = rng() % K;\n            if (ui == vi) continue;\n            int i = order[ui];\n            int j = order[vi];\n            if (i > j) swap(i, j);\n            if (!used[i][j]) {\n                a = i;\n                b = j;\n                found = true;\n            }\n        }\n\n        // Fallback: random pairs avoiding used ones if possible\n        if (!found) {\n            for (int attempt = 0; attempt < N * N && !found; ++attempt) {\n                int i = rng() % N;\n                int j = rng() % N;\n                if (i == j) continue;\n                if (i > j) swap(i, j);\n                if (!used[i][j]) {\n                    a = i;\n                    b = j;\n                    found = true;\n                }\n            }\n        }\n\n        // If all pairs are used (very unlikely since Q < N(N-1)/2), just pick any pair\n        if (!found) {\n            do {\n                a = rng() % N;\n                b = rng() % N;\n            } while (a == b);\n            if (a > b) swap(a, b);\n        }\n\n        used[a][b] = used[b][a] = true;\n        matchCount[a]++;\n        matchCount[b]++;\n        A[q] = a;\n        B[q] = b;\n\n        // Output the query: 1 item on each side\n        cout << 1 << ' ' << 1 << ' ' << a << ' ' << b << '\\n';\n        cout.flush();\n\n        // Read the result\n        string res;\n        if (!(cin >> res)) return 0;\n        if (res[0] == '>') {\n            Y[q] = +1;  // A heavier than B\n        } else if (res[0] == '<') {\n            Y[q] = -1;  // B heavier than A\n        } else {\n            Y[q] = 0;   // '=' (very rare)\n        }\n    }\n\n    // ---- Offline rating (Bradley\u2013Terry style logistic regression) ----\n    vector<double> r(N, 0.0);  // ratings\n\n    const int ITER = 80;\n    const double base_eta = 0.5;\n\n    bool hasInfo = false;\n    for (int q = 0; q < Q; ++q) if (Y[q] != 0) { hasInfo = true; break; }\n\n    if (hasInfo) {\n        for (int iter = 0; iter < ITER; ++iter) {\n            double eta = base_eta / (1.0 + 0.1 * iter);\n            for (int q = 0; q < Q; ++q) {\n                int y = Y[q];\n                if (y == 0) continue;  // skip ties\n                int a = A[q], b = B[q];\n                double s = r[a] - r[b];\n                double z = (double) y * s;\n\n                // Avoid overflow; if z is large positive, gradient ~ 0\n                if (z > 40.0) continue;\n\n                double g;\n                if (z < -40.0) {\n                    g = (double) y;  // ~ y / (1 + 0) = y\n                } else {\n                    g = (double) y / (1.0 + std::exp(z));\n                }\n                double step = eta * g;\n                r[a] += step;\n                r[b] -= step;\n            }\n        }\n    }\n\n    // ---- Map ratings to approximate weights using exponential order statistics ----\n    vector<int> idx(N);\n    iota(idx.begin(), idx.end(), 0);\n    // Larger rating => heavier\n    sort(idx.begin(), idx.end(), [&](int i, int j) {\n        if (r[i] != r[j]) return r[i] > r[j];\n        return i < j;\n    });\n\n    vector<double> wAsc(N);  // expected Exp(lambda) order statistics, ascending\n    const double lambda = 1e-5;\n    double acc = 0.0;\n    for (int k = 1; k <= N; ++k) {\n        acc += 1.0 / (lambda * (N - k + 1));  // increment for kth smallest\n        wAsc[k - 1] = acc;\n    }\n    // Clamp to generation max (not strictly necessary, but harmless)\n    double wmax = 1e5 * (double) N / (double) D;\n    for (int i = 0; i < N; ++i) {\n        if (wAsc[i] > wmax) wAsc[i] = wmax;\n    }\n\n    vector<double> weight(N);\n    if (hasInfo) {\n        // Assign heaviest rating to largest expected weight\n        for (int pos = 0; pos < N; ++pos) {\n            int item = idx[pos];\n            double w_est = wAsc[N - 1 - pos];\n            weight[item] = w_est;\n        }\n    } else {\n        // Degenerate case: no information (almost impossible); use equal weights\n        for (int i = 0; i < N; ++i) weight[i] = 1.0;\n    }\n\n    // ---- Partitioning: greedy + local search ----\n\n    // Greedy initialization (largest weight first)\n    vector<int> assign(N, -1);\n    vector<double> binSum(D, 0.0);\n\n    vector<int> ord(N);\n    iota(ord.begin(), ord.end(), 0);\n    sort(ord.begin(), ord.end(), [&](int i, int j) {\n        if (weight[i] != weight[j]) return weight[i] > weight[j];\n        return i < j;\n    });\n\n    for (int id : ord) {\n        int bestBin = 0;\n        double bestSum = binSum[0];\n        for (int k = 1; k < D; ++k) {\n            if (binSum[k] < bestSum) {\n                bestSum = binSum[k];\n                bestBin = k;\n            }\n        }\n        assign[id] = bestBin;\n        binSum[bestBin] += weight[id];\n    }\n\n    // Local search (moves + swaps) on approximate objective\n    double totalW = 0.0;\n    for (double x : weight) totalW += x;\n    double target = totalW / D;\n    const double EPS = 1e-9;\n    const int MAX_ITERS_LS = 10000;\n\n    int guard = 0;\n    while (true) {\n        bool improved = false;\n\n        // Single-item moves\n        for (int i = 0; i < N && !improved; ++i) {\n            int ai = assign[i];\n            double wi = weight[i];\n            double sa = binSum[ai];\n            double oldA = (sa - target) * (sa - target);\n            for (int k = 0; k < D; ++k) {\n                if (k == ai) continue;\n                double sb = binSum[k];\n                double oldB = (sb - target) * (sb - target);\n                double newSa = sa - wi;\n                double newSb = sb + wi;\n                double newCost = (newSa - target) * (newSa - target)\n                               + (newSb - target) * (newSb - target);\n                double oldCost = oldA + oldB;\n                if (newCost + EPS < oldCost) {\n                    // Apply move\n                    binSum[ai] -= wi;\n                    binSum[k] += wi;\n                    assign[i] = k;\n                    improved = true;\n                    break;\n                }\n            }\n        }\n\n        // Pair swaps\n        if (!improved) {\n            for (int i = 0; i < N && !improved; ++i) {\n                for (int j = i + 1; j < N; ++j) {\n                    int ai = assign[i];\n                    int aj = assign[j];\n                    if (ai == aj) continue;\n                    double wi = weight[i];\n                    double wj = weight[j];\n                    double sa = binSum[ai];\n                    double sb = binSum[aj];\n                    double oldCost = (sa - target) * (sa - target)\n                                   + (sb - target) * (sb - target);\n                    double newSa = sa - wi + wj;\n                    double newSb = sb - wj + wi;\n                    double newCost = (newSa - target) * (newSa - target)\n                                   + (newSb - target) * (newSb - target);\n                    if (newCost + EPS < oldCost) {\n                        binSum[ai] = newSa;\n                        binSum[aj] = newSb;\n                        swap(assign[i], assign[j]);\n                        improved = true;\n                        break;\n                    }\n                }\n            }\n        }\n\n        if (!improved) break;\n        if (++guard > MAX_ITERS_LS) break;\n    }\n\n    // ---- Final output: assignments d_0 ... d_{N-1} ----\n    for (int i = 0; i < N; ++i) {\n        if (i) cout << ' ';\n        cout << assign[i];\n    }\n    cout << '\\n';\n    cout.flush();\n\n    return 0;\n}","ahc026":"#include <bits/stdc++.h>\nusing namespace std;\n\n// Simple xorshift RNG\nstruct XorShift {\n    unsigned long long x;\n    XorShift(unsigned long long seed = 88172645463325252ULL) : x(seed) {}\n    unsigned long long next() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return x;\n    }\n};\n\nstatic const int MAXV = 205;\n\n// Fenwick tree / BIT for counting values in a stack\nstruct BIT {\n    int n;\n    int bit[MAXV];\n\n    void init(int n_) {\n        n = n_;\n        memset(bit, 0, sizeof(bit));\n    }\n\n    void add(int idx, int delta) {\n        // values are in [1..n]\n        for (int i = idx; i <= n; i += i & -i) {\n            bit[i] += delta;\n        }\n    }\n\n    int sumPrefix(int idx) const {\n        if (idx > n) idx = n;\n        int s = 0;\n        for (int i = idx; i > 0; i -= i & -i) {\n            s += bit[i];\n        }\n        return s;\n    }\n};\n\n// One simulation run with given weights\nstatic pair<long long, vector<pair<int,int>>>\nrunOnce(const vector<vector<int>>& initStacks,\n        const vector<int>& initStackOf,\n        const vector<int>& initPosInStack,\n        const vector<BIT>& initBits,\n        int n, int m,\n        int wPairs, int wSize,\n        XorShift& rng)\n{\n    // Local copies of state\n    vector<vector<int>> stacks = initStacks;\n    vector<int> stackOf = initStackOf;\n    vector<int> posInStack = initPosInStack;\n    vector<BIT> bits = initBits;\n\n    vector<pair<int,int>> ops;\n    ops.reserve(2 * n + 10);\n    long long energy = 0;\n\n    vector<int> groupVals;\n    groupVals.reserve(n);\n\n    for (int v = 1; v <= n; v++) {\n        int s = stackOf[v];\n        int idx = posInStack[v];\n\n        // If v is not at the top, move the suffix above it\n        if (idx != (int)stacks[s].size() - 1) {\n            int startIdx = idx + 1;\n            int len = (int)stacks[s].size() - startIdx;\n\n            groupVals.clear();\n            groupVals.reserve(len);\n            for (int i = startIdx; i < (int)stacks[s].size(); i++) {\n                groupVals.push_back(stacks[s][i]);\n            }\n\n            // Choose destination stack using pair-count heuristic\n            int dest = -1;\n            long long bestScore = (1LL << 60);\n\n            for (int t = 0; t < m; t++) {\n                if (t == s) continue;\n                long long pairs = 0;\n                const BIT &bt = bits[t];\n                for (int x : groupVals) {\n                    pairs += bt.sumPrefix(x - 1);  // #u in T with u < x\n                }\n\n                long long score = (long long)wPairs * pairs\n                                  + (long long)wSize * (int)stacks[t].size();\n                // Small random noise for tie-breaking\n                score = score * 16 + (rng.next() & 15);\n\n                if (score < bestScore) {\n                    bestScore = score;\n                    dest = t;\n                }\n            }\n            if (dest == -1) {\n                // Fallback (should not happen as m >= 2)\n                dest = (s + 1) % m;\n            }\n\n            int pivot = stacks[s][startIdx];\n            ops.emplace_back(pivot, dest + 1);  // operation 1\n            energy += len + 1;\n\n            // Perform move: update stacks, positions, and BITs\n            auto &Ss = stacks[s];\n            auto &Dt = stacks[dest];\n            int oldSize = (int)Ss.size();\n            for (int i = startIdx; i < oldSize; i++) {\n                int box = Ss[i];\n                bits[s].add(box, -1);\n                bits[dest].add(box, 1);\n                stackOf[box] = dest;\n                posInStack[box] = (int)Dt.size();\n                Dt.push_back(box);\n            }\n            Ss.resize(startIdx);\n        }\n\n        // Now v should be on top; remove it\n        s = stackOf[v];\n        auto &S = stacks[s];\n        // S.back() should be v\n        ops.emplace_back(v, 0);  // operation 2\n        bits[s].add(v, -1);\n        S.pop_back();\n        stackOf[v] = -1;\n        posInStack[v] = -1;\n    }\n\n    return {energy, std::move(ops)};\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int n, m;\n    if (!(cin >> n >> m)) return 0;\n\n    vector<vector<int>> initStacks(m);\n    vector<int> initStackOf(n + 1);\n    vector<int> initPosInStack(n + 1);\n    vector<BIT> initBits(m);\n\n    int perStack = n / m;\n    for (int i = 0; i < m; i++) {\n        initStacks[i].resize(perStack);\n        initBits[i].init(n);\n        for (int j = 0; j < perStack; j++) {\n            int x;\n            cin >> x;\n            initStacks[i][j] = x;\n            initStackOf[x] = i;\n            initPosInStack[x] = j;\n            initBits[i].add(x, 1);\n        }\n    }\n\n    XorShift rng((unsigned long long)chrono::steady_clock::now()\n                     .time_since_epoch().count());\n\n    auto start = chrono::steady_clock::now();\n    auto endTime = start + chrono::milliseconds(1900);  // time guard\n\n    long long bestEnergy = (1LL << 60);\n    vector<pair<int,int>> bestOps;\n\n    int runId = 0;\n    while (true) {\n        int wPairs, wSize;\n\n        if (runId == 0) {\n            // Baseline deterministic-ish params\n            wPairs = 3;\n            wSize  = 1;\n        } else {\n            // Randomize weights for diversity\n            wPairs = 1 + (int)(rng.next() % 6);        // 1..6\n            wSize  = (int)(rng.next() % 7) - 2;        // -2..4\n        }\n\n        auto res = runOnce(initStacks, initStackOf, initPosInStack,\n                           initBits, n, m, wPairs, wSize, rng);\n        if (res.first < bestEnergy) {\n            bestEnergy = res.first;\n            bestOps = std::move(res.second);\n        }\n\n        runId++;\n        if (chrono::steady_clock::now() > endTime) break;\n    }\n\n    // Output best sequence of operations\n    for (auto &op : bestOps) {\n        cout << op.first << ' ' << op.second << '\\n';\n    }\n\n    return 0;\n}","ahc027":"#include <bits/stdc++.h>\nusing namespace std;\n\n// ---------- RNG (xorshift) ----------\nstatic uint64_t rng_state = 123456789ULL;\n\nstatic inline uint64_t xorshift64() {\n    uint64_t x = rng_state;\n    x ^= x << 7;\n    x ^= x >> 9;\n    rng_state = x;\n    return x;\n}\n\nstatic inline double rand_double() {\n    // [0,1)\n    return (xorshift64() & ((1ULL << 53) - 1)) * (1.0 / (1ULL << 53));\n}\n\n// ---------- Global structures ----------\nstruct Edge {\n    int to;\n    char dir; // 'U', 'D', 'L', 'R'\n};\n\nint N;\nint V; // N*N\nvector<string> hgrid; // (N-1) x N, between (i,j) and (i+1,j)\nvector<string> vgrid; // N x (N-1), between (i,j) and (i,j+1)\nvector<int> dflat; // N*N\nvector<vector<Edge>> adj;\n\nvector<int> dist_bfs;\nvector<int> parent_bfs;\nvector<char> pdir_bfs;        // direction parent -> node in BFS tree\nvector<vector<int>> children; // children in BFS tree\n\nstring coverMoves;            // covering tour (DFS over BFS tree)\nconstexpr int L_MAX = 100000;\n\n// ---------- Utility ----------\ninline char revdir(char c) {\n    if (c == 'U') return 'D';\n    if (c == 'D') return 'U';\n    if (c == 'L') return 'R';\n    return 'L'; // 'R'\n}\n\n// ---------- DFS on BFS tree to build covering tour ----------\nvoid dfs_cover(int u) {\n    for (int v : children[u]) {\n        char dir = pdir_bfs[v]; // parent -> child\n        coverMoves.push_back(dir);\n        dfs_cover(v);\n        coverMoves.push_back(revdir(dir)); // back to parent\n    }\n}\n\n// ---------- Append shortest path root -> v (using BFS tree) ----------\nvoid append_path_root_to(int v, string &route) {\n    const int root = 0;\n    if (v == root) return;\n    vector<char> tmp;\n    int cur = v;\n    while (cur != root) {\n        tmp.push_back(pdir_bfs[cur]); // parent -> cur\n        cur = parent_bfs[cur];\n    }\n    for (int i = (int)tmp.size() - 1; i >= 0; --i) {\n        route.push_back(tmp[i]);\n    }\n}\n\n// ---------- Append shortest path cur -> root (using BFS tree) ----------\nvoid append_path_to_root(int cur, string &route) {\n    const int root = 0;\n    while (cur != root) {\n        char c = revdir(pdir_bfs[cur]); // cur -> parent\n        route.push_back(c);\n        cur = parent_bfs[cur];\n    }\n}\n\n// ---------- Evaluate a route: exact average dirtiness ----------\nlong double evaluate_route(const string &route) {\n    int L = (int)route.size();\n    if (L == 0) return 0.0L;\n\n    static vector<int> firstVisit, lastVisit;\n    static vector<unsigned long long> sumLen2;\n\n    if ((int)firstVisit.size() != V) {\n        firstVisit.assign(V, 0);\n        lastVisit.assign(V, 0);\n        sumLen2.assign(V, 0ULL);\n    } else {\n        fill(firstVisit.begin(), firstVisit.end(), 0);\n        fill(lastVisit.begin(), lastVisit.end(), 0);\n        fill(sumLen2.begin(), sumLen2.end(), 0ULL);\n    }\n\n    int ci = 0, cj = 0; // start at (0,0)\n    for (int t = 1; t <= L; ++t) {\n        char mv = route[t - 1];\n        if      (mv == 'U') --ci;\n        else if (mv == 'D') ++ci;\n        else if (mv == 'L') --cj;\n        else                ++cj; // 'R'\n        int id = ci * N + cj;\n\n        if (lastVisit[id] == 0) {\n            firstVisit[id] = t;\n            lastVisit[id] = t;\n        } else {\n            int len = t - lastVisit[id];\n            unsigned long long l = (unsigned long long)len;\n            sumLen2[id] += l * (l - 1ULL);\n            lastVisit[id] = t;\n        }\n    }\n\n    unsigned long long totalScore = 0ULL;\n    for (int id = 0; id < V; ++id) {\n        if (lastVisit[id] == 0) continue; // should not happen (covering visits all)\n        int len = (firstVisit[id] + L) - lastVisit[id];\n        unsigned long long l = (unsigned long long)len;\n        sumLen2[id] += l * (l - 1ULL);\n\n        unsigned long long contrib = sumLen2[id] * (unsigned long long)dflat[id];\n        contrib >>= 1; // divide by 2 (len*(len-1) is always even)\n        totalScore += contrib;\n    }\n\n    return (long double)totalScore / (long double)L;\n}\n\n// ---------- Build one candidate route under a given weight vector ----------\nstring build_candidate_route(\n    int startCell,\n    const vector<double> &weight,\n    int Dmax\n) {\n    const int root = 0;\n\n    string route;\n    route.reserve(L_MAX + 10);\n\n    // Covering tour that starts and ends at root\n    route += coverMoves;\n\n    // Move root -> startCell if needed\n    if (startCell != root) {\n        append_path_root_to(startCell, route);\n    }\n\n    int prefixLen = (int)route.size();\n    int S = L_MAX - prefixLen - Dmax; // random-walk length upper bound\n    if (S < 0) S = 0;\n\n    int pos = startCell;\n\n    // Biased random walk\n    for (int step = 0; step < S; ++step) {\n        auto &nb = adj[pos];\n        int deg = (int)nb.size();\n        if (deg == 0) break; // should not happen (connected graph)\n\n        double sumw = 0.0;\n        for (const auto &e : nb) {\n            sumw += weight[e.to];\n        }\n        double r = rand_double() * sumw;\n        double acc = 0.0;\n        int chosen = deg - 1;\n        for (int k = 0; k < deg; ++k) {\n            acc += weight[nb[k].to];\n            if (acc >= r) { chosen = k; break; }\n        }\n        const auto &e = nb[chosen];\n        route.push_back(e.dir);\n        pos = e.to;\n    }\n\n    // Return to root\n    append_path_to_root(pos, route);\n\n    if ((int)route.size() > L_MAX) {\n        // Safety (shouldn't happen with S computed as above)\n        route.resize(L_MAX);\n    }\n\n    return route;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N;\n    hgrid.resize(N - 1);\n    for (int i = 0; i < N - 1; ++i) {\n        cin >> hgrid[i];\n    }\n    vgrid.resize(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> vgrid[i];\n    }\n\n    V = N * N;\n    dflat.assign(V, 0);\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int x;\n            cin >> x;\n            dflat[i * N + j] = x;\n        }\n    }\n\n    // Build adjacency list\n    adj.assign(V, {});\n    auto in_bounds = [&](int i, int j) {\n        return (0 <= i && i < N && 0 <= j && j < N);\n    };\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int id = i * N + j;\n            // Up\n            if (i > 0 && hgrid[i - 1][j] == '0') {\n                int to = (i - 1) * N + j;\n                adj[id].push_back({to, 'U'});\n            }\n            // Down\n            if (i < N - 1 && hgrid[i][j] == '0') {\n                int to = (i + 1) * N + j;\n                adj[id].push_back({to, 'D'});\n            }\n            // Left\n            if (j > 0 && vgrid[i][j - 1] == '0') {\n                int to = i * N + (j - 1);\n                adj[id].push_back({to, 'L'});\n            }\n            // Right\n            if (j < N - 1 && vgrid[i][j] == '0') {\n                int to = i * N + (j + 1);\n                adj[id].push_back({to, 'R'});\n            }\n        }\n    }\n\n    // Sort adjacency: neighbors with larger d first\n    for (int u = 0; u < V; ++u) {\n        sort(adj[u].begin(), adj[u].end(),\n            [&](const Edge &a, const Edge &b) {\n                return dflat[a.to] > dflat[b.to];\n            });\n    }\n\n    // BFS from root to build BFS tree and distances\n    const int root = 0;\n    dist_bfs.assign(V, -1);\n    parent_bfs.assign(V, -1);\n    pdir_bfs.assign(V, 0);\n    queue<int> q;\n    dist_bfs[root] = 0;\n    parent_bfs[root] = root;\n    q.push(root);\n    while (!q.empty()) {\n        int u = q.front(); q.pop();\n        for (const auto &e : adj[u]) {\n            int v = e.to;\n            if (dist_bfs[v] == -1) {\n                dist_bfs[v] = dist_bfs[u] + 1;\n                parent_bfs[v] = u;\n                pdir_bfs[v] = e.dir; // parent -> v\n                q.push(v);\n            }\n        }\n    }\n\n    int Dmax = 0;\n    for (int i = 0; i < V; ++i) {\n        if (dist_bfs[i] > Dmax) Dmax = dist_bfs[i];\n    }\n\n    // Build BFS tree children list\n    children.assign(V, {});\n    for (int v = 0; v < V; ++v) {\n        if (v == root) continue;\n        int p = parent_bfs[v];\n        if (p >= 0 && p < V) {\n            children[p].push_back(v);\n        }\n    }\n    // Sort children by descending d for a slightly better covering\n    for (int u = 0; u < V; ++u) {\n        sort(children[u].begin(), children[u].end(),\n             [&](int a, int b) {\n                 return dflat[a] > dflat[b];\n             });\n    }\n\n    // Build covering tour (edge-doubling DFS)\n    coverMoves.clear();\n    dfs_cover(root);\n\n    // Build anchor list: root + top-K high-d cells\n    int K = 12;\n    vector<int> idx(V);\n    iota(idx.begin(), idx.end(), 0);\n    sort(idx.begin(), idx.end(),\n         [&](int a, int b) {\n             return dflat[a] > dflat[b];\n         });\n    vector<int> anchors;\n    anchors.reserve(K + 1);\n    anchors.push_back(root);\n    for (int id : idx) {\n        if ((int)anchors.size() >= K + 1) break;\n        if (id == root) continue;\n        anchors.push_back(id);\n    }\n\n    // Exponent set for weights\n    vector<double> exps = {0.25, 0.5, 0.75, 1.0};\n    int E = (int)exps.size();\n\n    // Precompute weights for each exponent\n    vector<vector<double>> weights(E, vector<double>(V));\n    for (int ei = 0; ei < E; ++ei) {\n        double p = exps[ei];\n        for (int i = 0; i < V; ++i) {\n            weights[ei][i] = pow((double)dflat[i], p);\n        }\n    }\n\n    string bestRoute;\n    long double bestScore = numeric_limits<long double>::infinity();\n\n    // Baseline: covering tour only\n    {\n        string baseRoute = coverMoves;\n        long double sc = evaluate_route(baseRoute);\n        if (sc < bestScore) {\n            bestScore = sc;\n            bestRoute = std::move(baseRoute);\n        }\n    }\n\n    // Candidates: for each anchor and each exponent\n    for (int anchor : anchors) {\n        for (int ei = 0; ei < E; ++ei) {\n            string route = build_candidate_route(anchor, weights[ei], Dmax);\n            long double sc = evaluate_route(route);\n            if (sc < bestScore) {\n                bestScore = sc;\n                bestRoute = std::move(route);\n            }\n        }\n    }\n\n    cout << bestRoute << '\\n';\n    return 0;\n}","ahc028":"#include <bits/stdc++.h>\nusing namespace std;\n\n// Large enough INF for costs\nconst int INF = 1e9;\n\n// Compute overlap length: max k in [0..4] such that\n// suffix of a of length k == prefix of b of length k.\nint compute_overlap(const string &a, const string &b) {\n    const int L = 5;\n    for (int k = L - 1; k >= 1; --k) { // k=4..1\n        bool ok = true;\n        for (int i = 0; i < k; ++i) {\n            if (a[L - k + i] != b[i]) {\n                ok = false;\n                break;\n            }\n        }\n        if (ok) return k;\n    }\n    return 0;\n}\n\n// Local search: adjacent swaps to improve total overlap\nint local_search_adjacent_swaps(vector<int> &path, const vector<vector<int>> &ov) {\n    int M = (int)path.size();\n    if (M <= 1) return 0;\n\n    vector<int> edgeOv(max(0, M - 1));\n    int totalOv = 0;\n    for (int i = 0; i + 1 < M; ++i) {\n        int val = ov[path[i]][path[i + 1]];\n        edgeOv[i] = val;\n        totalOv += val;\n    }\n\n    if (M <= 2) {\n        return totalOv; // nothing to improve\n    }\n\n    bool improved = true;\n    while (improved) {\n        improved = false;\n        for (int i = 0; i < M - 1; ++i) {\n            int delta = 0;\n            if (i == 0) {\n                int A = path[0];\n                int B = path[1];\n                int C = path[2];\n\n                int old1 = ov[A][B];\n                int old2 = ov[B][C];\n\n                int new1 = ov[B][A];\n                int new2 = ov[A][C];\n\n                delta = (new1 + new2) - (old1 + old2);\n                if (delta > 0) {\n                    swap(path[0], path[1]);\n                    edgeOv[0] = new1;\n                    edgeOv[1] = new2;\n                    totalOv += delta;\n                    improved = true;\n                }\n            } else if (i == M - 2) {\n                int D = path[M - 3];\n                int A = path[M - 2];\n                int B = path[M - 1];\n\n                int old1 = ov[D][A];\n                int old2 = ov[A][B];\n\n                int new1 = ov[D][B];\n                int new2 = ov[B][A];\n\n                delta = (new1 + new2) - (old1 + old2);\n                if (delta > 0) {\n                    swap(path[M - 2], path[M - 1]);\n                    edgeOv[M - 3] = new1;\n                    edgeOv[M - 2] = new2;\n                    totalOv += delta;\n                    improved = true;\n                }\n            } else {\n                int D = path[i - 1];\n                int A = path[i];\n                int B = path[i + 1];\n                int C = path[i + 2];\n\n                int old1 = ov[D][A];\n                int old2 = ov[A][B];\n                int old3 = ov[B][C];\n\n                int new1 = ov[D][B];\n                int new2 = ov[B][A];\n                int new3 = ov[A][C];\n\n                delta = (new1 + new2 + new3) - (old1 + old2 + old3);\n                if (delta > 0) {\n                    swap(path[i], path[i + 1]);\n                    edgeOv[i - 1] = new1;\n                    edgeOv[i] = new2;\n                    edgeOv[i + 1] = new3;\n                    totalOv += delta;\n                    improved = true;\n                }\n            }\n        }\n    }\n    return totalOv;\n}\n\n// DP cost computation without parent reconstruction\nint compute_cost_no_parent(\n    const string &S,\n    const vector<vector<int>> &dist,\n    const vector<vector<int>> &cellsByLetter,\n    int startIdx\n) {\n    int L = (int)S.size();\n    if (L == 0) return 0;\n    int G = (int)dist.size();\n\n    vector<int> dpPrev(G, INF), dpCur(G, INF);\n    vector<int> prevCells, curCells;\n    prevCells.reserve(G);\n    curCells.reserve(G);\n\n    int c0 = S[0] - 'A';\n    const auto &cand0 = cellsByLetter[c0];\n    prevCells.clear();\n    for (int cell : cand0) {\n        dpPrev[cell] = dist[startIdx][cell];\n        prevCells.push_back(cell);\n    }\n\n    for (int pos = 1; pos < L; ++pos) {\n        int c = S[pos] - 'A';\n        const auto &cand = cellsByLetter[c];\n        curCells.clear();\n\n        for (int b : cand) {\n            int best = INF;\n            for (int a : prevCells) {\n                int val = dpPrev[a] + dist[a][b];\n                if (val < best) best = val;\n            }\n            dpCur[b] = best;\n            curCells.push_back(b);\n        }\n\n        dpPrev.swap(dpCur);\n        prevCells.swap(curCells);\n    }\n\n    int bestCost = INF;\n    for (int a : prevCells) {\n        if (dpPrev[a] < bestCost) bestCost = dpPrev[a];\n    }\n    return bestCost;\n}\n\n// DP with parent reconstruction: returns sequence of cell indices\nvector<int> compute_path_with_parent(\n    const string &S,\n    const vector<vector<int>> &dist,\n    const vector<vector<int>> &cellsByLetter,\n    int startIdx\n) {\n    int L = (int)S.size();\n    int G = (int)dist.size();\n    vector<int> result(L);\n    if (L == 0) return result;\n\n    vector<vector<int>> parent(L, vector<int>(G, -1));\n    vector<int> dpPrev(G, INF), dpCur(G, INF);\n    vector<int> prevCells, curCells;\n    prevCells.reserve(G);\n    curCells.reserve(G);\n\n    int c0 = S[0] - 'A';\n    const auto &cand0 = cellsByLetter[c0];\n    prevCells.clear();\n    for (int cell : cand0) {\n        dpPrev[cell] = dist[startIdx][cell];\n        parent[0][cell] = startIdx;\n        prevCells.push_back(cell);\n    }\n\n    for (int pos = 1; pos < L; ++pos) {\n        int c = S[pos] - 'A';\n        const auto &cand = cellsByLetter[c];\n        curCells.clear();\n\n        for (int b : cand) {\n            int best = INF;\n            int bestPrevCell = -1;\n            for (int a : prevCells) {\n                int val = dpPrev[a] + dist[a][b];\n                if (val < best) {\n                    best = val;\n                    bestPrevCell = a;\n                }\n            }\n            dpCur[b] = best;\n            parent[pos][b] = bestPrevCell;\n            curCells.push_back(b);\n        }\n\n        dpPrev.swap(dpCur);\n        prevCells.swap(curCells);\n    }\n\n    int bestCost = INF;\n    int bestLastCell = -1;\n    for (int a : prevCells) {\n        if (dpPrev[a] < bestCost) {\n            bestCost = dpPrev[a];\n            bestLastCell = a;\n        }\n    }\n\n    int cell = bestLastCell;\n    for (int pos = L - 1; pos >= 0; --pos) {\n        result[pos] = cell;\n        cell = parent[pos][cell]; // for pos=0 this becomes startIdx; we ignore it\n    }\n\n    return result;\n}\n\n// Build superstring S from path and overlap matrix\nstring build_superstring(const vector<int> &path, const vector<string> &words, const vector<vector<int>> &ov) {\n    int M = (int)path.size();\n    string S = words[path[0]];\n    for (int i = 1; i < M; ++i) {\n        int prev = path[i - 1];\n        int cur = path[i];\n        int k = ov[prev][cur];\n        S.append(words[cur].begin() + k, words[cur].end());\n    }\n    return S;\n}\n\n// Relocation local search (on a copy of path) guided by overlap,\n// but evaluated by full DP; updates global best string and cost.\nvoid relocate_local_search_T(\n    vector<int> path,                 // copy\n    const vector<vector<int>> &ov,\n    const vector<string> &words,\n    const vector<vector<int>> &dist,\n    const vector<vector<int>> &cellsByLetter,\n    int startIdx,\n    int &globalBestT,\n    string &globalBestS\n) {\n    int M = (int)path.size();\n    if (M <= 2) return;\n\n    // Compute initial total overlap\n    int totalOv = 0;\n    for (int i = 0; i + 1 < M; ++i) {\n        totalOv += ov[path[i]][path[i + 1]];\n    }\n\n    bool improved = true;\n    while (improved) {\n        improved = false;\n        for (int i = 0; i < M; ++i) {\n            int Xi = path[i];\n            int Li = (i > 0 ? path[i - 1] : -1);\n            int Ri = (i + 1 < M ? path[i + 1] : -1);\n\n            int wLiX = (i > 0 ? ov[Li][Xi] : 0);\n            int wXRi = (i + 1 < M ? ov[Xi][Ri] : 0);\n            int wLiRi = (i > 0 && i + 1 < M ? ov[Li][Ri] : 0);\n\n            for (int j = 0; j < M; ++j) {\n                if (j == i || j == i - 1) continue;\n                int Aj = path[j];\n                int Bj = (j + 1 < M ? path[j + 1] : -1);\n\n                int wAjBj = (j + 1 < M ? ov[Aj][Bj] : 0);\n                int wAjX = ov[Aj][Xi];\n                int wXBj = (j + 1 < M ? ov[Xi][Bj] : 0);\n\n                int delta = 0;\n                // remove X from its position\n                if (i > 0) delta -= wLiX;\n                if (i + 1 < M) delta -= wXRi;\n                if (i > 0 && i + 1 < M) delta += wLiRi;\n                // break insertion edge\n                if (j + 1 < M) delta -= wAjBj;\n                // add new edges\n                delta += wAjX;\n                if (j + 1 < M) delta += wXBj;\n\n                if (delta > 0) {\n                    totalOv += delta;\n\n                    // Apply relocation (careful with indices)\n                    int from = i;\n                    int to = j + 1;\n                    if (from < to) {\n                        // Removing earlier shifts target left by 1\n                        path.erase(path.begin() + from);\n                        to--;\n                        path.insert(path.begin() + to, Xi);\n                    } else {\n                        path.erase(path.begin() + from);\n                        path.insert(path.begin() + to, Xi);\n                    }\n\n                    // Evaluate this new path with DP\n                    string S = build_superstring(path, words, ov);\n                    int T = compute_cost_no_parent(S, dist, cellsByLetter, startIdx);\n                    if (T < globalBestT) {\n                        globalBestT = T;\n                        globalBestS = move(S);\n                    }\n\n                    improved = true;\n                    goto NEXT_ITERATION;\n                }\n            }\n        }\n        NEXT_ITERATION:;\n    }\n}\n\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M;\n    if (!(cin >> N >> M)) {\n        return 0;\n    }\n    int si, sj;\n    cin >> si >> sj;\n    vector<string> grid(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> grid[i];\n    }\n\n    vector<string> words(M);\n    for (int i = 0; i < M; ++i) {\n        cin >> words[i];\n    }\n\n    int G = N * N;\n    int startIdx = si * N + sj;\n\n    // Precompute cell coordinates\n    vector<pair<int,int>> coord(G);\n    for (int idx = 0; idx < G; ++idx) {\n        coord[idx] = {idx / N, idx % N};\n    }\n\n    // Cells by letter\n    vector<vector<int>> cellsByLetter(26);\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            char c = grid[i][j];\n            int idx = i * N + j;\n            cellsByLetter[c - 'A'].push_back(idx);\n        }\n    }\n\n    // Distance matrix\n    vector<vector<int>> dist(G, vector<int>(G));\n    for (int a = 0; a < G; ++a) {\n        int ax = coord[a].first;\n        int ay = coord[a].second;\n        for (int b = 0; b < G; ++b) {\n            int bx = coord[b].first;\n            int by = coord[b].second;\n            dist[a][b] = abs(ax - bx) + abs(ay - by) + 1;\n        }\n    }\n\n    // Overlap matrix between words\n    vector<vector<int>> ov(M, vector<int>(M, 0));\n    for (int i = 0; i < M; ++i) {\n        for (int j = 0; j < M; ++j) {\n            if (i == j) continue;\n            ov[i][j] = compute_overlap(words[i], words[j]);\n        }\n    }\n\n    mt19937 rng(712367821);\n\n    const int numRestarts = 400;  // increased for better exploration\n\n    vector<vector<int>> allPaths;\n    allPaths.reserve(numRestarts);\n    vector<int> allTOT(numRestarts, 0);\n    vector<int> allT(numRestarts, INF);\n\n    int globalBestT = INF;\n    string globalBestS;\n\n    vector<int> path(M);\n    vector<char> used(M);\n\n    for (int r = 0; r < numRestarts; ++r) {\n        fill(used.begin(), used.end(), 0);\n        int startNode = (int)(rng() % M);\n        path[0] = startNode;\n        used[startNode] = 1;\n\n        // Greedy path by overlap\n        for (int pos = 1; pos < M; ++pos) {\n            int u = path[pos - 1];\n            int bestOv = -1;\n            vector<int> cands;\n            cands.reserve(M);\n\n            for (int v = 0; v < M; ++v) {\n                if (used[v]) continue;\n                int o = ov[u][v];\n                if (o > bestOv) {\n                    bestOv = o;\n                    cands.clear();\n                    cands.push_back(v);\n                } else if (o == bestOv) {\n                    cands.push_back(v);\n                }\n            }\n\n            int v = cands[rng() % cands.size()];\n            path[pos] = v;\n            used[v] = 1;\n        }\n\n        // Local search with adjacent swaps\n        int totalOv = local_search_adjacent_swaps(path, ov);\n\n        // Build superstring and evaluate DP cost\n        string S = build_superstring(path, words, ov);\n        int T = compute_cost_no_parent(S, dist, cellsByLetter, startIdx);\n\n        allPaths.push_back(path);\n        allTOT[r] = totalOv;\n        allT[r] = T;\n\n        if (T < globalBestT) {\n            globalBestT = T;\n            globalBestS = move(S);\n        }\n    }\n\n    // Find best by DP cost and by overlap\n    int idxBestT = 0;\n    int idxBestOv = 0;\n    for (int r = 0; r < (int)allPaths.size(); ++r) {\n        if (allT[r] < allT[idxBestT]) idxBestT = r;\n        if (allTOT[r] > allTOT[idxBestOv]) idxBestOv = r;\n    }\n\n    // Extra refinement: relocation-based local search on best by overlap\n    {\n        vector<int> pathCopy = allPaths[idxBestOv];\n        relocate_local_search_T(pathCopy, ov, words, dist, cellsByLetter, startIdx, globalBestT, globalBestS);\n    }\n    // And also on best by DP cost (if different)\n    if (idxBestT != idxBestOv) {\n        vector<int> pathCopy = allPaths[idxBestT];\n        relocate_local_search_T(pathCopy, ov, words, dist, cellsByLetter, startIdx, globalBestT, globalBestS);\n    }\n\n    // Reconstruct final finger path for the best string\n    vector<int> bestCells = compute_path_with_parent(globalBestS, dist, cellsByLetter, startIdx);\n\n    int L = (int)bestCells.size();\n    for (int pos = 0; pos < L; ++pos) {\n        int idx = bestCells[pos];\n        int x = idx / N;\n        int y = idx % N;\n        cout << x << ' ' << y << '\\n';\n    }\n\n    return 0;\n}","ahc030":"#include <bits/stdc++.h>\nusing namespace std;\n\n// Representation of each field's shape\nstruct Field {\n    int H, W;                             // bounding box size\n    vector<pair<int,int>> offsets;        // shape cells relative to (0,0)\n    vector<char> occ;                     // occupancy grid H x W: 1 if cell in shape\n};\n\n// A single candidate placement of a field\nstruct Placement {\n    int di, dj;                           // translation offset on the N x N grid\n    bool alive;                           // still possible?\n    vector<int> cells;                    // global cell indices covered by this placement\n};\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)) {\n        return 0;\n    }\n    int N2 = N * N;\n\n    // Read field shapes\n    vector<Field> fields(M);\n    int totalOil = 0; // Sum of all d_k = total sum of v(i,j)\n    for (int k = 0; k < M; ++k) {\n        int d;\n        cin >> d;\n        totalOil += d;\n        vector<pair<int,int>> cells(d);\n        int max_i = 0, max_j = 0;\n        for (int t = 0; t < d; ++t) {\n            int x, y;\n            cin >> x >> y;\n            cells[t] = {x, y};\n            if (x > max_i) max_i = x;\n            if (y > max_j) max_j = y;\n        }\n        Field &f = fields[k];\n        f.H = max_i + 1;\n        f.W = max_j + 1;\n        f.offsets = move(cells);\n        f.occ.assign(f.H * f.W, 0);\n        for (auto &p : f.offsets) {\n            int x = p.first, y = p.second;\n            f.occ[x * f.W + y] = 1;\n        }\n    }\n\n    // Build all candidate placements and cover counts\n    vector<vector<Placement>> placements(M);\n    vector<vector<int>> coverCount(M, vector<int>(N2, 0)); // coverCount[k][cell]\n    vector<int> totalCandidates(M, 0);\n\n    for (int k = 0; k < M; ++k) {\n        Field &f = fields[k];\n        for (int di = 0; di <= N - f.H; ++di) {\n            for (int dj = 0; dj <= N - f.W; ++dj) {\n                Placement p;\n                p.di = di;\n                p.dj = dj;\n                p.alive = true;\n                p.cells.reserve(f.offsets.size());\n                for (auto &off : f.offsets) {\n                    int i = di + off.first;\n                    int j = dj + off.second;\n                    int cid = i * N + j;\n                    p.cells.push_back(cid);\n                    coverCount[k][cid]++;\n                }\n                placements[k].push_back(move(p));\n                totalCandidates[k]++;\n            }\n        }\n    }\n\n    // Observed v(i,j); -1 means not drilled yet\n    vector<int> observed(N2, -1);\n\n    // Candidate-based min/max possible v for each cell and elimination potential\n    vector<int> candMin(N2), candMax(N2), elimSum(N2);\n\n    // Inferred min/max after also applying global sum constraint\n    vector<int> infoMin(N2), infoMax(N2);\n\n    // Recompute candMin, candMax, elimSum from current candidate sets\n    auto recomputeCandidateMinMax = [&]() {\n        for (int c = 0; c < N2; ++c) {\n            int mn = 0, mx = 0, el = 0;\n            for (int k = 0; k < M; ++k) {\n                int tc = totalCandidates[k];\n                if (tc <= 0) continue; // safety\n                int cc = coverCount[k][c];\n                if (cc == tc) mn += 1;      // all placements of k cover c\n                if (cc > 0)    mx += 1;      // some placement covers c\n                if (cc > 0 && cc < tc) {\n                    // Potential elimination for this field at this cell\n                    el += min(cc, tc - cc);\n                }\n            }\n            candMin[c] = mn;\n            candMax[c] = mx;\n            elimSum[c] = el;\n        }\n    };\n\n    // Compute infoMin/infoMax by combining candidate-based bounds + observed + global sum\n    auto recomputeInfoBounds = [&]() {\n        long long Smin = 0, Smax = 0;\n        for (int c = 0; c < N2; ++c) {\n            infoMin[c] = candMin[c];\n            infoMax[c] = candMax[c];\n        }\n        // Override observed cells with exact values\n        for (int c = 0; c < N2; ++c) {\n            if (observed[c] != -1) {\n                infoMin[c] = infoMax[c] = observed[c];\n            }\n        }\n        for (int c = 0; c < N2; ++c) {\n            Smin += infoMin[c];\n            Smax += infoMax[c];\n        }\n\n        // Apply global sum constraint if consistent\n        if (Smin <= totalOil && totalOil <= Smax) {\n            for (int c = 0; c < N2; ++c) {\n                int L = infoMin[c];\n                int U = infoMax[c];\n                // T - sum_{j\u2260i} U_j = T - (Smax - U_i)\n                int newL = max(L, totalOil - int(Smax - U));\n                // T - sum_{j\u2260i} L_j = T - (Smin - L_i)\n                int newU = min(U, totalOil - int(Smin - L));\n                if (newL > newU) {\n                    // Should not occur; keep conservative single value\n                    newL = newU = max(0, min(L, U));\n                }\n                infoMin[c] = newL;\n                infoMax[c] = newU;\n            }\n        }\n        // else: something inconsistent; skip refinement to stay safe\n    };\n\n    int drilledCount = 0;\n\n    while (true) {\n        // Update candidate-based bounds and inferred bounds\n        recomputeCandidateMinMax();\n        recomputeInfoBounds();\n\n        // Check if all cells are already determined (infoMin == infoMax)\n        bool allKnown = true;\n        for (int c = 0; c < N2; ++c) {\n            if (infoMin[c] != infoMax[c]) {\n                allKnown = false;\n                break;\n            }\n        }\n        if (allKnown) break; // we know v(i,j) for every cell\n\n        // Safety: if we've drilled every cell, stop\n        if (drilledCount >= N2) break;\n\n        // Choose next cell to drill:\n        // among undrilled cells with infoMin < infoMax, pick the one with largest elimSum\n        int bestCell = -1;\n        int bestScore = -1;\n\n        for (int c = 0; c < N2; ++c) {\n            if (observed[c] != -1) continue;              // already drilled\n            if (infoMin[c] == infoMax[c]) continue;       // value already inferred\n            int score = elimSum[c];\n            if (score > bestScore) {\n                bestScore = score;\n                bestCell = c;\n            }\n        }\n\n        // Fallback: if no positive elimination score (should be rare), pick widest interval\n        if (bestCell == -1) {\n            int bestDiff = -1;\n            for (int c = 0; c < N2; ++c) {\n                if (observed[c] != -1) continue;\n                if (infoMin[c] == infoMax[c]) continue;\n                int diff = infoMax[c] - infoMin[c];\n                if (diff > bestDiff) {\n                    bestDiff = diff;\n                    bestCell = c;\n                }\n            }\n            if (bestCell == -1) break; // nothing left to drill\n        }\n\n        int bi = bestCell / N;\n        int bj = bestCell % N;\n\n        // Drill this cell\n        cout << \"q 1 \" << bi << ' ' << bj << '\\n' << flush;\n        int v_resp;\n        if (!(cin >> v_resp)) return 0;\n        observed[bestCell] = v_resp;\n        drilledCount++;\n\n        // Use this observation to prune candidate placements (using candidate-based bounds only)\n        int c = bestCell;\n        int observed_v = v_resp;\n\n        for (int k = 0; k < M; ++k) {\n            int tc_before = totalCandidates[k];\n            if (tc_before <= 0) continue; // safety\n\n            int cc = coverCount[k][c];\n            bool minCk = (cc == tc_before); // all placements of k cover c?\n            bool maxCk = (cc > 0);          // some placement covers c?\n\n            int min_without_k = candMin[c] - (minCk ? 1 : 0);\n            int max_without_k = candMax[c] - (maxCk ? 1 : 0);\n\n            Field &f = fields[k];\n\n            for (Placement &p : placements[k]) {\n                if (!p.alive) continue;\n\n                // Determine whether this placement covers cell c\n                int delta = 0;\n                int di = p.di, dj = p.dj;\n                int ci = c / N;\n                int cj = c % N;\n                int li = ci - di;\n                int lj = cj - dj;\n                if (0 <= li && li < f.H && 0 <= lj && lj < f.W) {\n                    if (f.occ[li * f.W + lj]) {\n                        delta = 1;\n                    }\n                }\n\n                int min_possible = delta + min_without_k;\n                int max_possible = delta + max_without_k;\n\n                if (observed_v < min_possible || observed_v > max_possible) {\n                    // This placement cannot be part of any configuration consistent\n                    // with this observation; remove it.\n                    p.alive = false;\n                    totalCandidates[k]--;\n                    // Update cover counts for all cells covered by this placement\n                    for (int cell2 : p.cells) {\n                        coverCount[k][cell2]--;\n                    }\n                }\n            }\n        }\n    }\n\n    // Final inference: recompute bounds one last time\n    recomputeCandidateMinMax();\n    recomputeInfoBounds();\n\n    vector<pair<int,int>> has_oil;\n    has_oil.reserve(N2);\n    for (int c = 0; c < N2; ++c) {\n        int val;\n        if (observed[c] != -1) {\n            val = observed[c];\n        } else {\n            // Undrilled but determined by constraints (infoMin == infoMax here)\n            val = infoMin[c];\n        }\n        if (val > 0) {\n            int i = c / N;\n            int j = c % N;\n            has_oil.emplace_back(i, j);\n        }\n    }\n\n    // Output the answer\n    cout << \"a \" << has_oil.size();\n    for (auto &p : has_oil) {\n        cout << ' ' << p.first << ' ' << p.second;\n    }\n    cout << '\\n' << flush;\n\n    // Read verdict (1 = correct, 0 = wrong); should be 1 if logic is correct.\n    int verdict;\n    if (!(cin >> verdict)) return 0;\n\n    return 0;\n}","ahc031":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Rect {\n    int i0, j0, i1, j1;\n};\n\n// Greedy \"water-filling\" stripes assignment.\n// dem: demands (areas) for the items (arbitrary order).\n// H  : height of the stripe region.\n// W  : total width limit.\n// Returns: (total shortage in cells, widths for each item in dem order).\npair<long long, vector<int>> stripes_assign(const vector<long long> &dem, int H, int W) {\n    int M = (int)dem.size();\n    vector<int> w(M, 1);      // each item gets at least width 1\n    int widthSum = M;\n    long long base = H;\n\n    // Max-heap of (residual shortage when width=1, index)\n    priority_queue<pair<long long,int>> pq;\n    for (int i = 0; i < M; i++) {\n        long long r = dem[i] - base;  // residual if width=1\n        if (r > 0) pq.emplace(r, i);\n    }\n\n    while (widthSum < W && !pq.empty()) {\n        auto [r, idx] = pq.top();\n        pq.pop();\n        if (r <= 0) break;\n        w[idx]++;\n        widthSum++;\n        r -= base;\n        if (r > 0) pq.emplace(r, idx);\n    }\n\n    long long def = 0;\n    for (int i = 0; i < M; i++) {\n        long long cap = 1LL * H * w[i];\n        long long diff = dem[i] - cap;\n        if (diff > 0) def += diff;\n    }\n\n    return {def, w};\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int W, D, N;\n    if (!(cin >> W >> D >> N)) return 0;\n\n    vector<vector<long long>> a(D, vector<long long>(N));\n    for (int d = 0; d < D; d++) {\n        for (int k = 0; k < N; k++) {\n            cin >> a[d][k];\n        }\n    }\n\n    for (int d = 0; d < D; d++) {\n        const auto &dem = a[d];\n\n        // -------- Candidate 1: baseline full-height stripes --------\n        auto [defStripe, widthsStripe] = stripes_assign(dem, W, W);\n\n        vector<Rect> rectStripe(N);\n        {\n            int x = 0;\n            for (int k = 0; k < N; k++) {\n                int w = widthsStripe[k];\n                int j0 = x;\n                int j1 = x + w;\n                if (j1 > W) j1 = W; // safety clamp (should not be needed)\n                x = j1;\n                rectStripe[k] = {0, j0, W, j1};\n            }\n        }\n\n        // -------- Candidate 2: improved hybrid layout --------\n        bool haveHybrid = false;\n        long long defHybrid = LLONG_MAX;\n        vector<Rect> rectHybrid(N);\n\n        // Split into small (<W) and big (>=W) reservations.\n        vector<int> smallIdx, bigIdx;\n        smallIdx.reserve(N);\n        bigIdx.reserve(N);\n        for (int k = 0; k < N; k++) {\n            if (dem[k] < W) smallIdx.push_back(k);\n            else bigIdx.push_back(k);\n        }\n\n        if (!smallIdx.empty()) {\n            // Pack small items into 1-row height bins using subset-sum DP.\n            int S = (int)smallIdx.size();\n            vector<int> smallRow(N, -1), smallJ0(N, 0);\n            vector<int> remaining = smallIdx;\n            vector<int> rowUsedWidth;\n            rowUsedWidth.reserve(S);\n\n            int row = 0;\n            while (!remaining.empty()) {\n                int M = (int)remaining.size();\n                // widths of remaining small items\n                vector<int> w(M);\n                for (int i = 0; i < M; i++) {\n                    w[i] = (int)dem[remaining[i]]; // dem[idx] < W, safe to cast\n                }\n\n                // DP: dp[i][j] = reachable using first i items with sum j\n                static bool dp[51][1001];\n                for (int i = 0; i <= M; i++)\n                    for (int j = 0; j <= W; j++)\n                        dp[i][j] = false;\n                dp[0][0] = true;\n\n                for (int i = 0; i < M; i++) {\n                    int wi = w[i];\n                    for (int j = 0; j <= W; j++) {\n                        if (!dp[i][j]) continue;\n                        dp[i+1][j] = true; // skip\n                        if (j + wi <= W) dp[i+1][j + wi] = true; // take\n                    }\n                }\n\n                int best = 0;\n                for (int j = W; j >= 1; j--) {\n                    if (dp[M][j]) { best = j; break; }\n                }\n                if (best == 0) {\n                    // Fallback: place at least one item (they all fit since w[i] < W)\n                    best = w[0];\n                }\n\n                // Reconstruct subset\n                vector<int> use(M, 0);\n                int j = best;\n                for (int i = M - 1; i >= 0; i--) {\n                    if (dp[i][j]) {\n                        use[i] = 0; // not used\n                    } else {\n                        use[i] = 1; // used\n                        j -= w[i];\n                    }\n                }\n\n                int curWidth = 0;\n                vector<int> newRemaining;\n                newRemaining.reserve(M);\n                for (int i = 0; i < M; i++) {\n                    int idx = remaining[i];\n                    if (use[i]) {\n                        int j0 = curWidth;\n                        int j1 = j0 + w[i];\n                        if (j1 > W) j1 = W; // safety\n                        smallRow[idx] = row;\n                        smallJ0[idx] = j0;\n                        curWidth = j1;\n                    } else {\n                        newRemaining.push_back(idx);\n                    }\n                }\n                remaining.swap(newRemaining);\n                rowUsedWidth.push_back(curWidth);\n                row++;\n            }\n\n            int H_small = row;\n            if (H_small <= W) {\n                if (bigIdx.empty()) {\n                    // Only small items: no big region, zero shortage.\n                    for (int idx : smallIdx) {\n                        int r = smallRow[idx];\n                        int j0 = smallJ0[idx];\n                        int j1 = j0 + (int)dem[idx];\n                        if (j1 > W) j1 = W; // safety\n                        rectHybrid[idx] = {r, j0, r + 1, j1};\n                    }\n                    defHybrid = 0;\n                    haveHybrid = true;\n                } else {\n                    int H_big = W - H_small;\n                    if (H_big > 0) {\n                        int Mbig = (int)bigIdx.size();\n                        vector<pair<long long,int>> bigList;\n                        bigList.reserve(Mbig);\n                        for (int idx : bigIdx) {\n                            bigList.emplace_back(dem[idx], idx);\n                        }\n                        sort(bigList.begin(), bigList.end(),\n                             [&](const pair<long long,int> &p1, const pair<long long,int> &p2) {\n                                 return p1.first < p2.first;\n                             });\n\n                        vector<long long> bigDemands(Mbig);\n                        vector<int> bigOrderIndex(Mbig);\n                        for (int i = 0; i < Mbig; i++) {\n                            bigDemands[i] = bigList[i].first;\n                            bigOrderIndex[i] = bigList[i].second;\n                        }\n\n                        auto [defBig, widthsBig] = stripes_assign(bigDemands, H_big, W);\n\n                        // Small rectangles\n                        for (int idx : smallIdx) {\n                            int r = smallRow[idx];\n                            int j0 = smallJ0[idx];\n                            int j1 = j0 + (int)dem[idx];\n                            if (j1 > W) j1 = W; // safety\n                            rectHybrid[idx] = {r, j0, r + 1, j1};\n                        }\n\n                        // Big rectangles as vertical stripes in [H_small, W)\n                        int x = 0;\n                        for (int i = 0; i < Mbig; i++) {\n                            int idx = bigOrderIndex[i];\n                            int w = widthsBig[i];\n                            int j0 = x;\n                            int j1 = x + w;\n                            if (j1 > W) j1 = W; // safety\n                            x = j1;\n                            rectHybrid[idx] = {H_small, j0, W, j1};\n                        }\n\n                        defHybrid = defBig; // smalls have zero shortage\n                        haveHybrid = true;\n                    }\n                }\n            }\n        }\n\n        // -------- Choose better candidate for this day --------\n        const vector<Rect> *chosenRects;\n        if (!haveHybrid || defStripe <= defHybrid) {\n            chosenRects = &rectStripe;\n        } else {\n            chosenRects = &rectHybrid;\n        }\n\n        // Output rectangles for this day in original reservation order.\n        for (int k = 0; k < N; k++) {\n            const Rect &r = (*chosenRects)[k];\n            int i0 = r.i0;\n            int j0 = r.j0;\n            int i1 = r.i1;\n            int j1 = r.j1;\n            // Final safety clamps\n            if (i0 < 0) i0 = 0;\n            if (i1 > W) i1 = W;\n            if (j0 < 0) j0 = 0;\n            if (j1 > W) j1 = W;\n            if (i0 >= i1) i1 = min(W, i0 + 1);\n            if (j0 >= j1) j1 = min(W, j0 + 1);\n            cout << i0 << ' ' << j0 << ' ' << i1 << ' ' << j1 << '\\n';\n        }\n    }\n\n    return 0;\n}","ahc032":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const long long MOD = 998244353LL;\n\n// Fast RNG (xorshift64)\nstruct XorShift64 {\n    uint64_t x;\n    XorShift64(uint64_t seed = 88172645463325252ull) {\n        x = seed ? seed : 88172645463325252ull;\n    }\n    inline uint64_t next() {\n        uint64_t y = x;\n        y ^= y << 7;\n        y ^= y >> 9;\n        return x = y;\n    }\n    inline int next_int(int n) { // 0..n-1\n        return (int)(next() % (uint64_t)n);\n    }\n    inline double next_double() { // [0,1)\n        return (next() >> 11) * (1.0 / (1ULL << 53));\n    }\n};\n\nstruct Op {\n    int m, p, q;\n};\n\nstruct CellChange {\n    int idx;\n    int oldv;\n    int newv;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    auto global_start = chrono::steady_clock::now();\n    const double TOTAL_LIMIT = 1.9; // safety margin under 2.0s\n\n    int N, M, K;\n    if (!(cin >> N >> M >> K)) return 0;\n    const int NN = N * N;\n\n    // Read initial board\n    vector<int> initial_board(NN);\n    long long initial_score = 0;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            long long v;\n            cin >> v;\n            v %= MOD;\n            initial_board[i * N + j] = (int)v;\n            initial_score += v;\n        }\n    }\n\n    // Read stamps s[m][3][3]\n    static int s[20][3][3];\n    for (int m = 0; m < M; ++m) {\n        for (int i = 0; i < 3; ++i) {\n            for (int j = 0; j < 3; ++j) {\n                long long v;\n                cin >> v;\n                v %= MOD;\n                s[m][i][j] = (int)v;\n            }\n        }\n    }\n\n    // Precompute all candidate operations (m, p, q)\n    vector<Op> all_ops;\n    all_ops.reserve(M * (N - 2) * (N - 2));\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                all_ops.push_back({m, p, q});\n            }\n        }\n    }\n    const int NUM_OPS = (int)all_ops.size(); // N=9,M=20 => 980\n\n    // Precompute for each op: its 9 cell indices and increment values\n    vector<array<int, 9>> op_cells(NUM_OPS);\n    vector<array<int, 9>> op_vals(NUM_OPS);\n    // For fast lookup: board-index -> pos (0..8) in op or -1\n    vector<array<int8_t, 81>> op_pos(NUM_OPS);\n\n    for (int op_id = 0; op_id < NUM_OPS; ++op_id) {\n        const Op &op = all_ops[op_id];\n        int m = op.m, p = op.p, q = op.q;\n        array<int, 9> cells;\n        array<int, 9> vals;\n        int t = 0;\n        for (int di = 0; di < 3; ++di) {\n            int r = p + di;\n            int base = r * N;\n            for (int dj = 0; dj < 3; ++dj) {\n                int c = q + dj;\n                int idx = base + c;\n                cells[t] = idx;\n                vals[t] = s[m][di][dj];\n                ++t;\n            }\n        }\n        op_cells[op_id] = cells;\n        op_vals[op_id] = vals;\n\n        auto &pm = op_pos[op_id];\n        pm.fill(-1);\n        for (int i = 0; i < 9; ++i) {\n            pm[cells[i]] = (int8_t)i;\n        }\n    }\n\n    // RNG\n    uint64_t seed = chrono::high_resolution_clock::now().time_since_epoch().count();\n    XorShift64 rng(seed);\n\n    // Working board and greedy initial solution\n    vector<int> board = initial_board;\n    long long cur_score = initial_score;\n    vector<int> cur_ops;\n    cur_ops.reserve(K);\n\n    // Greedy: repeatedly add best positive operation\n    for (int step = 0; step < K; ++step) {\n        long long best_delta = 0;\n        int best_id = -1;\n        for (int op_id = 0; op_id < NUM_OPS; ++op_id) {\n            const auto &cells = op_cells[op_id];\n            const auto &vals  = op_vals[op_id];\n            long long delta = 0;\n            for (int t = 0; t < 9; ++t) {\n                int d = vals[t];\n                if (d == 0) continue;\n                int idx = cells[t];\n                int x = board[idx];\n                int tmp = x + d;\n                if (tmp >= MOD) tmp -= MOD;\n                delta += tmp - x;\n            }\n            if (delta > best_delta) {\n                best_delta = delta;\n                best_id = op_id;\n            }\n        }\n        if (best_id == -1 || best_delta <= 0) break;\n\n        const auto &cells = op_cells[best_id];\n        const auto &vals  = op_vals[best_id];\n        for (int t = 0; t < 9; ++t) {\n            int d = vals[t];\n            if (d == 0) continue;\n            int idx = cells[t];\n            int x = board[idx];\n            int tmp = x + d;\n            if (tmp >= MOD) tmp -= MOD;\n            board[idx] = tmp;\n        }\n        cur_score += best_delta;\n        cur_ops.push_back(best_id);\n    }\n\n    long long best_score = cur_score;\n    vector<int> best_ops = cur_ops;\n\n    // Simulated Annealing\n    const double SA_TIME_LIMIT = 1.6; // seconds for SA\n    auto sa_start = chrono::steady_clock::now();\n    const double T0 = 1e9;\n    const double T_end = 1e6;\n    double T = T0;\n\n    CellChange changes[18]; // max affected cells in REPLACE\n    int iteration = 0;\n\n    while (true) {\n        if ((iteration & 1023) == 0) {\n            auto now = chrono::steady_clock::now();\n            double elapsed_sa = chrono::duration<double>(now - sa_start).count();\n            if (elapsed_sa >= SA_TIME_LIMIT) break;\n            double progress = elapsed_sa / SA_TIME_LIMIT;\n            if (progress > 1.0) progress = 1.0;\n            T = T0 + (T_end - T0) * progress;\n        }\n        ++iteration;\n\n        int L = (int)cur_ops.size();\n        int move_type; // 0=ADD,1=REMOVE,2=REPLACE\n        if (L == 0) {\n            move_type = 0;\n        } else if (L == K) {\n            move_type = (rng.next_int(2) == 0 ? 1 : 2);\n        } else {\n            int r = rng.next_int(100);\n            if (r < 40) move_type = 0;        // 40% ADD\n            else if (r < 80) move_type = 2;   // 40% REPLACE\n            else move_type = 1;               // 20% REMOVE\n        }\n\n        long long deltaScore = 0;\n        int chN = 0;\n\n        if (move_type == 0) { // ADD\n            int op_new = rng.next_int(NUM_OPS);\n            const auto &cells = op_cells[op_new];\n            const auto &vals  = op_vals[op_new];\n\n            deltaScore = 0;\n            chN = 0;\n            for (int t = 0; t < 9; ++t) {\n                int d = vals[t];\n                if (d == 0) continue;\n                int idx = cells[t];\n                int x = board[idx];\n                int tmp = x + d;\n                if (tmp >= MOD) tmp -= MOD;\n                if (tmp != x) {\n                    deltaScore += tmp - x;\n                    changes[chN++] = {idx, x, tmp};\n                }\n            }\n\n            bool accept;\n            if (deltaScore >= 0) {\n                accept = true;\n            } else if (-deltaScore > 20.0 * T) {\n                accept = false;\n            } else {\n                double prob = exp((double)deltaScore / T);\n                accept = (rng.next_double() < prob);\n            }\n\n            if (accept) {\n                for (int i = 0; i < chN; ++i) {\n                    board[changes[i].idx] = changes[i].newv;\n                }\n                cur_score += deltaScore;\n                cur_ops.push_back(op_new);\n                if (cur_score > best_score) {\n                    best_score = cur_score;\n                    best_ops = cur_ops;\n                }\n            }\n\n        } else if (move_type == 1) { // REMOVE\n            if (L == 0) continue;\n            int idx_op = rng.next_int(L);\n            int op_old = cur_ops[idx_op];\n            const auto &cells = op_cells[op_old];\n            const auto &vals  = op_vals[op_old];\n\n            deltaScore = 0;\n            chN = 0;\n            for (int t = 0; t < 9; ++t) {\n                int d = vals[t];\n                if (d == 0) continue;\n                int idx = cells[t];\n                int x = board[idx];\n                int tmp = x - d;\n                if (tmp < 0) tmp += MOD;\n                if (tmp != x) {\n                    deltaScore += tmp - x;\n                    changes[chN++] = {idx, x, tmp};\n                }\n            }\n\n            bool accept;\n            if (deltaScore >= 0) {\n                accept = true;\n            } else if (-deltaScore > 20.0 * T) {\n                accept = false;\n            } else {\n                double prob = exp((double)deltaScore / T);\n                accept = (rng.next_double() < prob);\n            }\n\n            if (accept) {\n                for (int i = 0; i < chN; ++i) {\n                    board[changes[i].idx] = changes[i].newv;\n                }\n                cur_score += deltaScore;\n                cur_ops[idx_op] = cur_ops.back();\n                cur_ops.pop_back();\n                if (cur_score > best_score) {\n                    best_score = cur_score;\n                    best_ops = cur_ops;\n                }\n            }\n\n        } else { // REPLACE\n            if (L == 0) continue;\n            int idx_old = rng.next_int(L);\n            int op_old = cur_ops[idx_old];\n            int op_new = rng.next_int(NUM_OPS);\n            if (op_new == op_old) continue;\n\n            const auto &cellsOld = op_cells[op_old];\n            const auto &valsOld  = op_vals[op_old];\n            const auto &cellsNew = op_cells[op_new];\n            const auto &valsNew  = op_vals[op_new];\n\n            int idxList[18];\n            int uc = 0;\n            for (int t = 0; t < 9; ++t) idxList[uc++] = cellsOld[t];\n            for (int t = 0; t < 9; ++t) {\n                int idx = cellsNew[t];\n                bool found = false;\n                for (int z = 0; z < uc; ++z) {\n                    if (idxList[z] == idx) { found = true; break; }\n                }\n                if (!found) idxList[uc++] = idx;\n            }\n\n            auto &posOldMap = op_pos[op_old];\n            auto &posNewMap = op_pos[op_new];\n\n            deltaScore = 0;\n            chN = 0;\n            for (int t = 0; t < uc; ++t) {\n                int idx = idxList[t];\n                int x = board[idx];\n\n                int posOld = (int)posOldMap[idx];\n                int d_old = (posOld >= 0 ? valsOld[posOld] : 0);\n                int posNew = (int)posNewMap[idx];\n                int d_new = (posNew >= 0 ? valsNew[posNew] : 0);\n                int diff = d_new - d_old;\n                if (diff == 0) continue;\n\n                int tmp = x + diff;\n                if (tmp < 0) tmp += MOD;\n                else if (tmp >= MOD) tmp -= MOD;\n\n                if (tmp != x) {\n                    deltaScore += tmp - x;\n                    changes[chN++] = {idx, x, tmp};\n                }\n            }\n\n            bool accept;\n            if (deltaScore >= 0) {\n                accept = true;\n            } else if (-deltaScore > 20.0 * T) {\n                accept = false;\n            } else {\n                double prob = exp((double)deltaScore / T);\n                accept = (rng.next_double() < prob);\n            }\n\n            if (accept) {\n                for (int i = 0; i < chN; ++i) {\n                    board[changes[i].idx] = changes[i].newv;\n                }\n                cur_score += deltaScore;\n                cur_ops[idx_old] = op_new;\n                if (cur_score > best_score) {\n                    best_score = cur_score;\n                    best_ops = cur_ops;\n                }\n            }\n        }\n    }\n\n    // Final deterministic local improvement from best SA solution\n    vector<int> sol_ops = best_ops;\n    vector<int> boardHC = initial_board;\n    long long scoreHC = initial_score;\n\n    // Rebuild boardHC from sol_ops\n    for (int op_id : sol_ops) {\n        const auto &cells = op_cells[op_id];\n        const auto &vals  = op_vals[op_id];\n        for (int t = 0; t < 9; ++t) {\n            int d = vals[t];\n            if (d == 0) continue;\n            int idx = cells[t];\n            int x = boardHC[idx];\n            int tmp = x + d;\n            if (tmp >= MOD) tmp -= MOD;\n            boardHC[idx] = tmp;\n            scoreHC += tmp - x;\n        }\n    }\n\n    // Hill climbing: best ADD / best REMOVE\n    const int MAX_HC_ITERS = 2000;\n    for (int iter = 0; iter < MAX_HC_ITERS; ++iter) {\n        auto now = chrono::steady_clock::now();\n        double elapsed_total = chrono::duration<double>(now - global_start).count();\n        if (elapsed_total >= TOTAL_LIMIT) break;\n\n        int L = (int)sol_ops.size();\n\n        long long bestAddDelta = 0;\n        int bestAddOp = -1;\n        if (L < K) {\n            for (int op_id = 0; op_id < NUM_OPS; ++op_id) {\n                const auto &cells = op_cells[op_id];\n                const auto &vals  = op_vals[op_id];\n                long long delta = 0;\n                for (int t = 0; t < 9; ++t) {\n                    int d = vals[t];\n                    if (d == 0) continue;\n                    int idx = cells[t];\n                    int x = boardHC[idx];\n                    int tmp = x + d;\n                    if (tmp >= MOD) tmp -= MOD;\n                    delta += tmp - x;\n                }\n                if (delta > bestAddDelta) {\n                    bestAddDelta = delta;\n                    bestAddOp = op_id;\n                }\n            }\n        }\n\n        long long bestRemDelta = 0;\n        int bestRemIdx = -1;\n        for (int i = 0; i < L; ++i) {\n            int op_id = sol_ops[i];\n            const auto &cells = op_cells[op_id];\n            const auto &vals  = op_vals[op_id];\n            long long delta = 0;\n            for (int t = 0; t < 9; ++t) {\n                int d = vals[t];\n                if (d == 0) continue;\n                int idx = cells[t];\n                int x = boardHC[idx];\n                int tmp = x - d;\n                if (tmp < 0) tmp += MOD;\n                delta += tmp - x;\n            }\n            if (delta > bestRemDelta) {\n                bestRemDelta = delta;\n                bestRemIdx = i;\n            }\n        }\n\n        if (bestAddDelta <= 0 && bestRemDelta <= 0) break;\n\n        if (bestAddDelta >= bestRemDelta && bestAddDelta > 0 && L < K && bestAddOp != -1) {\n            // Apply best ADD\n            const auto &cells = op_cells[bestAddOp];\n            const auto &vals  = op_vals[bestAddOp];\n            for (int t = 0; t < 9; ++t) {\n                int d = vals[t];\n                if (d == 0) continue;\n                int idx = cells[t];\n                int x = boardHC[idx];\n                int tmp = x + d;\n                if (tmp >= MOD) tmp -= MOD;\n                boardHC[idx] = tmp;\n                scoreHC += tmp - x;\n            }\n            sol_ops.push_back(bestAddOp);\n        } else if (bestRemDelta > 0 && bestRemIdx != -1) {\n            // Apply best REMOVE\n            int op_id = sol_ops[bestRemIdx];\n            const auto &cells = op_cells[op_id];\n            const auto &vals  = op_vals[op_id];\n            for (int t = 0; t < 9; ++t) {\n                int d = vals[t];\n                if (d == 0) continue;\n                int idx = cells[t];\n                int x = boardHC[idx];\n                int tmp = x - d;\n                if (tmp < 0) tmp += MOD;\n                boardHC[idx] = tmp;\n                scoreHC += tmp - x;\n            }\n            sol_ops[bestRemIdx] = sol_ops.back();\n            sol_ops.pop_back();\n        } else {\n            break;\n        }\n    }\n\n    // Extra random REPLACE hill-climb (only accept positive moves)\n    const int MAX_RR_TRIES = 200000;\n    int tries = 0;\n    while (tries < MAX_RR_TRIES) {\n        auto now = chrono::steady_clock::now();\n        double elapsed_total = chrono::duration<double>(now - global_start).count();\n        if (elapsed_total >= TOTAL_LIMIT) break;\n\n        int L = (int)sol_ops.size();\n        if (L == 0) break;\n\n        int idx_old = rng.next_int(L);\n        int op_old = sol_ops[idx_old];\n        int op_new = rng.next_int(NUM_OPS);\n        if (op_new == op_old) {\n            ++tries;\n            continue;\n        }\n\n        const auto &cellsOld = op_cells[op_old];\n        const auto &valsOld  = op_vals[op_old];\n        const auto &cellsNew = op_cells[op_new];\n        const auto &valsNew  = op_vals[op_new];\n        auto &posOldMap = op_pos[op_old];\n        auto &posNewMap = op_pos[op_new];\n\n        int idxList[18];\n        int uc = 0;\n        for (int t = 0; t < 9; ++t) idxList[uc++] = cellsOld[t];\n        for (int t = 0; t < 9; ++t) {\n            int idx = cellsNew[t];\n            bool found = false;\n            for (int z = 0; z < uc; ++z) {\n                if (idxList[z] == idx) { found = true; break; }\n            }\n            if (!found) idxList[uc++] = idx;\n        }\n\n        long long delta = 0;\n        for (int t = 0; t < uc; ++t) {\n            int idx = idxList[t];\n            int x = boardHC[idx];\n\n            int posOld = (int)posOldMap[idx];\n            int d_old = (posOld >= 0 ? valsOld[posOld] : 0);\n            int posNew = (int)posNewMap[idx];\n            int d_new = (posNew >= 0 ? valsNew[posNew] : 0);\n            int diff = d_new - d_old;\n            if (diff == 0) continue;\n\n            int tmp = x + diff;\n            if (tmp < 0) tmp += MOD;\n            else if (tmp >= MOD) tmp -= MOD;\n            delta += tmp - x;\n        }\n\n        if (delta > 0) {\n            // apply replace\n            for (int t = 0; t < uc; ++t) {\n                int idx = idxList[t];\n                int x = boardHC[idx];\n\n                int posOld = (int)posOldMap[idx];\n                int d_old = (posOld >= 0 ? valsOld[posOld] : 0);\n                int posNew = (int)posNewMap[idx];\n                int d_new = (posNew >= 0 ? valsNew[posNew] : 0);\n                int diff = d_new - d_old;\n                if (diff == 0) continue;\n\n                int tmp = x + diff;\n                if (tmp < 0) tmp += MOD;\n                else if (tmp >= MOD) tmp -= MOD;\n                boardHC[idx] = tmp;\n            }\n            scoreHC += delta;\n            sol_ops[idx_old] = op_new;\n            tries = 0; // reset since we improved\n        } else {\n            ++tries;\n        }\n    }\n\n    // Output final solution\n    cout << (int)sol_ops.size() << '\\n';\n    for (int op_id : sol_ops) {\n        const Op &op = all_ops[op_id];\n        cout << op.m << ' ' << op.p << ' ' << op.q << '\\n';\n    }\n\n    return 0;\n}","ahc033":"#include <bits/stdc++.h>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    if (!(cin >> N)) return 0; // N == 5\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    const int totalContainers = N * N; // 25\n\n    // For each container id, its receiving (spawn) row.\n    vector<int> spawnRow(totalContainers);\n    for (int r = 0; r < N; ++r) {\n        for (int j = 0; j < N; ++j) {\n            int id = A[r][j];\n            spawnRow[id] = r;\n        }\n    }\n\n    // Grid of containers: -1 = empty, otherwise container id.\n    vector<vector<int>> grid(N, vector<int>(N, -1));\n\n    // Container states\n    const int NOT_SPAWNED = 0, ON_GRID = 1, CARRIED = 2, DISPATCHED = 3;\n    vector<int> state(totalContainers, NOT_SPAWNED);\n\n    // Positions of containers when ON_GRID; (-1,-1) otherwise.\n    vector<int> posx(totalContainers, -1), posy(totalContainers, -1);\n\n    // Receiving gate spawn indices per row.\n    int next_idx[5] = {0, 0, 0, 0, 0};\n    bool spawn_done[5] = {false, false, false, false, false};\n\n    // Big crane (index 0)\n    int bx = 0, by = 0;   // position\n    int carry = -1;       // carried container id, -1 if none\n\n    // For each dispatch row r, next id to dispatch for that row.\n    int nextRowId[5];\n    for (int r = 0; r < N; ++r) nextRowId[r] = r * N;\n\n    // Operation strings for cranes\n    vector<string> ops(N);\n\n    int dispatched_count = 0;\n\n    auto stepTowards = [&](int gx, int gy) -> char {\n        if (bx < gx) return 'D';\n        if (bx > gx) return 'U';\n        if (by < gy) return 'R';\n        if (by > gy) return 'L';\n        return '.';\n    };\n\n    const int MAX_TURNS = 10000;\n    for (int t = 0; t < MAX_TURNS && dispatched_count < totalContainers; ++t) {\n        // Step 1: spawn containers at receiving gates\n        for (int r = 0; r < N; ++r) {\n            if (next_idx[r] < N &&\n                grid[r][0] == -1 &&\n                !(carry != -1 && bx == r && by == 0)) {\n                int id = A[r][next_idx[r]];\n                grid[r][0] = id;\n                state[id] = ON_GRID;\n                posx[id] = r;\n                posy[id] = 0;\n                ++next_idx[r];\n                if (next_idx[r] == N) spawn_done[r] = true;\n            }\n        }\n\n        // Step 2: decide big crane command\n        char big_cmd = '.';\n\n        if (dispatched_count >= totalContainers) {\n            big_cmd = '.';\n        } else if (carry != -1) {\n            // Carrying some container: if it is the next required for its row, dispatch it.\n            int rc = carry / N;\n            if (carry == nextRowId[rc]) {\n                int gx = rc;\n                int gy = N - 1;\n                if (bx == gx && by == gy) {\n                    big_cmd = 'Q';\n                } else {\n                    big_cmd = stepTowards(gx, gy);\n                }\n            } else {\n                // Not yet needed for its row -> store it.\n                int bestX = -1, bestY = -1;\n                int bestDist = INT_MAX;\n\n                // Prefer interior cells (y=1..N-2).\n                for (int x = 0; x < N; ++x) {\n                    for (int y = 1; y <= N - 2; ++y) {\n                        if (grid[x][y] == -1) {\n                            int dist = abs(bx - x) + abs(by - y);\n                            if (dist < bestDist) {\n                                bestDist = dist;\n                                bestX = x;\n                                bestY = y;\n                            }\n                        }\n                    }\n                }\n                // If none, use gates of rows whose spawn is complete.\n                if (bestX == -1) {\n                    for (int x = 0; x < N; ++x) {\n                        if (spawn_done[x] && grid[x][0] == -1) {\n                            int dist = abs(bx - x) + abs(by - 0);\n                            if (dist < bestDist) {\n                                bestDist = dist;\n                                bestX = x;\n                                bestY = 0;\n                            }\n                        }\n                    }\n                }\n                if (bestX == -1) {\n                    // Fallback: deliver this container to its dispatch gate (may break order very rarely).\n                    int gx = rc;\n                    int gy = N - 1;\n                    if (bx == gx && by == gy) {\n                        big_cmd = 'Q';\n                    } else {\n                        big_cmd = stepTowards(gx, gy);\n                    }\n                } else {\n                    if (bx == bestX && by == bestY) {\n                        big_cmd = 'Q';\n                    } else {\n                        big_cmd = stepTowards(bestX, bestY);\n                    }\n                }\n            }\n        } else {\n            // Not carrying: choose best next target container among rows.\n            int bestId = -1;\n            int bestCost = INT_MAX;\n\n            for (int r = 0; r < N; ++r) {\n                // Ensure nextRowId[r] is not behind (for safety).\n                while (nextRowId[r] < (r + 1) * N &&\n                       state[nextRowId[r]] == DISPATCHED) {\n                    ++nextRowId[r];\n                }\n                int id = nextRowId[r];\n                if (id >= (r + 1) * N) continue; // this row done\n\n                if (state[id] == ON_GRID) {\n                    int cx = posx[id], cy = posy[id];\n                    if (cx == -1) continue; // safety\n                    int dist = abs(bx - cx) + abs(by - cy);\n                    int cost = dist; // no penalty\n                    if (cost < bestCost) {\n                        bestCost = cost;\n                        bestId = id;\n                    }\n                } else if (state[id] == NOT_SPAWNED) {\n                    int sr = spawnRow[id];\n                    int distGate = abs(bx - sr) + abs(by - 0);\n                    int extra = 7; // penalty for not yet spawned\n                    if (grid[sr][0] == -1) {\n                        // gate empty: we'll have to wait for spawn\n                        extra += 1;\n                    } else {\n                        // gate occupied: we need to clear it\n                        // approximate extra work by small constant\n                        extra += 0;\n                    }\n                    int cost = distGate + extra;\n                    if (cost < bestCost) {\n                        bestCost = cost;\n                        bestId = id;\n                    }\n                }\n            }\n\n            if (bestId == -1) {\n                big_cmd = '.';\n            } else if (state[bestId] == ON_GRID) {\n                int cx = posx[bestId], cy = posy[bestId];\n                if (bx == cx && by == cy) {\n                    big_cmd = 'P';\n                } else {\n                    big_cmd = stepTowards(cx, cy);\n                }\n            } else if (state[bestId] == NOT_SPAWNED) {\n                int sr = spawnRow[bestId];\n                if (grid[sr][0] != -1) {\n                    // Clear blocking container from its gate.\n                    if (bx == sr && by == 0) {\n                        big_cmd = 'P';\n                    } else {\n                        big_cmd = stepTowards(sr, 0);\n                    }\n                } else {\n                    // Gate empty but id not yet spawned: move towards gate or wait.\n                    if (bx == sr && by == 0) {\n                        big_cmd = '.';\n                    } else {\n                        big_cmd = stepTowards(sr, 0);\n                    }\n                }\n            } else {\n                big_cmd = '.';\n            }\n        }\n\n        // Small cranes: bomb at t=0, then idle.\n        char small_cmd = (t == 0 ? 'B' : '.');\n        ops[0].push_back(big_cmd);\n        for (int i = 1; i < N; ++i) ops[i].push_back(small_cmd);\n\n        // Apply big crane action\n        if (big_cmd == 'P') {\n            if (carry == -1 && grid[bx][by] != -1) {\n                carry = grid[bx][by];\n                state[carry] = CARRIED;\n                posx[carry] = -1;\n                posy[carry] = -1;\n                grid[bx][by] = -1;\n            }\n        } else if (big_cmd == 'Q') {\n            if (carry != -1 && grid[bx][by] == -1) {\n                grid[bx][by] = carry;\n                state[carry] = ON_GRID;\n                posx[carry] = bx;\n                posy[carry] = by;\n                carry = -1;\n            }\n        } else if (big_cmd == 'U') {\n            if (bx > 0) --bx;\n        } else if (big_cmd == 'D') {\n            if (bx < N - 1) ++bx;\n        } else if (big_cmd == 'L') {\n            if (by > 0) --by;\n        } else if (big_cmd == 'R') {\n            if (by < N - 1) ++by;\n        } else {\n            // '.', 'B' for big crane: no movement\n        }\n\n        // Step 3: dispatch containers at right edge\n        for (int i = 0; i < N; ++i) {\n            int &cell = grid[i][N - 1];\n            if (cell != -1) {\n                int id = cell;\n                cell = -1;\n                state[id] = DISPATCHED;\n                posx[id] = -1;\n                posy[id] = -1;\n                ++dispatched_count;\n                int r = id / N;\n                if (nextRowId[r] == id) {\n                    ++nextRowId[r];\n                }\n            }\n        }\n    }\n\n    // Output operation strings\n    for (int i = 0; i < N; ++i) {\n        cout << ops[i] << '\\n';\n    }\n\n    return 0;\n}","ahc034":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int MAXN = 20;\nconst int TOT_LIMIT = 100000;  // Hard limit from problem\nconst int LIMIT_GREEDY = 90000; // Cap for greedy stage, leave room for fallback\n\nint N;\nlong long h[MAXN][MAXN];\nvector<string> ops;\n\nint cur_r = 0, cur_c = 0;   // current truck position\nlong long load_truck = 0;   // current truck load\n\nvector<pair<int,int>> snakePath;\n\n// Move truck from current (cur_r, cur_c) to (tr, tc) along Manhattan path\nvoid move_to(int tr, int tc) {\n    while (cur_r < tr) {\n        ++cur_r;\n        ops.emplace_back(\"D\");\n    }\n    while (cur_r > tr) {\n        --cur_r;\n        ops.emplace_back(\"U\");\n    }\n    while (cur_c < tc) {\n        ++cur_c;\n        ops.emplace_back(\"R\");\n    }\n    while (cur_c > tc) {\n        --cur_c;\n        ops.emplace_back(\"L\");\n    }\n}\n\n// Find nearest cell of given sign from current position.\n// sign = +1: h > 0 (positive), sign = -1: h < 0 (negative).\n// Tie-break by larger |h|.\npair<int,int> findNearest(int sign) {\n    int bestR = -1, bestC = -1;\n    int bestd = INT_MAX;\n    long long bestVal = -1;\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            long long v = h[i][j];\n            if (sign == 1) {\n                if (v <= 0) continue;\n                int d = abs(i - cur_r) + abs(j - cur_c);\n                if (d < bestd || (d == bestd && v > bestVal)) {\n                    bestd = d;\n                    bestVal = v;\n                    bestR = i;\n                    bestC = j;\n                }\n            } else {\n                if (v >= 0) continue;\n                int d = abs(i - cur_r) + abs(j - cur_c);\n                long long absV = -v;\n                if (d < bestd || (d == bestd && absV > bestVal)) {\n                    bestd = d;\n                    bestVal = absV;\n                    bestR = i;\n                    bestC = j;\n                }\n            }\n        }\n    }\n    return {bestR, bestC};\n}\n\n// Stage 1: greedy shipping between nearest positives and negatives\nvoid greedy_phase() {\n    long long base_total = 0;\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            base_total += llabs(h[i][j]);\n\n    while (base_total > 0 && (int)ops.size() < LIMIT_GREEDY) {\n        if (load_truck == 0) {\n            // Need a positive cell\n            auto [pr, pc] = findNearest(+1);\n            if (pr == -1) break; // should not happen in a correct state\n            move_to(pr, pc);\n\n            long long v = h[pr][pc];\n            if (v > 0) {\n                long long d = v;\n                ops.emplace_back(\"+\" + to_string(d));\n                load_truck += d;\n                h[pr][pc] = 0;\n                base_total -= d;\n            }\n        } else {\n            // We have load, need a negative cell\n            auto [nr, nc] = findNearest(-1);\n            if (nr == -1) break; // should not happen if total sum is 0\n            move_to(nr, nc);\n\n            long long v = h[nr][nc];\n            if (v < 0) {\n                long long need = -v;\n                long long d = min(load_truck, need);\n                ops.emplace_back(\"-\" + to_string(d));\n                load_truck -= d;\n                h[nr][nc] += d;\n                base_total -= d;\n            }\n        }\n    }\n}\n\n// Build snake Hamiltonian path for fallback\nvoid buildSnakePath() {\n    snakePath.clear();\n    for (int i = 0; i < N; ++i) {\n        if (i % 2 == 0) {\n            for (int j = 0; j < N; ++j) {\n                snakePath.emplace_back(i, j);\n            }\n        } else {\n            for (int j = N - 1; j >= 0; --j) {\n                snakePath.emplace_back(i, j);\n            }\n        }\n    }\n}\n\n// Stage 2: fallback using two-pass snake sweep\nvoid fallback_snake() {\n    // Unload everything at current cell to make load_truck zero\n    if (load_truck > 0) {\n        ops.emplace_back(\"-\" + to_string(load_truck));\n        h[cur_r][cur_c] += load_truck;\n        load_truck = 0;\n    }\n\n    // Move to (0,0) which is snakePath[0]\n    move_to(0, 0);\n\n    int M = (int)snakePath.size();\n\n    // Forward pass\n    for (int idx = 0; idx < M; ++idx) {\n        int r = snakePath[idx].first;\n        int c = snakePath[idx].second;\n        move_to(r, c);\n\n        long long v = h[r][c];\n        if (v > 0) {\n            long long d = v;\n            ops.emplace_back(\"+\" + to_string(d));\n            load_truck += d;\n            h[r][c] = 0;\n        } else if (v < 0 && load_truck > 0) {\n            long long need = -v;\n            long long d = min(load_truck, need);\n            ops.emplace_back(\"-\" + to_string(d));\n            load_truck -= d;\n            h[r][c] += d;\n        }\n    }\n\n    // Backward pass\n    for (int idx = M - 1; idx >= 0; --idx) {\n        int r = snakePath[idx].first;\n        int c = snakePath[idx].second;\n        move_to(r, c);\n\n        long long v = h[r][c];\n        if (v < 0 && load_truck > 0) {\n            long long need = -v;\n            long long d = min(load_truck, need);\n            ops.emplace_back(\"-\" + to_string(d));\n            load_truck -= d;\n            h[r][c] += d;\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    if (!(cin >> N)) return 0;\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            cin >> h[i][j];\n\n    cur_r = 0;\n    cur_c = 0;\n    load_truck = 0;\n\n    buildSnakePath();\n    greedy_phase();\n\n    // Check if everything is leveled\n    bool all_zero = true;\n    for (int i = 0; i < N && all_zero; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (h[i][j] != 0) {\n                all_zero = false;\n                break;\n            }\n        }\n    }\n\n    if (!all_zero && (int)ops.size() < TOT_LIMIT) {\n        fallback_snake();\n    }\n\n    // Absolute safety: never output more than 100000 operations\n    if ((int)ops.size() > TOT_LIMIT) {\n        ops.resize(TOT_LIMIT);\n    }\n\n    for (const string &s : ops) {\n        cout << s << '\\n';\n    }\n    return 0;\n}","ahc035":"#include <bits/stdc++.h>\nusing namespace std;\n\n/*\nImproved heuristic:\n\n- N=6, M=15, T=10 fixed.\n- Seed count per generation: S = 2*N*(N-1) = 60.\n- Each turn:\n  1) Compute normalized scores using global per-dim maxima from initial seeds.\n  2) Compute pairwise \"synergy\" for all seeds:\n       S(a,b) = sum_l max(x_a_l, x_b_l) / X_l.\n  3) Select 36 seeds:\n       - Dimension champions (best for each dimension).\n       - Then greedily add seeds using a combined score:\n           score(k) = normV[k] + \u03bb * avg_synergy_to_selected(k)\n         (\u03bb ~ 0.35).\n  4) Among the 36 selected seeds, compute \"centrality\":\n       cent(s) = avg synergy to other selected seeds.\n     Order seeds by normV + \u03b3 * cent(s) (\u03b3 ~ 0.45).\n  5) Greedy initial placement:\n       - Positions sorted by degree (center > edge > corner).\n       - Place seeds in the above order to positions maximizing incremental synergy.\n  6) Hill-climb the placement by random swaps (200k iterations).\n  7) Output arrangement, then read next generation seeds.\n*/\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, T;\n    if (!(cin >> N >> M >> T)) return 0;\n\n    const int SEED_COUNT = 2 * N * (N - 1); // 60 for N=6\n    const int SZ = N * N;                   // 36 for N=6\n    const int MAXS = 60;                    // max seed count\n\n    // Current seeds: x[k][l]\n    vector<vector<int>> x(SEED_COUNT, vector<int>(M));\n    for (int i = 0; i < SEED_COUNT; i++) {\n        for (int l = 0; l < M; l++) cin >> x[i][l];\n    }\n\n    // Global per-dimension maxima from initial seeds\n    vector<int> X_global(M, 0);\n    for (int l = 0; l < M; l++) {\n        int mx = 0;\n        for (int i = 0; i < SEED_COUNT; i++) {\n            mx = max(mx, x[i][l]);\n        }\n        X_global[l] = mx;\n    }\n\n    // Active dimensions (those with X_global[l] > 0, to avoid division by zero)\n    vector<int> active_dims;\n    active_dims.reserve(M);\n    for (int l = 0; l < M; l++) {\n        if (X_global[l] > 0) active_dims.push_back(l);\n    }\n\n    // Precompute grid adjacency (neighbors) and edges\n    vector<vector<int>> neighbors(SZ);\n    vector<pair<int,int>> edges;\n    edges.reserve(2 * N * (N - 1));\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            int pos = i * N + j;\n            if (j + 1 < N) {\n                int q = pos + 1;\n                edges.emplace_back(pos, q);\n                neighbors[pos].push_back(q);\n                neighbors[q].push_back(pos);\n            }\n            if (i + 1 < N) {\n                int q = pos + N;\n                edges.emplace_back(pos, q);\n                neighbors[pos].push_back(q);\n                neighbors[q].push_back(pos);\n            }\n        }\n    }\n\n    // Positions sorted by degree (center > edge > corner)\n    vector<int> pos_by_deg(SZ);\n    iota(pos_by_deg.begin(), pos_by_deg.end(), 0);\n    sort(pos_by_deg.begin(), pos_by_deg.end(), [&](int a, int b) {\n        if (neighbors[a].size() != neighbors[b].size())\n            return neighbors[a].size() > neighbors[b].size();\n        return a < b;\n    });\n\n    // Simple xorshift RNG (deterministic)\n    uint64_t rng_state = 88172645463325252ull;\n    auto rng = [&]() -> uint64_t {\n        rng_state ^= (rng_state << 7);\n        rng_state ^= (rng_state >> 9);\n        return rng_state;\n    };\n\n    // Normalized total scores per seed\n    vector<double> normV(SEED_COUNT);\n\n    // Synergy matrix (pairwise)\n    static double synergy[MAXS][MAXS];\n\n    const double LAMBDA = 0.35; // weight for synergy in selection\n    const double GAMMA  = 0.45; // weight for synergy centrality in ordering\n\n    for (int turn = 0; turn < T; turn++) {\n        // 1. Compute normalized total score for each seed\n        for (int k = 0; k < SEED_COUNT; k++) {\n            double s = 0.0;\n            for (int idx = 0; idx < (int)active_dims.size(); idx++) {\n                int l = active_dims[idx];\n                s += (double)x[k][l] / (double)X_global[l];\n            }\n            normV[k] = s;\n        }\n\n        // 2. Compute synergy matrix for all seeds\n        for (int i = 0; i < SEED_COUNT; i++) {\n            synergy[i][i] = 0.0;\n            for (int j = i + 1; j < SEED_COUNT; j++) {\n                double s = 0.0;\n                for (int idx = 0; idx < (int)active_dims.size(); idx++) {\n                    int l = active_dims[idx];\n                    s += (double)max(x[i][l], x[j][l]) / (double)X_global[l];\n                }\n                synergy[i][j] = synergy[j][i] = s;\n            }\n        }\n\n        // 3. Select 36 seeds: dimension champions + synergy-guided greedy fill\n        vector<int> selected;\n        selected.reserve(SZ);\n        vector<char> used(SEED_COUNT, 0);\n\n        // 3-1. Dimension champions\n        for (int idx = 0; idx < (int)active_dims.size(); idx++) {\n            int l = active_dims[idx];\n            int best = -1;\n            int bestVal = -1;\n            double bestNorm = -1.0;\n            for (int k = 0; k < SEED_COUNT; k++) {\n                int v = x[k][l];\n                if (v > bestVal || (v == bestVal && normV[k] > bestNorm)) {\n                    bestVal = v;\n                    bestNorm = normV[k];\n                    best = k;\n                }\n            }\n            if (best != -1 && !used[best]) {\n                used[best] = 1;\n                selected.push_back(best);\n                if ((int)selected.size() == SZ) break;\n            }\n        }\n\n        // 3-2. Greedy fill with synergy-based score\n        while ((int)selected.size() < SZ) {\n            int bestK = -1;\n            double bestScore = -1e100;\n\n            for (int k = 0; k < SEED_COUNT; k++) {\n                if (used[k]) continue;\n                double avgSyn = 0.0;\n                if (!selected.empty()) {\n                    double sumSyn = 0.0;\n                    for (int s : selected) sumSyn += synergy[k][s];\n                    avgSyn = sumSyn / (double)selected.size();\n                }\n                double score = normV[k] + LAMBDA * avgSyn;\n                if (score > bestScore) {\n                    bestScore = score;\n                    bestK = k;\n                }\n            }\n            if (bestK == -1) {\n                // Fallback: pick any unused seed\n                for (int k = 0; k < SEED_COUNT; k++) {\n                    if (!used[k]) {\n                        bestK = k;\n                        break;\n                    }\n                }\n                if (bestK == -1) break; // should not happen\n            }\n            used[bestK] = 1;\n            selected.push_back(bestK);\n        }\n\n        // 4. Compute centrality for selected seeds (within the selected set)\n        vector<double> cent(SZ);\n        for (int i = 0; i < SZ; i++) {\n            double s = 0.0;\n            for (int j = 0; j < SZ; j++) {\n                if (i == j) continue;\n                s += synergy[selected[i]][selected[j]];\n            }\n            cent[i] = s / max(1, SZ - 1);\n        }\n\n        // 5. Order selected seeds for placement:\n        //    by normV + GAMMA * centrality (descending)\n        vector<int> seed_order(SZ);\n        iota(seed_order.begin(), seed_order.end(), 0);\n        sort(seed_order.begin(), seed_order.end(), [&](int a, int b) {\n            double sa = normV[selected[a]] + GAMMA * cent[a];\n            double sb = normV[selected[b]] + GAMMA * cent[b];\n            if (sa != sb) return sa > sb;\n            return selected[a] < selected[b];\n        });\n\n        // 6. Greedy initial placement:\n        //    Put seeds in \"seed_order\" into positions \"pos_by_deg\"\n        //    maximizing incremental synergy with already placed neighbors.\n        vector<int> pos_to_seed(SZ, -1);\n        for (int idx = 0; idx < SZ; idx++) {\n            int seed_id = selected[seed_order[idx]]; // actual seed index\n            int bestPos = -1;\n            double bestInc = -1e100;\n\n            for (int pos : pos_by_deg) {\n                if (pos_to_seed[pos] != -1) continue;\n                double inc = 0.0;\n                for (int nb : neighbors[pos]) {\n                    if (pos_to_seed[nb] != -1) {\n                        int nbSeed = pos_to_seed[nb];\n                        inc += synergy[seed_id][nbSeed];\n                    }\n                }\n                if (inc > bestInc + 1e-9 ||\n                    (fabs(inc - bestInc) <= 1e-9 &&\n                     neighbors[pos].size() > (bestPos == -1 ? -1 : (int)neighbors[bestPos].size()))) {\n                    bestInc = inc;\n                    bestPos = pos;\n                }\n            }\n            if (bestPos == -1) bestPos = pos_by_deg[0]; // fallback (should not happen)\n            pos_to_seed[bestPos] = seed_id;\n        }\n\n        // Current arrangement: arr[pos] = seed index\n        vector<int> arr = pos_to_seed;\n\n        // Compute initial total synergy score\n        double cur_score = 0.0;\n        for (auto &e : edges) {\n            cur_score += synergy[arr[e.first]][arr[e.second]];\n        }\n\n        // 7. Hill-climb to improve placement\n        const int ITER = 200000;  // number of random swap attempts per turn\n        for (int it = 0; it < ITER; it++) {\n            int p1 = (int)(rng() % SZ);\n            int p2 = (int)(rng() % SZ);\n            if (p1 == p2) continue;\n\n            int s1 = arr[p1];\n            int s2 = arr[p2];\n            if (s1 == s2) continue;\n\n            double delta = 0.0;\n\n            // Edges incident to p1 (excluding p2)\n            for (int nb : neighbors[p1]) {\n                if (nb == p2) continue; // edge (p1,p2) symmetric, no change\n                int s_nb = arr[nb];\n                delta -= synergy[s1][s_nb];\n                delta += synergy[s2][s_nb];\n            }\n            // Edges incident to p2 (excluding p1)\n            for (int nb : neighbors[p2]) {\n                if (nb == p1) continue;\n                int s_nb = arr[nb];\n                delta -= synergy[s2][s_nb];\n                delta += synergy[s1][s_nb];\n            }\n\n            if (delta > 0.0) {\n                cur_score += delta;\n                swap(arr[p1], arr[p2]);\n            }\n        }\n\n        // 8. Output arrangement for this turn\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                if (j) cout << ' ';\n                cout << arr[i * N + j];\n            }\n            cout << '\\n';\n        }\n        cout.flush();\n\n        // 9. Read next generation seeds\n        if (turn + 1 < T) {\n            for (int i = 0; i < SEED_COUNT; i++) {\n                for (int l = 0; l < M; l++) {\n                    cin >> x[i][l];\n                }\n            }\n        } else {\n            // For completeness, also attempt to read final seeds if provided\n            for (int i = 0; i < SEED_COUNT; i++) {\n                for (int l = 0; l < M; l++) {\n                    int tmp;\n                    if (!(cin >> tmp)) {\n                        break;\n                    }\n                }\n            }\n        }\n    }\n\n    return 0;\n}","ahc038":"#include <bits/stdc++.h>\nusing namespace std;\n\n// Directions: 0=Right, 1=Down, 2=Left, 3=Up\nconst int DX[4] = {0, 1, 0, -1};\nconst int DY[4] = {1, 0, -1, 0};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, V;\n    if (!(cin >> N >> M >> V)) return 0;\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    // Current occupancy grid\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            if (s[i][j] == '1') occ[i][j] = 1;\n        }\n    }\n\n    // Collect mismatches\n    vector<pair<int,int>> sources;\n    vector<pair<int,int>> targets;\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (s[i][j] == '1' && t[i][j] == '0') {\n                sources.emplace_back(i, j);\n            } else if (s[i][j] == '0' && t[i][j] == '1') {\n                targets.emplace_back(i, j);\n            }\n        }\n    }\n    int K = (int)sources.size(); // number of pairs to handle\n\n    // Arm: 2 vertices: 0=root, 1=fingertip (length 1)\n    const int Vp = 2;\n\n    struct PairInfo {\n        int sx, sy;\n        int tx, ty;\n    };\n    vector<PairInfo> pairs;\n\n    if (K > 0) {\n        // Global greedy matching between sources and targets\n        // Precompute Manhattan distances\n        vector<vector<int>> dist(K, vector<int>(K));\n        for (int i = 0; i < K; i++) {\n            for (int j = 0; j < K; j++) {\n                dist[i][j] = abs(sources[i].first - targets[j].first)\n                           + abs(sources[i].second - targets[j].second);\n            }\n        }\n        vector<int> matchT(K, -1);\n        vector<char> usedS(K, 0), usedT(K, 0);\n\n        for (int iter = 0; iter < K; iter++) {\n            int bestD = INT_MAX;\n            int bestI = -1, bestJ = -1;\n            for (int i = 0; i < K; i++) if (!usedS[i]) {\n                for (int j = 0; j < K; j++) if (!usedT[j]) {\n                    int d = dist[i][j];\n                    if (d < bestD) {\n                        bestD = d;\n                        bestI = i;\n                        bestJ = j;\n                    }\n                }\n            }\n            // Assign bestI -> bestJ\n            usedS[bestI] = 1;\n            usedT[bestJ] = 1;\n            matchT[bestI] = bestJ;\n        }\n\n        // Build pairs\n        pairs.resize(K);\n        for (int i = 0; i < K; i++) {\n            int j = matchT[i];\n            pairs[i].sx = sources[i].first;\n            pairs[i].sy = sources[i].second;\n            pairs[i].tx = targets[j].first;\n            pairs[i].ty = targets[j].second;\n        }\n    }\n\n    // Determine order of processing pairs: nearest-neighbor from fingertip position\n    vector<int> order;\n    if (K > 0) {\n        order.reserve(K);\n        vector<char> usedPair(K, 0);\n\n        // Initial fingertip position: root at (0,0), dir=Right => finger at (0,1)\n        int curFx = 0, curFy = 1;\n\n        for (int step = 0; step < K; step++) {\n            int bestId = -1;\n            int bestD = INT_MAX;\n            for (int i = 0; i < K; i++) if (!usedPair[i]) {\n                int d = abs(curFx - pairs[i].sx) + abs(curFy - pairs[i].sy);\n                if (d < bestD) {\n                    bestD = d;\n                    bestId = i;\n                }\n            }\n            usedPair[bestId] = 1;\n            order.push_back(bestId);\n            // After processing this pair, fingertip will end at its target\n            curFx = pairs[bestId].tx;\n            curFy = pairs[bestId].ty;\n        }\n    }\n\n    // Command sequence\n    vector<string> cmds;\n    cmds.reserve(100000);\n\n    int rootX = 0, rootY = 0; // initial root position\n    int initRootX = rootX, initRootY = rootY;\n    int dir = 0;              // 0=Right initially\n    bool holding = false;\n\n    auto add_step = [&](char mv, char rot, bool doP) {\n        string S(2 * Vp, '.'); // length 4\n        S[0] = mv;\n        S[1] = rot;\n        // S[2] is root action, always '.'\n        if (doP) S[3] = 'P';\n        cmds.push_back(S);\n\n        // Update root position\n        if (mv == 'U') rootX--;\n        else if (mv == 'D') rootX++;\n        else if (mv == 'L') rootY--;\n        else if (mv == 'R') rootY++;\n\n        // Update direction of edge (0,1)\n        if (rot == 'L') dir = (dir + 3) & 3;\n        else if (rot == 'R') dir = (dir + 1) & 3;\n    };\n\n    auto finger_x = [&]() { return rootX + DX[dir]; };\n    auto finger_y = [&]() { return rootY + DY[dir]; };\n\n    // Move root to (nx, ny) and orientation to ndir, overlapping movement & rotation\n    auto move_root_dir = [&](int nx, int ny, int ndir) {\n        int dx = nx - rootX;\n        int dy = ny - rootY;\n        vector<char> path;\n        if (dx > 0) path.insert(path.end(), dx, 'D');\n        else if (dx < 0) path.insert(path.end(), -dx, 'U');\n        if (dy > 0) path.insert(path.end(), dy, 'R');\n        else if (dy < 0) path.insert(path.end(), -dy, 'L');\n\n        int diff = (ndir - dir + 4) & 3;\n        int rotSteps = 0;\n        char rotChar = '.';\n        if (diff == 0) {\n            rotSteps = 0;\n        } else if (diff == 1) {\n            rotSteps = 1;\n            rotChar = 'R';\n        } else if (diff == 2) {\n            rotSteps = 2;\n            rotChar = 'R'; // two clockwise rotations\n        } else { // diff == 3\n            rotSteps = 1;\n            rotChar = 'L';\n        }\n\n        int moveSteps = (int)path.size();\n        int usedRot = min(rotSteps, moveSteps);\n        for (int i = 0; i < moveSteps; i++) {\n            char mv = path[i];\n            char rot = (i < usedRot ? rotChar : '.');\n            add_step(mv, rot, false);\n        }\n        for (int i = usedRot; i < rotSteps; i++) {\n            // rotate in place\n            add_step('.', rotChar, false);\n        }\n    };\n\n    // Move fingertip to exactly (tx, ty)\n    auto move_finger_to = [&](int tx, int ty) {\n        int bestNX = rootX, bestNY = rootY, bestDir = dir;\n        int bestCost = INT_MAX;\n\n        for (int ndir = 0; ndir < 4; ndir++) {\n            int nrX = tx - DX[ndir];\n            int nrY = ty - DY[ndir];\n            if (nrX < 0 || nrX >= N || nrY < 0 || nrY >= N) continue;\n            int distRoot = abs(nrX - rootX) + abs(nrY - rootY);\n            int diff = (ndir - dir + 4) & 3;\n            int rotCost = min(diff, 4 - diff);\n            int cost = max(distRoot, rotCost); // rotations can overlap with moves\n            if (cost < bestCost) {\n                bestCost = cost;\n                bestNX = nrX;\n                bestNY = nrY;\n                bestDir = ndir;\n            }\n        }\n\n        move_root_dir(bestNX, bestNY, bestDir);\n        // Now fingertip should be at (tx, ty)\n    };\n\n    if (K > 0) {\n        for (int idx : order) {\n            const auto &P = pairs[idx];\n\n            // Move fingertip to source\n            move_finger_to(P.sx, P.sy);\n            int fx = finger_x(), fy = finger_y();\n            bool doP = false;\n            if (!holding && fx >= 0 && fx < N && fy >= 0 && fy < N && occ[fx][fy] == 1) {\n                doP = true;\n                holding = true;\n                occ[fx][fy] = 0;\n            }\n            add_step('.', '.', doP); // pick\n\n            // Move fingertip to target\n            move_finger_to(P.tx, P.ty);\n            fx = finger_x();\n            fy = finger_y();\n            doP = false;\n            if (holding && fx >= 0 && fx < N && fy >= 0 && fy < N && occ[fx][fy] == 0) {\n                doP = true;\n                holding = false;\n                occ[fx][fy] = 1;\n            }\n            add_step('.', '.', doP); // drop\n        }\n    }\n\n    // Output\n    // 1) Tree description: 2 vertices: 0 (root), 1 (fingertip), length 1\n    cout << Vp << '\\n';\n    cout << 0 << ' ' << 1 << '\\n';\n\n    // 2) Initial root position\n    cout << initRootX << ' ' << initRootY << '\\n';\n\n    // 3) Operation sequence\n    for (const string &S : cmds) {\n        cout << S << '\\n';\n    }\n\n    return 0;\n}","ahc039":"#include <bits/stdc++.h>\nusing namespace std;\n\n// ---------- Geometry utilities for polygon evaluation ----------\n\nbool pointInPolygon(int px, int py, const vector<pair<int,int>>& poly) {\n    int n = (int)poly.size();\n    bool inside = false;\n    for (int i = 0, j = n - 1; i < n; j = i++) {\n        long long xi = poly[i].first, yi = poly[i].second;\n        long long xj = poly[j].first, yj = poly[j].second;\n\n        // Check if point lies on segment (xi,yi)-(xj,yj) (edges inclusive)\n        long long minx = min(xi, xj), maxx = max(xi, xj);\n        long long miny = min(yi, yj), maxy = max(yi, yj);\n        long long cross = (xj - xi) * 1LL * (py - yi) - (yj - yi) * 1LL * (px - xi);\n        if (cross == 0 && px >= minx && px <= maxx && py >= miny && py <= maxy) {\n            return true; // on edge\n        }\n\n        // Even-odd rule; ignore horizontal edges\n        bool cond = ((yi > py) != (yj > py));\n        if (cond) {\n            double interX = xi + (double)(xj - xi) * (double)(py - yi) / (double)(yj - yi);\n            if (interX > px) inside = !inside;\n        }\n    }\n    return inside;\n}\n\nint evaluatePolygonDiff(const vector<pair<int,int>>& poly,\n                        const vector<int>& xs, const vector<int>& ys, int N) {\n    if (poly.empty()) return INT_MIN/2;\n    int total = 2 * N;\n    int minx = INT_MAX, maxx = INT_MIN, miny = INT_MAX, maxy = INT_MIN;\n    for (auto &p : poly) {\n        minx = min(minx, p.first);\n        maxx = max(maxx, p.first);\n        miny = min(miny, p.second);\n        maxy = max(maxy, p.second);\n    }\n\n    int diff = 0;\n    for (int i = 0; i < total; ++i) {\n        int x = xs[i], y = ys[i];\n        if (x < minx || x > maxx || y < miny || y > maxy) continue;\n        if (pointInPolygon(x, y, poly)) {\n            diff += (i < N ? 1 : -1);\n        }\n    }\n    return diff;\n}\n\n// ---------- Polygon construction from grid mask ----------\n\nvector<pair<int,int>> buildPolygonFromMask(\n    int H, int W,\n    const vector<char>& inside,\n    const vector<int>& xCoord,\n    const vector<int>& yCoord\n) {\n    int V = (H + 1) * (W + 1);\n    vector<vector<int>> adj(V);\n\n    auto cellInside = [&](int i, int j) -> bool {\n        if (i < 0 || i >= H || j < 0 || j >= W) return false;\n        return inside[i * W + j] != 0;\n    };\n    auto vertIndex = [&](int r, int c) -> int {\n        return r * (W + 1) + c;\n    };\n    auto addEdge = [&](int u, int v) {\n        adj[u].push_back(v);\n        adj[v].push_back(u);\n    };\n\n    // Build boundary edges (between inside and outside cells)\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            if (!cellInside(i, j)) continue;\n\n            // Left side\n            if (j == 0 || !cellInside(i, j - 1)) {\n                int u = vertIndex(i, j);\n                int v = vertIndex(i + 1, j);\n                addEdge(u, v);\n            }\n            // Right side\n            if (j == W - 1 || !cellInside(i, j + 1)) {\n                int u = vertIndex(i, j + 1);\n                int v = vertIndex(i + 1, j + 1);\n                addEdge(u, v);\n            }\n            // Bottom side\n            if (i == 0 || !cellInside(i - 1, j)) {\n                int u = vertIndex(i, j);\n                int v = vertIndex(i, j + 1);\n                addEdge(u, v);\n            }\n            // Top side\n            if (i == H - 1 || !cellInside(i + 1, j)) {\n                int u = vertIndex(i + 1, j);\n                int v = vertIndex(i + 1, j + 1);\n                addEdge(u, v);\n            }\n        }\n    }\n\n    vector<char> used(V, false);\n    vector<pair<int,int>> bestPoly;\n    long long bestAreaAbs = -1;\n\n    for (int start = 0; start < V; ++start) {\n        if (used[start] || adj[start].empty()) continue;\n\n        vector<int> cyc;\n        int cur = start;\n        int prev = -1;\n        int safety = 0;\n\n        while (true) {\n            cyc.push_back(cur);\n            used[cur] = true;\n\n            if (adj[cur].empty()) {\n                cyc.clear();\n                break;\n            }\n\n            int nxt;\n            if ((int)adj[cur].size() == 1) {\n                nxt = adj[cur][0];\n            } else {\n                if (adj[cur][0] != prev) nxt = adj[cur][0];\n                else nxt = adj[cur][1];\n            }\n\n            prev = cur;\n            cur = nxt;\n            if (cur == start) break;\n\n            if (++safety > V * 4) { // safety guard\n                cyc.clear();\n                break;\n            }\n        }\n\n        if (cyc.empty() || (int)cyc.size() < 4) continue;\n\n        // Convert vertices to coordinates\n        vector<pair<int,int>> ptsRaw;\n        ptsRaw.reserve(cyc.size());\n        for (int vid : cyc) {\n            int r = vid / (W + 1);\n            int c = vid % (W + 1);\n            int x = xCoord[c];\n            int y = yCoord[r];\n            ptsRaw.emplace_back(x, y);\n        }\n\n        // Remove collinear middle vertices\n        int m = (int)ptsRaw.size();\n        vector<pair<int,int>> pts;\n        pts.reserve(m);\n        for (int i = 0; i < m; ++i) {\n            auto &prevP = ptsRaw[(i + m - 1) % m];\n            auto &curP  = ptsRaw[i];\n            auto &nextP = ptsRaw[(i + 1) % m];\n            bool collinear =\n                (prevP.first == curP.first && curP.first == nextP.first) ||\n                (prevP.second == curP.second && curP.second == nextP.second);\n            if (!collinear) {\n                pts.push_back(curP);\n            }\n        }\n\n        if ((int)pts.size() < 4) continue;\n        if ((int)pts.size() > 1000) continue;\n\n        // Perimeter check\n        long long per = 0;\n        int m2 = (int)pts.size();\n        for (int i = 0; i < m2; ++i) {\n            auto &a = pts[i];\n            auto &b = pts[(i + 1) % m2];\n            per += llabs((long long)a.first - b.first) + llabs((long long)a.second - b.second);\n        }\n        if (per > 400000LL) continue;\n\n        // Area (twice)\n        long long area2 = 0;\n        for (int i = 0; i < m2; ++i) {\n            long long x1 = pts[i].first, y1 = pts[i].second;\n            long long x2 = pts[(i + 1) % m2].first, y2 = pts[(i + 1) % m2].second;\n            area2 += x1 * y2 - x2 * y1;\n        }\n        long long areaAbs = llabs(area2);\n        if (areaAbs > bestAreaAbs) {\n            bestAreaAbs = areaAbs;\n            bestPoly = std::move(pts);\n        }\n    }\n\n    return bestPoly;\n}\n\n// ---------- Rectangle diff ----------\n\nint evaluateRectDiff(int xL, int yB, int xR, int yT,\n                     const vector<int>& xs, const vector<int>& ys, int N) {\n    if (xL > xR || yB > yT) return INT_MIN/2;\n    int total = 2 * N;\n    int diff = 0;\n    for (int i = 0; i < total; ++i) {\n        int x = xs[i], y = ys[i];\n        if (x >= xL && x <= xR && y >= yB && y <= yT) {\n            diff += (i < N ? 1 : -1);\n        }\n    }\n    return diff;\n}\n\n// ---------- Main ----------\n\nstruct Rect {\n    int xL, yB, xR, yT;\n    int diff;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    if (!(cin >> N)) return 0;\n    int total = 2 * N;\n\n    const int MAXC = 100000;\n    const int FULL = MAXC + 1;\n\n    vector<int> xs(total), ys(total);\n    for (int i = 0; i < total; ++i) {\n        cin >> xs[i] >> ys[i];\n    }\n\n    // Global best solution (polygon, can be rectangle)\n    vector<pair<int,int>> bestPoly;\n    int bestDiff = 0;\n    // Best rectangular solution\n    Rect bestRect = {0, 0, MAXC, MAXC, 0};\n\n    // Initialize with full bounding rectangle (diff = 0)\n    bestPoly = {\n        {0, 0},\n        {MAXC, 0},\n        {MAXC, MAXC},\n        {0, MAXC}\n    };\n\n    auto updateBestWithRect = [&](int xL, int yB, int xR, int yT) {\n        if (xL > xR || yB > yT) return;\n        int diff = evaluateRectDiff(xL, yB, xR, yT, xs, ys, N);\n        if (diff > bestRect.diff) {\n            bestRect = {xL, yB, xR, yT, diff};\n        }\n        if (diff > bestDiff) {\n            bestDiff = diff;\n            bestPoly.clear();\n            bestPoly.push_back({xL, yB});\n            bestPoly.push_back({xR, yB});\n            bestPoly.push_back({xR, yT});\n            bestPoly.push_back({xL, yT});\n        }\n    };\n\n    auto updateBestWithPoly = [&](const vector<pair<int,int>>& poly) {\n        if (poly.empty()) return;\n        int diff = evaluatePolygonDiff(poly, xs, ys, N);\n        if (diff > bestDiff) {\n            bestDiff = diff;\n            bestPoly = poly;\n        }\n    };\n\n    // Grid sizes and weight modes\n    vector<int> gridSizes = {40, 60, 90, 130};\n    vector<pair<int,int>> weightModes = {\n        {1, -1},\n        {1, -2},\n        {2, -1}\n    };\n\n    vector<int> cell;\n    vector<long long> colSum;\n    vector<char> visited, bestMask;\n    vector<pair<int,int>> qCells;\n\n    for (int S : gridSizes) {\n        int H = S, W = S;\n        vector<int> xCoord(W + 1), yCoord(H + 1);\n        for (int j = 0; j <= W; ++j) {\n            int val = (int)(1LL * j * FULL / W);\n            if (val > MAXC) val = MAXC;\n            xCoord[j] = val;\n        }\n        for (int i = 0; i <= H; ++i) {\n            int val = (int)(1LL * i * FULL / H);\n            if (val > MAXC) val = MAXC;\n            yCoord[i] = val;\n        }\n\n        // Base arrays of cell counts for mackerel and sardine\n        vector<int> mCell(H * W, 0), sCell(H * W, 0);\n        for (int idx = 0; idx < total; ++idx) {\n            int x = xs[idx], y = ys[idx];\n            int cx = (int)(1LL * x * W / FULL);\n            int cy = (int)(1LL * y * H / FULL);\n            if (cx < 0) cx = 0;\n            if (cx >= W) cx = W - 1;\n            if (cy < 0) cy = 0;\n            if (cy >= H) cy = H - 1;\n            int cidx = cy * W + cx;\n            if (idx < N) mCell[cidx]++; else sCell[cidx]++;\n        }\n\n        for (auto [wM, wS] : weightModes) {\n            // Build weighted cell values\n            cell.assign(H * W, 0);\n            for (int i = 0; i < H * W; ++i) {\n                cell[i] = wM * mCell[i] + wS * sCell[i];\n            }\n\n            // ----- 2D Kadane for best rectangle on this grid -----\n            const long long NEG_INF = -(1LL << 60);\n            long long bestSum = NEG_INF;\n            int bestL = 0, bestR = 0, bestT = 0, bestB = 0;\n\n            colSum.assign(W, 0);\n            for (int top = 0; top < H; ++top) {\n                fill(colSum.begin(), colSum.end(), 0);\n                for (int bottom = top; bottom < H; ++bottom) {\n                    int rowOffset = bottom * W;\n                    for (int c = 0; c < W; ++c) {\n                        colSum[c] += cell[rowOffset + c];\n                    }\n                    long long sum = 0;\n                    int curL = 0;\n                    for (int c = 0; c < W; ++c) {\n                        if (sum <= 0) {\n                            sum = colSum[c];\n                            curL = c;\n                        } else {\n                            sum += colSum[c];\n                        }\n                        if (sum > bestSum) {\n                            bestSum = sum;\n                            bestL = curL;\n                            bestR = c;\n                            bestT = top;\n                            bestB = bottom;\n                        }\n                    }\n                }\n            }\n\n            if (bestSum > 0) {\n                int xL = xCoord[bestL];\n                int xR = xCoord[bestR + 1];\n                int yB = yCoord[bestT];\n                int yT = yCoord[bestB + 1];\n\n                if (xL < 0) xL = 0;\n                if (xR > MAXC) xR = MAXC;\n                if (yB < 0) yB = 0;\n                if (yT > MAXC) yT = MAXC;\n\n                updateBestWithRect(xL, yB, xR, yT);\n            }\n\n            // ----- Best connected component of positive cells -> union-of-cells polygon -----\n            visited.assign(H * W, 0);\n            bestMask.assign(H * W, 0);\n            long long bestCompSum = 0;\n\n            qCells.clear();\n            queue<int> q;\n            static const int dr[4] = {-1, 1, 0, 0};\n            static const int dc[4] = {0, 0, -1, 1};\n\n            for (int i = 0; i < H; ++i) {\n                for (int j = 0; j < W; ++j) {\n                    int idx = i * W + j;\n                    if (visited[idx] || cell[idx] <= 0) continue;\n\n                    qCells.clear();\n                    long long curSum = 0;\n\n                    visited[idx] = 1;\n                    while (!q.empty()) q.pop();\n                    q.push(idx);\n\n                    while (!q.empty()) {\n                        int u = q.front(); q.pop();\n                        qCells.push_back({u / W, u % W});\n                        curSum += cell[u];\n\n                        int r = u / W, c = u % W;\n                        for (int d = 0; d < 4; ++d) {\n                            int nr = r + dr[d];\n                            int nc = c + dc[d];\n                            if (nr < 0 || nr >= H || nc < 0 || nc >= W) continue;\n                            int v = nr * W + nc;\n                            if (!visited[v] && cell[v] > 0) {\n                                visited[v] = 1;\n                                q.push(v);\n                            }\n                        }\n                    }\n\n                    if (curSum > bestCompSum) {\n                        bestCompSum = curSum;\n                        fill(bestMask.begin(), bestMask.end(), 0);\n                        for (auto &rc : qCells) {\n                            bestMask[rc.first * W + rc.second] = 1;\n                        }\n                    }\n                }\n            }\n\n            if (bestCompSum > 0) {\n                // Build polygon from mask\n                vector<pair<int,int>> poly = buildPolygonFromMask(H, W, bestMask, xCoord, yCoord);\n                if (!poly.empty()) {\n                    updateBestWithPoly(poly);\n                }\n            }\n        }\n    }\n\n    // Fallback: if no positive diff found, try small rectangles around mackerels\n    if (bestDiff <= 0) {\n        const int delta = 1000;\n        for (int i = 0; i < N; ++i) {\n            int xL = max(0, xs[i] - delta);\n            int xR = min(MAXC, xs[i] + delta);\n            int yB = max(0, ys[i] - delta);\n            int yT = min(MAXC, ys[i] + delta);\n            updateBestWithRect(xL, yB, xR, yT);\n        }\n    }\n\n    // ---------- Local hill-climb search on the best rectangle ----------\n\n    // Collect sorted unique x and y coordinates of all fish\n    vector<int> uniqX = xs, uniqY = ys;\n    sort(uniqX.begin(), uniqX.end());\n    uniqX.erase(unique(uniqX.begin(), uniqX.end()), uniqX.end());\n    sort(uniqY.begin(), uniqY.end());\n    uniqY.erase(unique(uniqY.begin(), uniqY.end()), uniqY.end());\n\n    mt19937 rng(1234567); // deterministic seed for reproducibility\n\n    auto randRange = [&](int lo, int hi) -> int {\n        if (lo > hi) return lo;\n        uint32_t r = rng();\n        return lo + (int)(r % (uint32_t)(hi - lo + 1));\n    };\n\n    Rect cur = bestRect;\n    int curDiff = cur.diff;\n    int Mx = (int)uniqX.size();\n    int My = (int)uniqY.size();\n    const int ITER = 200;\n    const int RANGE = 50; // neighborhood size in sorted coords\n\n    for (int it = 0; it < ITER; ++it) {\n        Rect cand = cur;\n        bool ok = false;\n        int side = randRange(0, 3); // 0:left,1:right,2:bottom,3:top\n\n        for (int attempt = 0; attempt < 5; ++attempt) {\n            if (side == 0) { // move left side\n                int idx = (int)(lower_bound(uniqX.begin(), uniqX.end(), cur.xL) - uniqX.begin());\n                if (idx >= Mx) idx = Mx - 1;\n                int lo = max(0, idx - RANGE);\n                int hi = idx;\n                if (lo > hi) break;\n                int newIdx = randRange(lo, hi);\n                int nx = uniqX[newIdx];\n                if (nx >= cand.xR) continue;\n                cand.xL = nx;\n                ok = true;\n                break;\n            } else if (side == 1) { // move right side\n                int idx = (int)(upper_bound(uniqX.begin(), uniqX.end(), cur.xR) - uniqX.begin()) - 1;\n                if (idx < 0) idx = 0;\n                int lo = idx;\n                int hi = min(Mx - 1, idx + RANGE);\n                if (lo > hi) break;\n                int newIdx = randRange(lo, hi);\n                int nx = uniqX[newIdx];\n                if (nx <= cand.xL) continue;\n                cand.xR = nx;\n                ok = true;\n                break;\n            } else if (side == 2) { // move bottom side\n                int idx = (int)(lower_bound(uniqY.begin(), uniqY.end(), cur.yB) - uniqY.begin());\n                if (idx >= My) idx = My - 1;\n                int lo = max(0, idx - RANGE);\n                int hi = idx;\n                if (lo > hi) break;\n                int newIdx = randRange(lo, hi);\n                int ny = uniqY[newIdx];\n                if (ny >= cand.yT) continue;\n                cand.yB = ny;\n                ok = true;\n                break;\n            } else { // move top side\n                int idx = (int)(upper_bound(uniqY.begin(), uniqY.end(), cur.yT) - uniqY.begin()) - 1;\n                if (idx < 0) idx = 0;\n                int lo = idx;\n                int hi = min(My - 1, idx + RANGE);\n                if (lo > hi) break;\n                int newIdx = randRange(lo, hi);\n                int ny = uniqY[newIdx];\n                if (ny <= cand.yB) continue;\n                cand.yT = ny;\n                ok = true;\n                break;\n            }\n        }\n\n        if (!ok) continue;\n        if (cand.xL == cur.xL && cand.xR == cur.xR &&\n            cand.yB == cur.yB && cand.yT == cur.yT) continue;\n\n        int diff = evaluateRectDiff(cand.xL, cand.yB, cand.xR, cand.yT, xs, ys, N);\n        if (diff > curDiff) {\n            cur = cand;\n            curDiff = diff;\n            if (diff > bestRect.diff) {\n                bestRect = {cand.xL, cand.yB, cand.xR, cand.yT, diff};\n            }\n            if (diff > bestDiff) {\n                bestDiff = diff;\n                bestPoly.clear();\n                bestPoly.push_back({cand.xL, cand.yB});\n                bestPoly.push_back({cand.xR, cand.yB});\n                bestPoly.push_back({cand.xR, cand.yT});\n                bestPoly.push_back({cand.xL, cand.yT});\n            }\n        }\n    }\n\n    // Final validity check; if invalid, fall back to full rectangle\n    auto checkPolygon = [&](const vector<pair<int,int>>& poly) -> bool {\n        int m = (int)poly.size();\n        if (m < 4 || m > 1000) return false;\n        long long per = 0;\n        for (int i = 0; i < m; ++i) {\n            auto &a = poly[i];\n            auto &b = poly[(i + 1) % m];\n            per += llabs((long long)a.first - b.first) + llabs((long long)a.second - b.second);\n        }\n        if (per > 400000LL) return false;\n        set<pair<int,int>> st(poly.begin(), poly.end());\n        if ((int)st.size() != m) return false;\n        return true;\n    };\n\n    if (!checkPolygon(bestPoly)) {\n        bestPoly = {\n            {0, 0},\n            {MAXC, 0},\n            {MAXC, MAXC},\n            {0, MAXC}\n        };\n    }\n\n    cout << bestPoly.size() << '\\n';\n    for (auto &p : bestPoly) {\n        cout << p.first << ' ' << p.second << '\\n';\n    }\n    return 0;\n}","ahc040":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct EvalResult {\n    long long W = (1LL<<62);\n    long long H = (1LL<<62);\n    long long S = (1LL<<62);\n    vector<int> cuts; // row boundaries: 0 = cuts[0] < ... < cuts[R] = N\n};\n\n// Evaluate a given orientation vector 'rot' (0=no-rot,1=rot):\n// compute best shelf segmentation (contiguous rows) and return W,H,S and cuts.\nEvalResult evaluate_orientation(const vector<long long>& w0,\n                                const vector<long long>& h0,\n                                const vector<int>& rot) {\n    int N = (int)w0.size();\n    const long long INF = (1LL<<62);\n\n    // Build width/height under this orientation\n    vector<long long> width(N), height(N);\n    long long sumW = 0, maxW = 0;\n    long double area = 0.0L;\n\n    for (int i = 0; i < N; i++) {\n        if (rot[i] == 0) {\n            width[i]  = w0[i];\n            height[i] = h0[i];\n        } else {\n            width[i]  = h0[i];\n            height[i] = w0[i];\n        }\n        sumW += width[i];\n        maxW = max(maxW, width[i]);\n        area += (long double)width[i] * (long double)height[i];\n    }\n\n    if (sumW == 0) { // degenerate, shouldn't happen\n        EvalResult res;\n        res.W = res.H = res.S = 0;\n        res.cuts = {0, N};\n        return res;\n    }\n\n    // Candidate width limits\n    vector<long long> Ws;\n    Ws.reserve(16);\n    Ws.push_back(sumW);  // one big row (upper extreme)\n    Ws.push_back(maxW);  // narrow rows (lower extreme)\n\n    long double base = sqrtl(max((long double)1.0L, area));\n    long double low  = max((long double)maxW, base * 0.5L);\n    long double high = min((long double)sumW, base * 2.0L);\n    if (high < low) high = low;\n\n    const int EXTRA = 10;\n    if (high == low) {\n        long long Wc = (long long)(low + 0.5L);\n        Ws.push_back(Wc);\n    } else {\n        for (int k = 0; k < EXTRA; k++) {\n            long double t = (k + 0.5L) / (long double)EXTRA;\n            long double w = low + (high - low) * t;\n            long long Wc = (long long)(w + 0.5L);\n            if (Wc < maxW) Wc = maxW;\n            if (Wc > sumW) Wc = sumW;\n            Ws.push_back(Wc);\n        }\n    }\n\n    sort(Ws.begin(), Ws.end());\n    Ws.erase(unique(Ws.begin(), Ws.end()), Ws.end());\n\n    EvalResult best;\n\n    vector<long long> dp(N + 1);\n    vector<int> prev(N + 1);\n\n    for (long long W_limit : Ws) {\n        // DP over prefix length\n        dp[0] = 0;\n        prev[0] = -1;\n        for (int i = 1; i <= N; i++) {\n            long long bestH = INF;\n            int bestJ = -1;\n            long long rowW = 0;\n            long long rowH = 0;\n            // consider last row being [j, i)\n            for (int j = i - 1; j >= 0; j--) {\n                rowW += width[j];\n                if (rowW > W_limit) break;\n                if (height[j] > rowH) rowH = height[j];\n                long long cand = dp[j] + rowH;\n                if (cand < bestH) {\n                    bestH = cand;\n                    bestJ = j;\n                }\n            }\n            dp[i] = bestH;\n            prev[i] = bestJ;\n        }\n        if (prev[N] == -1 || dp[N] >= INF) continue;\n\n        // Recover cuts\n        vector<int> cuts;\n        int cur = N;\n        cuts.push_back(N);\n        while (cur > 0) {\n            int pj = prev[cur];\n            if (pj < 0) { cuts.clear(); break; }\n            cuts.push_back(pj);\n            cur = pj;\n        }\n        if (cuts.empty()) continue;\n        if (cuts.back() != 0) {\n            // something went wrong; skip\n            continue;\n        }\n        reverse(cuts.begin(), cuts.end());\n\n        // Compute actual W,H\n        long long Htotal = 0;\n        long long Wactual = 0;\n        int R = (int)cuts.size() - 1;\n        for (int r = 0; r < R; r++) {\n            int L = cuts[r];\n            int Ridx = cuts[r+1];\n            long long rowW = 0;\n            long long rowH = 0;\n            for (int i = L; i < Ridx; i++) {\n                rowW += width[i];\n                if (height[i] > rowH) rowH = height[i];\n            }\n            Htotal += rowH;\n            if (rowW > Wactual) Wactual = rowW;\n        }\n        long long S = Htotal + Wactual;\n        if (S < best.S) {\n            best.S = S;\n            best.W = Wactual;\n            best.H = Htotal;\n            best.cuts = std::move(cuts);\n        }\n    }\n\n    // As a fallback, ensure we have some segmentation\n    if (best.S >= INF) {\n        best.cuts = {0, N};\n        long long Htotal = 0, Wactual = 0;\n        long long rowW = 0, rowH = 0;\n        for (int i = 0; i < N; i++) {\n            rowW += width[i];\n            if (height[i] > rowH) rowH = height[i];\n        }\n        Htotal = rowH;\n        Wactual = rowW;\n        best.W = Wactual;\n        best.H = Htotal;\n        best.S = Wactual + Htotal;\n    }\n\n    return best;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, T;\n    long long sigma;\n    if (!(cin >> N >> T >> sigma)) {\n        return 0;\n    }\n\n    vector<long long> w0(N), h0(N);\n    for (int i = 0; i < N; i++) {\n        cin >> w0[i] >> h0[i];\n        if (w0[i] < 1) w0[i] = 1;\n        if (h0[i] < 1) h0[i] = 1;\n    }\n\n    // Initial orientation: minimize height\n    vector<int> rot(N);\n    for (int i = 0; i < N; i++) {\n        // If h <= w, keep; else rotate so height=min\n        rot[i] = (h0[i] > w0[i]) ? 1 : 0;\n    }\n\n    // Local search over orientations\n    EvalResult bestEval = evaluate_orientation(w0, h0, rot);\n\n    const int MAX_PASSES = 2;\n    for (int pass = 0; pass < MAX_PASSES; pass++) {\n        bool improved = false;\n        for (int i = 0; i < N; i++) {\n            rot[i] ^= 1; // toggle\n            EvalResult cand = evaluate_orientation(w0, h0, rot);\n            if (cand.S < bestEval.S) {\n                bestEval = cand;\n                improved = true;\n            } else {\n                rot[i] ^= 1; // revert\n            }\n        }\n        if (!improved) break;\n    }\n\n    // Final width/height arrays under chosen orientation\n    vector<long long> width(N), height(N);\n    for (int i = 0; i < N; i++) {\n        if (rot[i] == 0) {\n            width[i]  = w0[i];\n            height[i] = h0[i];\n        } else {\n            width[i]  = h0[i];\n            height[i] = w0[i];\n        }\n    }\n\n    // Derive row index for each rectangle, and bases per row\n    vector<int>& cuts = bestEval.cuts;\n    int R = (int)cuts.size() - 1; // number of rows\n    vector<int> rowOf(N, 0);\n    for (int r = 0; r < R; r++) {\n        for (int i = cuts[r]; i < cuts[r+1]; i++) {\n            rowOf[i] = r;\n        }\n    }\n    vector<int> base(R, -1);\n    for (int r = 0; r < R; r++) {\n        int L = cuts[r];\n        int Ridx = cuts[r+1];\n        long long bestH = -1;\n        int bestIdx = L;\n        for (int i = L; i < Ridx; i++) {\n            if (height[i] > bestH) {\n                bestH = height[i];\n                bestIdx = i;\n            }\n        }\n        base[r] = bestIdx;\n    }\n\n    // We output the same arrangement T times\n    for (int t = 0; t < T; t++) {\n        // Number of rectangles used: all N\n        cout << N << '\\n';\n        for (int i = 0; i < N; i++) {\n            int r = rowOf[i];\n            int b = -1;\n            if (r > 0) {\n                b = base[r - 1]; // base of previous row\n            }\n            char d = 'L';\n            cout << i << ' ' << rot[i] << ' ' << d << ' ' << b << '\\n';\n        }\n        cout.flush();\n\n        long long Wm, Hm;\n        if (!(cin >> Wm >> Hm)) {\n            // In official judge this should not happen, but be safe\n            return 0;\n        }\n    }\n\n    return 0;\n}","ahc041":"#include <bits/stdc++.h>\nusing namespace std;\n\n// Simple fast RNG\nstruct FastRand {\n    uint64_t x;\n    FastRand() {\n        x = 88172645463393265ull;\n    }\n    uint64_t next() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return x;\n    }\n    int nextInt(int n) { // 0..n-1\n        return (int)(next() % (uint64_t)n);\n    }\n    double nextDouble() {\n        return (next() >> 11) * (1.0 / 9007199254740992.0); // [0,1)\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, H;\n    if (!(cin >> N >> M >> H)) {\n        return 0;\n    }\n\n    vector<int> A(N);\n    for (int i = 0; i < N; ++i) cin >> A[i];\n\n    vector<vector<int>> adj(N);\n    for (int i = 0; i < M; ++i) {\n        int u, v;\n        cin >> u >> v;\n        adj[u].push_back(v);\n        adj[v].push_back(u);\n    }\n\n    // Coordinates (unused in this solution, but must be read)\n    vector<int> x(N), y(N);\n    for (int i = 0; i < N; ++i) cin >> x[i] >> y[i];\n\n    // ---------- Initial forest construction: greedy by ascending beauty ----------\n    vector<int> parent(N, -1);\n    vector<int> depth(N, 0);\n    vector<char> processed(N, 0);\n\n    vector<int> orderAsc(N);\n    iota(orderAsc.begin(), orderAsc.end(), 0);\n    sort(orderAsc.begin(), orderAsc.end(), [&](int i, int j) {\n        if (A[i] != A[j]) return A[i] < A[j];\n        return i < j;\n    });\n\n    for (int idx = 0; idx < N; ++idx) {\n        int v = orderAsc[idx];\n        processed[v] = 1;\n        int bestParent = -1;\n        int bestDepth = -1;\n        for (int u : adj[v]) {\n            if (!processed[u]) continue;          // only already placed vertices\n            if (depth[u] > H - 1) continue;       // parent depth must allow child depth <= H\n            if (depth[u] > bestDepth) {\n                bestDepth = depth[u];\n                bestParent = u;\n            }\n        }\n        if (bestParent == -1) {\n            parent[v] = -1;\n            depth[v] = 0;\n        } else {\n            parent[v] = bestParent;\n            depth[v] = depth[bestParent] + 1;\n            if (depth[v] > H) depth[v] = H; // safety\n        }\n    }\n\n    // ---------- Build children lists ----------\n    vector<vector<int>> children(N);\n    for (int v = 0; v < N; ++v) {\n        int p = parent[v];\n        if (p != -1) children[p].push_back(v);\n    }\n\n    // ---------- Compute subtreeSum and subHeight bottom-up ----------\n    vector<vector<int>> nodesAtDepth(H + 1);\n    for (int v = 0; v < N; ++v) {\n        int d = depth[v];\n        if (d < 0) d = 0;\n        if (d > H) d = H;\n        nodesAtDepth[d].push_back(v);\n    }\n\n    vector<long long> subtreeSum(N, 0);\n    vector<int> subHeight(N, 0);\n\n    for (int d = H; d >= 0; --d) {\n        for (int v : nodesAtDepth[d]) {\n            long long sum = A[v];\n            int h = 0;\n            for (int c : children[v]) {\n                sum += subtreeSum[c];\n                h = max(h, 1 + subHeight[c]);\n            }\n            subtreeSum[v] = sum;\n            subHeight[v] = h;\n        }\n    }\n\n    // ---------- Compute initial score ----------\n    long long score = 0;\n    for (int v = 0; v < N; ++v) {\n        int d = depth[v];\n        if (d < 0) d = 0;\n        if (d > H) d = H;\n        score += (long long)(d + 1) * (long long)A[v];\n    }\n\n    // From now on, we get depths on demand from parent pointers.\n    auto getDepth = [&](int v) -> int {\n        int d = 0;\n        while (parent[v] != -1) {\n            v = parent[v];\n            ++d;\n        }\n        return d; // \u2264 H\n    };\n\n    // Best solution tracking (we will run extra local search / SA)\n    long long bestScore = score;\n    vector<int> bestParent = parent;\n\n    // ---------- Helpers for local modifications ----------\n    auto recomputeHeightFrom = [&](int start) {\n        int x = start;\n        while (x != -1) {\n            int old_h = subHeight[x];\n            int new_h = 0;\n            for (int c : children[x]) {\n                new_h = max(new_h, 1 + subHeight[c]);\n            }\n            if (new_h == old_h) break;\n            subHeight[x] = new_h;\n            x = parent[x];\n        }\n    };\n\n    auto reparentFn = [&](int v, int newParent, int oldDepth, int newDepth) {\n        int oldParent = parent[v];\n        if (oldParent == newParent) return;\n\n        long long deltaDepth = (long long)(newDepth - oldDepth);\n        long long deltaScore = deltaDepth * subtreeSum[v];\n        score += deltaScore;\n\n        // Update subtreeSum along old parent path: remove subtreeSum[v]\n        if (oldParent != -1) {\n            for (int x = oldParent; x != -1; x = parent[x]) {\n                subtreeSum[x] -= subtreeSum[v];\n            }\n        }\n\n        // Update subtreeSum along new parent path: add subtreeSum[v]\n        if (newParent != -1) {\n            for (int x = newParent; x != -1; x = parent[x]) {\n                subtreeSum[x] += subtreeSum[v];\n            }\n        }\n\n        // Update children lists\n        if (oldParent != -1) {\n            auto &vec = children[oldParent];\n            for (int i = 0; i < (int)vec.size(); ++i) {\n                if (vec[i] == v) {\n                    vec[i] = vec.back();\n                    vec.pop_back();\n                    break;\n                }\n            }\n        }\n        if (newParent != -1) {\n            children[newParent].push_back(v);\n        }\n\n        parent[v] = newParent;\n\n        // Update heights along old and new parent paths\n        if (oldParent != -1) recomputeHeightFrom(oldParent);\n        if (newParent != -1) recomputeHeightFrom(newParent);\n\n        // Record best solution\n        if (score > bestScore) {\n            bestScore = score;\n            bestParent = parent;\n        }\n    };\n\n    // ---------- Greedy hill climbing (depth-increasing only) ----------\n    vector<int> orderDesc(N);\n    iota(orderDesc.begin(), orderDesc.end(), 0);\n    sort(orderDesc.begin(), orderDesc.end(), [&](int i, int j) {\n        if (A[i] != A[j]) return A[i] > A[j];\n        return i < j;\n    });\n\n    bool improved;\n    do {\n        improved = false;\n        for (int v : orderDesc) {\n            int oldParent = parent[v];\n            int oldDepth = getDepth(v);\n            long long bestDelta = 0;\n            int bestP = oldParent;\n            int bestNewDepth = oldDepth;\n\n            for (int u : adj[v]) {\n                if (u == oldParent) continue;\n\n                // Check if u is in subtree of v (to avoid cycles)\n                int x = u;\n                bool cyc = false;\n                while (x != -1) {\n                    if (x == v) {\n                        cyc = true;\n                        break;\n                    }\n                    x = parent[x];\n                }\n                if (cyc) continue;\n\n                int du = getDepth(u);\n                int newDepth = du + 1;\n                if (newDepth > H) continue;\n                if (newDepth + subHeight[v] > H) continue;\n\n                long long deltaScore = (long long)(newDepth - oldDepth) * subtreeSum[v];\n                if (deltaScore > bestDelta) {\n                    bestDelta = deltaScore;\n                    bestP = u;\n                    bestNewDepth = newDepth;\n                }\n            }\n\n            if (bestP != oldParent && bestDelta > 0) {\n                reparentFn(v, bestP, oldDepth, bestNewDepth);\n                improved = true;\n            }\n        }\n    } while (improved);\n\n    // ---------- Simulated annealing to escape local maxima ----------\n    FastRand rng;\n    // Time budget for SA only; initial phases are extra but cheap.\n    const double TIME_LIMIT = 1.5; // seconds\n    const double T0 = 200000.0;\n    const double T1 = 10.0;\n\n    auto startTime = chrono::steady_clock::now();\n    double T = T0;\n\n    int iter = 0;\n    while (true) {\n        ++iter;\n        if ((iter & 1023) == 0) {\n            double elapsed = chrono::duration<double>(chrono::steady_clock::now() - startTime).count();\n            if (elapsed > TIME_LIMIT) break;\n            double t = elapsed / TIME_LIMIT;\n            if (t > 1.0) t = 1.0;\n            T = T0 + (T1 - T0) * t; // linear cooling\n            if (T < T1) T = T1;\n        }\n\n        int v = rng.nextInt(N);\n        int deg = (int)adj[v].size();\n        if (deg == 0 && parent[v] == -1) continue; // just in case\n\n        // Choose a new parent: one of neighbors or -1 (make root)\n        int choice = rng.nextInt(deg + 1); // 0..deg\n        int newParent = (choice == deg ? -1 : adj[v][choice]);\n\n        if (newParent == parent[v]) continue;\n\n        // Cycle check (only needed if newParent != -1)\n        if (newParent != -1) {\n            int x = newParent;\n            bool cyc = false;\n            while (x != -1) {\n                if (x == v) {\n                    cyc = true;\n                    break;\n                }\n                x = parent[x];\n            }\n            if (cyc) continue;\n        }\n\n        int oldDepth = getDepth(v);\n        int newDepth;\n        if (newParent == -1) {\n            newDepth = 0;\n        } else {\n            int du = getDepth(newParent);\n            newDepth = du + 1;\n        }\n\n        if (newDepth > H) continue;\n        if (newDepth + subHeight[v] > H) continue;\n\n        long long deltaScore = (long long)(newDepth - oldDepth) * subtreeSum[v];\n\n        if (deltaScore >= 0) {\n            reparentFn(v, newParent, oldDepth, newDepth);\n        } else {\n            double prob = exp((double)deltaScore / T);  // deltaScore < 0\n            double r = rng.nextDouble();\n            if (r < prob) {\n                reparentFn(v, newParent, oldDepth, newDepth);\n            }\n        }\n    }\n\n    // ---------- Output best found solution ----------\n    for (int i = 0; i < N; ++i) {\n        if (i) cout << ' ';\n        cout << bestParent[i];\n    }\n    cout << '\\n';\n\n    return 0;\n}","ahc042":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Operation {\n    char dir;      // 'U', 'D', 'L', 'R' : direction of the first half\n    int  p;        // row or column index\n    int  len;      // number of shifts in each direction\n    int  cost;     // 2 * len\n    uint64_t mask; // which Oni are removed by this operation\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    if (!(cin >> N)) return 0;\n    vector<string> C(N);\n    for (int i = 0; i < N; ++i) cin >> C[i];\n\n    // Collect Oni and Fuku positions\n    vector<pair<int,int>> oni;  // (row,col) for each Oni\n    vector<vector<int>> oni_id(N, vector<int>(N, -1));\n    vector<vector<bool>> fuku(N, vector<bool>(N, false));\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            char ch = C[i][j];\n            if (ch == 'x') {\n                int id = (int)oni.size();\n                oni.emplace_back(i, j);\n                oni_id[i][j] = id;\n            } else if (ch == 'o') {\n                fuku[i][j] = true;\n            }\n        }\n    }\n\n    int M = (int)oni.size(); // number of Oni, should be 2N\n    if (M == 0) {\n        // No Oni: nothing to do\n        return 0;\n    }\n\n    // Prefix sums of Fuku for rows and columns\n    vector<vector<int>> row_pref(N, vector<int>(N, 0));\n    vector<vector<int>> col_pref(N, vector<int>(N, 0));\n\n    for (int i = 0; i < N; ++i) {\n        int acc = 0;\n        for (int j = 0; j < N; ++j) {\n            if (fuku[i][j]) acc++;\n            row_pref[i][j] = acc;\n        }\n    }\n    for (int j = 0; j < N; ++j) {\n        int acc = 0;\n        for (int i = 0; i < N; ++i) {\n            if (fuku[i][j]) acc++;\n            col_pref[j][i] = acc;\n        }\n    }\n\n    vector<Operation> ops;\n    ops.reserve(4 * N * N);\n\n    // Build all safe column operations\n    for (int j = 0; j < N; ++j) {\n        int total_fuku_col = col_pref[j][N-1];\n\n        // Up-prefix [0..h]\n        for (int h = 0; h < N; ++h) {\n            if (col_pref[j][h] == 0) { // no Fuku in [0..h]\n                uint64_t mask = 0;\n                for (int id = 0; id < M; ++id) {\n                    auto [r, c] = oni[id];\n                    if (c == j && r <= h) {\n                        mask |= (1ULL << id);\n                    }\n                }\n                if (mask) {\n                    int len = h + 1;\n                    Operation op;\n                    op.dir = 'U';\n                    op.p = j;\n                    op.len = len;\n                    op.cost = 2 * len;\n                    op.mask = mask;\n                    ops.push_back(op);\n                }\n            }\n        }\n\n        // Down-suffix [h..N-1]\n        for (int h = 0; h < N; ++h) {\n            int fuku_cnt = total_fuku_col - (h > 0 ? col_pref[j][h-1] : 0);\n            if (fuku_cnt == 0) { // no Fuku in [h..N-1]\n                uint64_t mask = 0;\n                for (int id = 0; id < M; ++id) {\n                    auto [r, c] = oni[id];\n                    if (c == j && r >= h) {\n                        mask |= (1ULL << id);\n                    }\n                }\n                if (mask) {\n                    int len = N - h;\n                    Operation op;\n                    op.dir = 'D';\n                    op.p = j;\n                    op.len = len;\n                    op.cost = 2 * len;\n                    op.mask = mask;\n                    ops.push_back(op);\n                }\n            }\n        }\n    }\n\n    // Build all safe row operations\n    for (int i = 0; i < N; ++i) {\n        int total_fuku_row = row_pref[i][N-1];\n\n        // Left-prefix [0..h]\n        for (int h = 0; h < N; ++h) {\n            if (row_pref[i][h] == 0) { // no Fuku in [0..h]\n                uint64_t mask = 0;\n                for (int id = 0; id < M; ++id) {\n                    auto [r, c] = oni[id];\n                    if (r == i && c <= h) {\n                        mask |= (1ULL << id);\n                    }\n                }\n                if (mask) {\n                    int len = h + 1;\n                    Operation op;\n                    op.dir = 'L';\n                    op.p = i;\n                    op.len = len;\n                    op.cost = 2 * len;\n                    op.mask = mask;\n                    ops.push_back(op);\n                }\n            }\n        }\n\n        // Right-suffix [h..N-1]\n        for (int h = 0; h < N; ++h) {\n            int fuku_cnt = total_fuku_row - (h > 0 ? row_pref[i][h-1] : 0);\n            if (fuku_cnt == 0) { // no Fuku in [h..N-1]\n                uint64_t mask = 0;\n                for (int id = 0; id < M; ++id) {\n                    auto [r, c] = oni[id];\n                    if (r == i && c >= h) {\n                        mask |= (1ULL << id);\n                    }\n                }\n                if (mask) {\n                    int len = N - h;\n                    Operation op;\n                    op.dir = 'R';\n                    op.p = i;\n                    op.len = len;\n                    op.cost = 2 * len;\n                    op.mask = mask;\n                    ops.push_back(op);\n                }\n            }\n        }\n    }\n\n    if (ops.empty()) {\n        // Should not happen due to problem guarantees, but be safe.\n        return 0;\n    }\n\n    // Deduplicate operations by their Oni-mask, keeping the cheapest one\n    sort(ops.begin(), ops.end(), [](const Operation &a, const Operation &b) {\n        if (a.mask != b.mask) return a.mask < b.mask;\n        if (a.cost != b.cost) return a.cost < b.cost;\n        if (a.dir != b.dir)   return a.dir < b.dir;\n        if (a.p != b.p)       return a.p < b.p;\n        return a.len < b.len;\n    });\n\n    {\n        vector<Operation> filtered;\n        filtered.reserve(ops.size());\n        for (int i = 0; i < (int)ops.size(); ) {\n            int j = i + 1;\n            Operation best = ops[i];\n            while (j < (int)ops.size() && ops[j].mask == ops[i].mask) {\n                if (ops[j].cost < best.cost) best = ops[j];\n                ++j;\n            }\n            filtered.push_back(best);\n            i = j;\n        }\n        ops.swap(filtered);\n    }\n\n    int K_ops = (int)ops.size();\n\n    // Build cover lists: for each Oni, which operations cover it\n    vector<vector<int>> cover_ops(M);\n    for (int idx = 0; idx < K_ops; ++idx) {\n        uint64_t m = ops[idx].mask;\n        while (m) {\n            int b = __builtin_ctzll(m);\n            m &= m - 1;\n            cover_ops[b].push_back(idx);\n        }\n    }\n\n    // Safety: each Oni must be coverable\n    for (int i = 0; i < M; ++i) {\n        if (cover_ops[i].empty()) {\n            // Extremely unlikely if generation is correct; fallback: do nothing\n            return 0;\n        }\n    }\n\n    uint64_t all_mask = (M == 64) ? ~0ULL : ((1ULL << M) - 1);\n\n    // Weights for Oni: rarer Oni (fewer covering operations) get higher weight\n    vector<double> oni_weight(M);\n    for (int i = 0; i < M; ++i) {\n        int deg = (int)cover_ops[i].size();\n        oni_weight[i] = (deg > 0 ? 1.0 / deg : 1.0);\n    }\n\n    // RNG for randomized greedy\n    uint64_t seed = chrono::steady_clock::now().time_since_epoch().count();\n    mt19937_64 rng(seed);\n\n    int best_cost = INT_MAX / 2;\n    vector<int> best_sel;\n\n    // Helper: prune redundant selected operations\n    auto prune_selected = [&](vector<bool> &selected, int &total_cost, vector<int> &cover_count) {\n        bool changed = true;\n        while (changed) {\n            changed = false;\n            uint64_t singular_mask = 0;\n            for (int i = 0; i < M; ++i) {\n                if (cover_count[i] == 1) singular_mask |= (1ULL << i);\n            }\n            for (int op_idx = 0; op_idx < K_ops; ++op_idx) {\n                if (!selected[op_idx]) continue;\n                if ((ops[op_idx].mask & singular_mask) == 0) {\n                    // Removing this op won't uncover any Oni\n                    selected[op_idx] = false;\n                    total_cost -= ops[op_idx].cost;\n                    uint64_t m = ops[op_idx].mask;\n                    while (m) {\n                        int b = __builtin_ctzll(m);\n                        m &= m - 1;\n                        cover_count[b]--;\n                    }\n                    changed = true;\n                }\n            }\n        }\n    };\n\n    // Local search: 1-for-1 and 1-for-2 exchanges\n    auto local_search = [&](vector<int> &sel, int &cost) {\n        vector<bool> selected(K_ops, false);\n        vector<int> cover_count(M, 0);\n        int total_cost = 0;\n\n        for (int idx : sel) {\n            if (!selected[idx]) {\n                selected[idx] = true;\n                total_cost += ops[idx].cost;\n                uint64_t m = ops[idx].mask;\n                while (m) {\n                    int b = __builtin_ctzll(m);\n                    m &= m - 1;\n                    cover_count[b]++;\n                }\n            }\n        }\n\n        prune_selected(selected, total_cost, cover_count);\n\n        // If coverage is broken for some reason, abort local search\n        for (int i = 0; i < M; ++i) {\n            if (cover_count[i] == 0) {\n                return;\n            }\n        }\n\n        vector<int> mark(K_ops, 0);\n        int currentMark = 1;\n        vector<int> cand;\n        cand.reserve(64);\n\n        bool improved = true;\n        while (improved) {\n            improved = false;\n\n            // 1-for-1 improvements\n            uint64_t singular_mask = 0;\n            for (int i = 0; i < M; ++i) {\n                if (cover_count[i] == 1) singular_mask |= (1ULL << i);\n            }\n\n            for (int a = 0; a < K_ops && !improved; ++a) {\n                if (!selected[a]) continue;\n                uint64_t U_mask = ops[a].mask & singular_mask;\n                if (!U_mask) continue;\n\n                cand.clear();\n                if (++currentMark == INT_MAX) {\n                    fill(mark.begin(), mark.end(), 0);\n                    currentMark = 1;\n                }\n                uint64_t tmp = U_mask;\n                while (tmp) {\n                    int b = __builtin_ctzll(tmp);\n                    tmp &= tmp - 1;\n                    for (int op_idx : cover_ops[b]) {\n                        if (mark[op_idx] != currentMark) {\n                            mark[op_idx] = currentMark;\n                            cand.push_back(op_idx);\n                        }\n                    }\n                }\n\n                for (int b_idx : cand) {\n                    if (selected[b_idx]) continue;\n                    if (ops[b_idx].cost >= ops[a].cost) continue;\n                    if ((ops[b_idx].mask & U_mask) == U_mask) {\n                        // 1-for-1 replacement: a -> b_idx\n                        selected[a] = false;\n                        selected[b_idx] = true;\n                        total_cost += ops[b_idx].cost - ops[a].cost;\n\n                        uint64_t ma = ops[a].mask;\n                        while (ma) {\n                            int bit = __builtin_ctzll(ma);\n                            ma &= ma - 1;\n                            cover_count[bit]--;\n                        }\n                        uint64_t mb = ops[b_idx].mask;\n                        while (mb) {\n                            int bit = __builtin_ctzll(mb);\n                            mb &= mb - 1;\n                            cover_count[bit]++;\n                        }\n\n                        prune_selected(selected, total_cost, cover_count);\n                        improved = true;\n                        break;\n                    }\n                }\n            }\n\n            if (improved) continue;\n\n            // 1-for-2 improvements\n            singular_mask = 0;\n            for (int i = 0; i < M; ++i) {\n                if (cover_count[i] == 1) singular_mask |= (1ULL << i);\n            }\n\n            for (int a = 0; a < K_ops && !improved; ++a) {\n                if (!selected[a]) continue;\n                uint64_t U_mask = ops[a].mask & singular_mask;\n                if (!U_mask) continue;\n\n                cand.clear();\n                if (++currentMark == INT_MAX) {\n                    fill(mark.begin(), mark.end(), 0);\n                    currentMark = 1;\n                }\n                uint64_t tmp = U_mask;\n                while (tmp) {\n                    int b = __builtin_ctzll(tmp);\n                    tmp &= tmp - 1;\n                    for (int op_idx : cover_ops[b]) {\n                        if (mark[op_idx] != currentMark) {\n                            mark[op_idx] = currentMark;\n                            cand.push_back(op_idx);\n                        }\n                    }\n                }\n\n                int csz = (int)cand.size();\n                for (int i1 = 0; i1 < csz && !improved; ++i1) {\n                    int b_idx = cand[i1];\n                    if (selected[b_idx]) continue;\n                    for (int i2 = i1 + 1; i2 < csz; ++i2) {\n                        int c_idx = cand[i2];\n                        if (selected[c_idx]) continue;\n                        int newCost = ops[b_idx].cost + ops[c_idx].cost;\n                        if (newCost >= ops[a].cost) continue;\n                        uint64_t union_mask = ops[b_idx].mask | ops[c_idx].mask;\n                        if ((union_mask & U_mask) == U_mask) {\n                            // 1-for-2 replacement: a -> b_idx, c_idx\n                            selected[a] = false;\n                            selected[b_idx] = true;\n                            selected[c_idx] = true;\n                            total_cost += newCost - ops[a].cost;\n\n                            uint64_t ma = ops[a].mask;\n                            while (ma) {\n                                int bit = __builtin_ctzll(ma);\n                                ma &= ma - 1;\n                                cover_count[bit]--;\n                            }\n                            uint64_t mb = ops[b_idx].mask;\n                            while (mb) {\n                                int bit = __builtin_ctzll(mb);\n                                mb &= mb - 1;\n                                cover_count[bit]++;\n                            }\n                            uint64_t mc = ops[c_idx].mask;\n                            while (mc) {\n                                int bit = __builtin_ctzll(mc);\n                                mc &= mc - 1;\n                                cover_count[bit]++;\n                            }\n\n                            prune_selected(selected, total_cost, cover_count);\n                            improved = true;\n                            break;\n                        }\n                    }\n                }\n            }\n        }\n\n        // Final coverage check\n        for (int i = 0; i < M; ++i) {\n            if (cover_count[i] == 0) {\n                // Something went wrong; keep original sel/cost\n                return;\n            }\n        }\n\n        vector<int> new_sel;\n        new_sel.reserve(M);\n        for (int i = 0; i < K_ops; ++i) {\n            if (selected[i]) new_sel.push_back(i);\n        }\n\n        sel.swap(new_sel);\n        cost = total_cost;\n    };\n\n    // Greedy (GRASP-like) set cover with multiple scoring heuristics\n    auto run_greedy = [&](int score_type, int RCL_SIZE, mt19937_64 &rng) -> pair<int, vector<int>> {\n        uint64_t uncovered = all_mask;\n        vector<int> chosen;\n        chosen.reserve(M);\n        int greedy_cost = 0;\n\n        while (uncovered) {\n            // RCL: top RCL_SIZE candidates by score\n            vector<double> bestRatios(RCL_SIZE, -1.0);\n            vector<int> bestIdx(RCL_SIZE, -1);\n\n            for (int i = 0; i < K_ops; ++i) {\n                uint64_t gainMask = ops[i].mask & uncovered;\n                if (!gainMask) continue;\n\n                int nGain = __builtin_popcountll(gainMask);\n                double wGain = 0.0;\n                uint64_t tmp = gainMask;\n                while (tmp) {\n                    int b = __builtin_ctzll(tmp);\n                    tmp &= tmp - 1;\n                    wGain += oni_weight[b];\n                }\n\n                double ratio;\n                switch (score_type) {\n                    case 0: // weighted gain / cost\n                        ratio = wGain / (double)ops[i].cost;\n                        break;\n                    case 1: // raw gain / cost\n                        ratio = (double)nGain / (double)ops[i].cost;\n                        break;\n                    case 2: // gain / sqrt(cost)\n                        ratio = (double)nGain / sqrt((double)ops[i].cost);\n                        break;\n                    case 3: // (weighted gain)^2 / cost\n                    default:\n                        ratio = (wGain * wGain) / (double)ops[i].cost;\n                        break;\n                }\n\n                for (int k = 0; k < RCL_SIZE; ++k) {\n                    if (ratio > bestRatios[k]) {\n                        for (int sh = RCL_SIZE - 1; sh > k; --sh) {\n                            bestRatios[sh] = bestRatios[sh - 1];\n                            bestIdx[sh] = bestIdx[sh - 1];\n                        }\n                        bestRatios[k] = ratio;\n                        bestIdx[k] = i;\n                        break;\n                    }\n                }\n            }\n\n            if (bestIdx[0] == -1) {\n                // Cannot cover remaining Oni (should not happen)\n                break;\n            }\n\n            // Early stop if this run can't beat current best\n            if (greedy_cost >= best_cost) {\n                return make_pair(INT_MAX / 2, vector<int>());\n            }\n\n            int rcl_end = 0;\n            while (rcl_end + 1 < RCL_SIZE && bestIdx[rcl_end + 1] != -1) ++rcl_end;\n            uniform_int_distribution<int> dist(0, rcl_end);\n            int chosen_pos = dist(rng);\n            int op_idx = bestIdx[chosen_pos];\n\n            chosen.push_back(op_idx);\n            uint64_t gainMask = ops[op_idx].mask & uncovered;\n            uncovered &= ~gainMask;\n            greedy_cost += ops[op_idx].cost;\n        }\n\n        if (uncovered) {\n            // Failed to cover all Oni\n            return make_pair(INT_MAX / 2, vector<int>());\n        }\n\n        // Remove duplicates and prune redundancies\n        vector<bool> selected(K_ops, false);\n        vector<int> cover_count(M, 0);\n        int total_cost = 0;\n        for (int idx : chosen) {\n            if (!selected[idx]) {\n                selected[idx] = true;\n                total_cost += ops[idx].cost;\n                uint64_t m = ops[idx].mask;\n                while (m) {\n                    int b = __builtin_ctzll(m);\n                    m &= m - 1;\n                    cover_count[b]++;\n                }\n            }\n        }\n\n        prune_selected(selected, total_cost, cover_count);\n\n        // Verify coverage (for safety)\n        for (int i = 0; i < M; ++i) {\n            if (cover_count[i] == 0) {\n                return make_pair(INT_MAX / 2, vector<int>());\n            }\n        }\n\n        vector<int> result;\n        result.reserve(M);\n        for (int i = 0; i < K_ops; ++i) {\n            if (selected[i]) result.push_back(i);\n        }\n\n        return make_pair(total_cost, move(result));\n    };\n\n    // Multi-start greedy with early stopping based on stagnation\n    const int MAX_RUNS = 260;\n    const int MAX_STAG = 120;\n    int stagnation = 0;\n\n    uniform_int_distribution<int> scoreDist(0, 3);\n    uniform_int_distribution<int> rclDist(2, 6);\n\n    for (int iter = 0; iter < MAX_RUNS && stagnation < MAX_STAG; ++iter) {\n        int score_type = scoreDist(rng);\n        int RCL_SIZE = rclDist(rng);\n\n        auto [cost, sel] = run_greedy(score_type, RCL_SIZE, rng);\n        if (cost >= INT_MAX / 4) {\n            ++stagnation;\n            continue;\n        }\n\n        uint64_t covered = 0;\n        for (int idx : sel) covered |= ops[idx].mask;\n        if (covered != all_mask) {\n            ++stagnation;\n            continue;\n        }\n\n        // Apply local search to refine this solution\n        int ls_cost = cost;\n        vector<int> ls_sel = sel;\n        local_search(ls_sel, ls_cost);\n\n        uint64_t covered_ls = 0;\n        for (int idx : ls_sel) covered_ls |= ops[idx].mask;\n        if (covered_ls != all_mask) {\n            // If local search broke coverage (shouldn't), fall back to greedy result\n            ls_cost = cost;\n            ls_sel = sel;\n            covered_ls = covered;\n        }\n\n        if (ls_cost < best_cost) {\n            best_cost = ls_cost;\n            best_sel = move(ls_sel);\n            stagnation = 0;\n        } else {\n            ++stagnation;\n        }\n    }\n\n    if (best_sel.empty()) {\n        // Fallback: run one deterministic greedy\n        auto [cost, sel] = run_greedy(0, 4, rng);\n        best_cost = cost;\n        best_sel = move(sel);\n    }\n\n    // Build the actual move sequence from best_sel\n    vector<pair<char,int>> moves;\n    moves.reserve(best_cost);\n\n    for (int idx : best_sel) {\n        const Operation &op = ops[idx];\n        char d1 = op.dir;\n        char d2;\n        if      (d1 == 'U') d2 = 'D';\n        else if (d1 == 'D') d2 = 'U';\n        else if (d1 == 'L') d2 = 'R';\n        else               d2 = 'L';\n\n        for (int k = 0; k < op.len; ++k) moves.emplace_back(d1, op.p);\n        for (int k = 0; k < op.len; ++k) moves.emplace_back(d2, op.p);\n    }\n\n    int T = (int)moves.size();\n    if (T > 4 * N * N) {\n        // Extremely unlikely with the above reasoning, but be safe.\n        return 0;\n    }\n\n    for (auto &mv : moves) {\n        cout << mv.first << ' ' << mv.second << '\\n';\n    }\n\n    return 0;\n}","ahc044":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const int MAXN = 100;\n\nstruct Candidate {\n    int a[MAXN];\n    int b[MAXN];\n    int t[MAXN];\n    int used[MAXN][2]; // edge usage counts: 0 -> a[i], 1 -> b[i]\n    long long E;\n};\n\n// Evaluate candidate by rotor-router simulation for L weeks\nvoid evalCandidate(Candidate &cand, int N, int L, const vector<long long> &T) {\n    static int rotor[MAXN];\n    for (int i = 0; i < N; ++i) {\n        cand.t[i] = 0;\n        rotor[i] = 0;\n        cand.used[i][0] = cand.used[i][1] = 0;\n    }\n\n    int cur = 0;  // week 1 cleaner is 0\n\n    // weeks 1..L-1: decide next cleaner\n    for (int week = 0; week < L - 1; ++week) {\n        int x = cur;\n        cand.t[x]++;\n\n        int e = rotor[x];\n        rotor[x] ^= 1;\n        int nxt = (e == 0 ? cand.a[x] : cand.b[x]);\n        cand.used[x][e]++;\n\n        cur = nxt;\n    }\n    // last week: count the final cleaner\n    cand.t[cur]++;\n\n    long long E = 0;\n    for (int i = 0; i < N; ++i) {\n        E += llabs((long long)cand.t[i] - T[i]);\n    }\n    cand.E = E;\n}\n\n// Build an \"ideal schedule\" based candidate using majority transitions\nCandidate buildMajorityCandidate(int N, int L, const vector<long long> &T, mt19937_64 &rng) {\n    Candidate cand;\n\n    // Work copy of T, ensure employee 0 appears at least once\n    vector<int> Twork(N);\n    for (int i = 0; i < N; ++i) Twork[i] = (int)T[i];\n\n    if (Twork[0] == 0) {\n        int j = 1;\n        for (int i = 2; i < N; ++i) {\n            if (Twork[i] > Twork[j]) j = i;\n        }\n        if (Twork[j] > 0) {\n            Twork[0] = 1;\n            Twork[j]--;\n        } else {\n            for (int i = 1; i < N; ++i) {\n                if (Twork[i] > 0) {\n                    Twork[i]--;\n                    break;\n                }\n            }\n            Twork[0] = 1;\n        }\n    }\n\n    // Build sequence of length L with counts Twork\n    vector<int> seq(L);\n    int pos = 0;\n    for (int i = 0; i < N; ++i) {\n        for (int k = 0; k < Twork[i]; ++k) {\n            if (pos < L) seq[pos++] = i;\n        }\n    }\n    if (pos < L) {\n        for (; pos < L; ++pos) seq[pos] = 0;\n    } else if (pos > L) {\n        seq.resize(L);\n    }\n\n    shuffle(seq.begin(), seq.end(), rng);\n\n    // Ensure seq[0] == 0 (since week1 cleaner is 0 in real process)\n    if (seq[0] != 0) {\n        for (int i = 1; i < L; ++i) {\n            if (seq[i] == 0) {\n                swap(seq[0], seq[i]);\n                break;\n            }\n        }\n        seq[0] = 0; // safety\n    }\n\n    vector<vector<int>> freqOdd(N, vector<int>(N, 0));\n    vector<vector<int>> freqEven(N, vector<int>(N, 0));\n    vector<int> cntVisit(N, 0);\n\n    for (int i = 0; i < N; ++i) cntVisit[i] = 0;\n\n    for (int i = 0; i < L - 1; ++i) {\n        int x = seq[i];\n        int y = seq[i + 1];\n        int k = ++cntVisit[x];\n        if (k & 1) freqOdd[x][y]++;\n        else       freqEven[x][y]++;\n    }\n\n    // Fallback destination: employee with largest T[i]\n    int fallback = 0;\n    for (int i = 1; i < N; ++i) {\n        if (T[i] > T[fallback]) fallback = i;\n    }\n\n    for (int x = 0; x < N; ++x) {\n        int best_j = fallback;\n        int best_c = 0;\n        for (int y = 0; y < N; ++y) {\n            if (freqOdd[x][y] > best_c) {\n                best_c = freqOdd[x][y];\n                best_j = y;\n            }\n        }\n        cand.a[x] = best_j;\n\n        best_j = fallback;\n        best_c = 0;\n        for (int y = 0; y < N; ++y) {\n            if (freqEven[x][y] > best_c) {\n                best_c = freqEven[x][y];\n                best_j = y;\n            }\n        }\n        cand.b[x] = best_j;\n    }\n\n    evalCandidate(cand, N, L, T);\n    return cand;\n}\n\n// Build template of edge destinations by apportionment according to T\nvector<int> buildDestTemplate(int N, const vector<long long> &T) {\n    vector<double> w(N);\n    double sumW = 0.0;\n    for (int i = 0; i < N; ++i) {\n        w[i] = (double)T[i] + 1.0; // +1 to avoid zero\n        sumW += w[i];\n    }\n    int totalEdges = 2 * N;\n\n    vector<double> ideal(N), frac(N);\n    vector<int> destCount(N, 0);\n    long long S = 0;\n\n    for (int i = 0; i < N; ++i) {\n        double val = totalEdges * w[i] / sumW;\n        ideal[i] = val;\n        int base = (int)floor(val);\n        destCount[i] = base;\n        frac[i] = val - base;\n        S += base;\n    }\n    int R = totalEdges - (int)S;\n    if (R < 0) R = 0;\n\n    vector<int> ord(N);\n    iota(ord.begin(), ord.end(), 0);\n    sort(ord.begin(), ord.end(), [&](int a, int b) {\n        return frac[a] > frac[b];\n    });\n    for (int k = 0; k < R && k < N; ++k) {\n        destCount[ord[k]]++;\n    }\n\n    vector<int> edgesDest;\n    edgesDest.reserve(totalEdges);\n    for (int i = 0; i < N; ++i) {\n        for (int c = 0; c < destCount[i]; ++c) {\n            edgesDest.push_back(i);\n        }\n    }\n    while ((int)edgesDest.size() > totalEdges) edgesDest.pop_back();\n    while ((int)edgesDest.size() < totalEdges) edgesDest.push_back(0);\n\n    return edgesDest;\n}\n\n// Build a random candidate from a given destination template\nCandidate buildRandomCandidateFromTemplate(const vector<int> &edgesTemplate,\n                                           int N, int L,\n                                           const vector<long long> &T,\n                                           mt19937_64 &rng) {\n    Candidate cand;\n    vector<int> edges = edgesTemplate; // copy\n    shuffle(edges.begin(), edges.end(), rng);\n\n    for (int i = 0; i < N; ++i) {\n        cand.a[i] = edges[2 * i];\n        cand.b[i] = edges[2 * i + 1];\n    }\n    evalCandidate(cand, N, L, T);\n    return cand;\n}\n\n// Mutate node idx's outgoing edges in candidate based on deficits (random/diversification move)\nvoid mutateNode(int idx,\n                Candidate &cand,\n                int N,\n                const vector<long long> &T,\n                const vector<int> &deficit,\n                const vector<int> &posIndices,\n                const vector<long long> &posPrefix,\n                long long sumPos,\n                const vector<long long> &Tprefix,\n                long long sumTw,\n                mt19937_64 &rng) {\n    auto samplePos = [&]() -> int {\n        if (sumPos <= 0 || posIndices.empty()) {\n            return idx; // fallback (should not generally happen)\n        }\n        long long r = (long long)(rng() % sumPos);\n        int pos = int(lower_bound(posPrefix.begin(), posPrefix.end(), r + 1) - posPrefix.begin());\n        if (pos < 0) pos = 0;\n        if (pos >= (int)posIndices.size()) pos = (int)posIndices.size() - 1;\n        return posIndices[pos];\n    };\n\n    auto sampleTdist = [&]() -> int {\n        if (sumTw <= 0) return idx;\n        long long r = (long long)(rng() % sumTw);\n        int pos = int(upper_bound(Tprefix.begin(), Tprefix.end(), r) - Tprefix.begin());\n        if (pos < 0) pos = 0;\n        if (pos >= N) pos = N - 1;\n        return pos;\n    };\n\n    if (deficit[idx] > 0) {\n        // node needs more visits: encourage self-loop\n        cand.a[idx] = idx;\n        if (sumPos > 0) {\n            cand.b[idx] = samplePos();\n        } else {\n            cand.b[idx] = sampleTdist();\n        }\n    } else {\n        // node has enough or too many visits: redirect to under-visited nodes\n        if (sumPos > 0) {\n            cand.a[idx] = samplePos();\n            cand.b[idx] = samplePos();\n        } else {\n            cand.a[idx] = sampleTdist();\n            cand.b[idx] = sampleTdist();\n        }\n    }\n\n    if (cand.a[idx] < 0) cand.a[idx] = 0;\n    if (cand.a[idx] >= N) cand.a[idx] = N - 1;\n    if (cand.b[idx] < 0) cand.b[idx] = 0;\n    if (cand.b[idx] >= N) cand.b[idx] = N - 1;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, L;\n    if (!(cin >> N >> L)) {\n        return 0;\n    }\n    vector<long long> T(N);\n    for (int i = 0; i < N; ++i) cin >> T[i];\n\n    mt19937_64 rng(123456789ULL);\n\n    auto startTime = chrono::steady_clock::now();\n    const int TIME_LIMIT_MS = 1950;\n\n    // Pre-build destination template from T\n    vector<int> destTemplate = buildDestTemplate(N, T);\n\n    // Best candidate\n    Candidate best;\n    bool bestInitialized = false;\n\n    // 1) Majority-based candidate from a shuffled ideal sequence\n    Candidate candMaj = buildMajorityCandidate(N, L, T, rng);\n    best = candMaj;\n    bestInitialized = true;\n\n    // 2) Some random candidates from destination template\n    const int INIT_RANDOM = 40;\n    for (int i = 0; i < INIT_RANDOM; ++i) {\n        Candidate c = buildRandomCandidateFromTemplate(destTemplate, N, L, T, rng);\n        if (!bestInitialized || c.E < best.E) {\n            best = c;\n            bestInitialized = true;\n        }\n    }\n\n    // Precompute T-weighted distribution for fallback sampling in local search\n    vector<long long> Tprefix(N);\n    long long sumTw = 0;\n    for (int i = 0; i < N; ++i) {\n        sumTw += (long long)T[i] + 1;\n        Tprefix[i] = sumTw;\n    }\n\n    // Local search: deficits and positive-deficit distribution\n    vector<int> deficit(N);\n    for (int i = 0; i < N; ++i) {\n        deficit[i] = (int)(T[i] - best.t[i]);\n    }\n\n    vector<int> posIndices;\n    vector<long long> posPrefix;\n    long long sumPos = 0;\n\n    auto updatePosDist = [&]() {\n        posIndices.clear();\n        posPrefix.clear();\n        sumPos = 0;\n        for (int i = 0; i < N; ++i) {\n            if (deficit[i] > 0) {\n                posIndices.push_back(i);\n                sumPos += deficit[i];\n                posPrefix.push_back(sumPos);\n            }\n        }\n    };\n    updatePosDist();\n\n    const int LOCAL_ITER_MAX = 600;\n\n    for (int iter = 0; iter < LOCAL_ITER_MAX; ++iter) {\n        if (iter % 8 == 0) {\n            auto now = chrono::steady_clock::now();\n            long long elapsed = chrono::duration_cast<chrono::milliseconds>(now - startTime).count();\n            if (elapsed > TIME_LIMIT_MS) break;\n        }\n\n        Candidate cand = best;  // copy\n\n        int numMut = 1;\n        if (iter > 200) numMut = 2;\n        if (iter > 400) numMut = 3;\n\n        // Sampling helpers for this iteration\n        auto samplePos = [&]() -> int {\n            if (sumPos <= 0 || posIndices.empty()) {\n                return (int)(rng() % N);\n            }\n            long long r = (long long)(rng() % sumPos);\n            int pos = int(lower_bound(posPrefix.begin(), posPrefix.end(), r + 1) - posPrefix.begin());\n            if (pos < 0) pos = 0;\n            if (pos >= (int)posIndices.size()) pos = (int)posIndices.size() - 1;\n            return posIndices[pos];\n        };\n\n        auto sampleTdist = [&]() -> int {\n            if (sumTw <= 0) return (int)(rng() % N);\n            long long r = (long long)(rng() % sumTw);\n            int pos = int(upper_bound(Tprefix.begin(), Tprefix.end(), r) - Tprefix.begin());\n            if (pos < 0) pos = 0;\n            if (pos >= N) pos = N - 1;\n            return pos;\n        };\n\n        bool usedTargeted = false;\n\n        // Decide whether to use targeted or random mutation\n        bool canTarget = (!posIndices.empty());\n        bool doTargeted = canTarget && (iter % 3 != 2); // ~2/3 of iterations use targeted\n\n        if (doTargeted) {\n            struct EdgeInfo {\n                int x;\n                int edge; // 0 or 1\n                long long score;\n            };\n            vector<EdgeInfo> edges;\n            edges.reserve(2 * N);\n\n            // Build list of \"bad\" edges: many uses into over-visited nodes\n            for (int x = 0; x < N; ++x) {\n                for (int e = 0; e < 2; ++e) {\n                    int uses = best.used[x][e];\n                    if (uses <= 0) continue;\n                    int child = (e == 0 ? best.a[x] : best.b[x]);\n                    if (deficit[child] < 0) {\n                        long long score = (long long)uses * (long long)(-deficit[child]);\n                        edges.push_back({x, e, score});\n                    }\n                }\n            }\n\n            if (!edges.empty() && sumPos > 0) {\n                sort(edges.begin(), edges.end(),\n                     [](const EdgeInfo &p, const EdgeInfo &q) {\n                         return p.score > q.score;\n                     });\n\n                int Ktop = (int)edges.size();\n                if (Ktop > 20) Ktop = 20; // focus on top edges\n\n                for (int m = 0; m < numMut && m < Ktop; ++m) {\n                    int idxEdge = m; // deterministic within top Ktop\n                    int x = edges[idxEdge].x;\n                    int e = edges[idxEdge].edge;\n\n                    int oldChild = (e == 0 ? cand.a[x] : cand.b[x]);\n                    int newChild = oldChild;\n\n                    int tries = 0;\n                    while (tries < 5) {\n                        newChild = samplePos();\n                        if (newChild != oldChild) break;\n                        ++tries;\n                    }\n                    if (newChild == oldChild) {\n                        // As a fallback, allow even if equal, but this likely won't happen often\n                        newChild = samplePos();\n                    }\n\n                    if (newChild < 0) newChild = 0;\n                    if (newChild >= N) newChild = N - 1;\n\n                    if (e == 0) cand.a[x] = newChild;\n                    else        cand.b[x] = newChild;\n                }\n                usedTargeted = true;\n            }\n        }\n\n        if (!usedTargeted) {\n            // Fallback / diversification: random node-based mutation\n            for (int k = 0; k < numMut; ++k) {\n                int idx = (int)(rng() % N);\n                mutateNode(idx, cand, N, T, deficit, posIndices, posPrefix, sumPos,\n                           Tprefix, sumTw, rng);\n            }\n        }\n\n        evalCandidate(cand, N, L, T);\n\n        if (cand.E < best.E) {\n            best = cand;\n            for (int i = 0; i < N; ++i) {\n                deficit[i] = (int)(T[i] - best.t[i]);\n            }\n            updatePosDist();\n        }\n    }\n\n    // Output best found a_i, b_i\n    for (int i = 0; i < N; ++i) {\n        int ai = best.a[i];\n        int bi = best.b[i];\n        if (ai < 0) ai = 0;\n        if (ai >= N) ai = N - 1;\n        if (bi < 0) bi = 0;\n        if (bi >= N) bi = N - 1;\n        cout << ai << ' ' << bi << '\\n';\n    }\n\n    return 0;\n}","ahc045":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int MAXN = 800;\n\nint N, M, Q, L, W;\nint G_in[400];                 // original group sizes\nint lx[MAXN], rx[MAXN], ly[MAXN], ry[MAXN];\nint cx[MAXN], cy[MAXN];        // centers\nint baseDist[MAXN][MAXN];      // squared approx distances\nuint8_t goodCnt[MAXN][MAXN];   // how many times edge appears in query-MST\nint B_bias = 0;                // bias to subtract per \"good\" edge appearance\n\n// Hilbert order of (x, y) with coordinates in [0, 2^pow_bits)\nstatic uint64_t hilbert_order(int x, int y, int pow_bits) {\n    uint64_t res = 0;\n    for (int s = pow_bits - 1; s >= 0; --s) {\n        int rx = (x >> s) & 1;\n        int ry = (y >> s) & 1;\n        res <<= 2;\n        res |= (uint64_t)((rx * 3) ^ ry);\n        if (ry == 0) {\n            if (rx == 1) {\n                x = ((1 << pow_bits) - 1) - x;\n                y = ((1 << pow_bits) - 1) - y;\n            }\n            std::swap(x, y);\n        }\n    }\n    return res;\n}\n\n// Build MST for one group using Prim with adjusted weights\nvoid buildMSTForGroup(const vector<int> &nodes,\n                      vector<pair<int,int>> &edgesOut,\n                      long long &costOut) {\n    int m = (int)nodes.size();\n    if (m <= 1) return;\n\n    const int INF = 1000000007;\n    edgesOut.clear();\n    edgesOut.reserve(max(0, m - 1));\n\n    static int best[MAXN];\n    static int parentIdx[MAXN];\n    static bool used[MAXN];\n\n    for (int i = 0; i < m; ++i) {\n        best[i] = INF;\n        parentIdx[i] = -1;\n        used[i] = false;\n    }\n\n    int root = 0;\n    used[root] = true;\n    // Initialize distances from root\n    for (int j = 1; j < m; ++j) {\n        int u = nodes[root];\n        int v = nodes[j];\n        int w = baseDist[u][v];\n        if (B_bias > 0) {\n            uint8_t cnt = goodCnt[u][v];\n            if (cnt) {\n                int cnti = (int)cnt;\n                if (cnti > 3) cnti = 3;\n                int sub = B_bias * cnti;\n                w = max(0, w - sub);\n            }\n        }\n        best[j] = w;\n        parentIdx[j] = root;\n    }\n\n    for (int it = 1; it < m; ++it) {\n        int t = -1;\n        int val = INF;\n        for (int i = 0; i < m; ++i) {\n            if (!used[i] && best[i] < val) {\n                val = best[i];\n                t = i;\n            }\n        }\n        if (t == -1) break; // should not happen\n\n        used[t] = true;\n        int u = nodes[t];\n        int pIdx = parentIdx[t];\n        if (pIdx != -1) {\n            int v = nodes[pIdx];\n            edgesOut.emplace_back(u, v);\n            costOut += val;\n        }\n\n        // Update distances using new node t\n        for (int i = 0; i < m; ++i) {\n            if (!used[i]) {\n                int uu = u;\n                int vv = nodes[i];\n                int w = baseDist[uu][vv];\n                if (B_bias > 0) {\n                    uint8_t cnt = goodCnt[uu][vv];\n                    if (cnt) {\n                        int cnti = (int)cnt;\n                        if (cnti > 3) cnti = 3;\n                        int sub = B_bias * cnti;\n                        w = max(0, w - sub);\n                    }\n                }\n                if (w < best[i]) {\n                    best[i] = w;\n                    parentIdx[i] = t;\n                }\n            }\n        }\n    }\n}\n\nstruct Solution {\n    vector<vector<int>> groups;\n    vector<vector<pair<int,int>>> edges;\n    long long cost;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    if (!(cin >> N >> M >> Q >> L >> W)) {\n        return 0;\n    }\n    for (int i = 0; i < M; ++i) cin >> G_in[i];\n    for (int i = 0; i < N; ++i) {\n        cin >> lx[i] >> rx[i] >> ly[i] >> ry[i];\n    }\n\n    // Approximate coordinates by centers\n    for (int i = 0; i < N; ++i) {\n        cx[i] = (lx[i] + rx[i]) / 2;\n        cy[i] = (ly[i] + ry[i]) / 2;\n    }\n\n    // Precompute squared distances between all pairs\n    for (int i = 0; i < N; ++i) {\n        baseDist[i][i] = 0;\n        for (int j = i + 1; j < N; ++j) {\n            long dx = (long)cx[i] - (long)cx[j];\n            long dy = (long)cy[i] - (long)cy[j];\n            long v = dx * dx + dy * dy;\n            if (v > INT_MAX) v = INT_MAX;\n            int d = (int)v;\n            baseDist[i][j] = baseDist[j][i] = d;\n        }\n    }\n\n    // Initialize goodCnt to zero\n    for (int i = 0; i < N; ++i) {\n        memset(goodCnt[i], 0, N * sizeof(uint8_t));\n    }\n\n    // Build primary Hilbert order (for queries)\n    const int HILBERT_BITS = 15; // 2^15 = 32768 > 10000\n    vector<pair<uint64_t,int>> hv(N);\n    for (int i = 0; i < N; ++i) {\n        uint64_t h = hilbert_order(cx[i], cy[i], HILBERT_BITS);\n        hv[i] = {h, i};\n    }\n    sort(hv.begin(), hv.end());\n    vector<int> hilbOrder(N);\n    for (int i = 0; i < N; ++i) hilbOrder[i] = hv[i].second;\n\n    // --------- Use queries on overlapping Hilbert windows ---------\n    vector<int> good_dists;\n    int qUsed = 0;\n\n    if (Q > 0 && L >= 2 && N > 1) {\n        if (N <= L) {\n            // One query on all cities\n            int len = N;\n            cout << \"? \" << len;\n            vector<int> subset(len);\n            for (int k = 0; k < len; ++k) {\n                subset[k] = hilbOrder[k];\n                cout << ' ' << subset[k];\n            }\n            cout << endl;\n\n            for (int t = 0; t < len - 1; ++t) {\n                int a, b;\n                cin >> a >> b;\n                if (goodCnt[a][b] < 255) {\n                    ++goodCnt[a][b];\n                    ++goodCnt[b][a];\n                    if (goodCnt[a][b] == 1) {\n                        good_dists.push_back(baseDist[a][b]);\n                    }\n                }\n            }\n            ++qUsed;\n        } else {\n            int maxQueries = Q;\n            int numerator = (N - L) + (maxQueries - 2);\n            int step = numerator / (maxQueries - 1);\n            if (step < 1) step = 1;\n\n            for (int start = 0; start < N && qUsed < Q; start += step) {\n                int len = min(L, N - start);\n                if (len < 2) break;\n                cout << \"? \" << len;\n                vector<int> subset(len);\n                for (int k = 0; k < len; ++k) {\n                    subset[k] = hilbOrder[start + k];\n                    cout << ' ' << subset[k];\n                }\n                cout << endl;\n\n                for (int t = 0; t < len - 1; ++t) {\n                    int a, b;\n                    cin >> a >> b;\n                    if (goodCnt[a][b] < 255) {\n                        ++goodCnt[a][b];\n                        ++goodCnt[b][a];\n                        if (goodCnt[a][b] == 1) {\n                            good_dists.push_back(baseDist[a][b]);\n                        }\n                    }\n                }\n                ++qUsed;\n            }\n        }\n    }\n\n    // Determine bias B_bias from collected good edge distances\n    if (!good_dists.empty()) {\n        sort(good_dists.begin(), good_dists.end());\n        int med = good_dists[good_dists.size() / 2];\n        if (med > 0) B_bias = max(1, med / 8);\n        else B_bias = 0;\n    } else {\n        B_bias = 0;\n    }\n\n    // --------- Build multiple city orders ---------\n    vector<vector<int>> cityOrders;\n\n    // 1) Hilbert original (already computed)\n    cityOrders.push_back(hilbOrder);\n\n    // 2) Hilbert with flipped X\n    {\n        vector<pair<uint64_t,int>> v(N);\n        for (int i = 0; i < N; ++i) {\n            int fx = 10000 - cx[i];\n            int fy = cy[i];\n            uint64_t h = hilbert_order(fx, fy, HILBERT_BITS);\n            v[i] = {h, i};\n        }\n        sort(v.begin(), v.end());\n        vector<int> ord(N);\n        for (int i = 0; i < N; ++i) ord[i] = v[i].second;\n        cityOrders.push_back(std::move(ord));\n    }\n\n    // 3) Hilbert with flipped Y\n    {\n        vector<pair<uint64_t,int>> v(N);\n        for (int i = 0; i < N; ++i) {\n            int fx = cx[i];\n            int fy = 10000 - cy[i];\n            uint64_t h = hilbert_order(fx, fy, HILBERT_BITS);\n            v[i] = {h, i};\n        }\n        sort(v.begin(), v.end());\n        vector<int> ord(N);\n        for (int i = 0; i < N; ++i) ord[i] = v[i].second;\n        cityOrders.push_back(std::move(ord));\n    }\n\n    // 4) Lexicographic by (x, y)\n    {\n        vector<pair<pair<int,int>,int>> v(N);\n        for (int i = 0; i < N; ++i) {\n            v[i] = {{cx[i], cy[i]}, i};\n        }\n        sort(v.begin(), v.end());\n        vector<int> ord(N);\n        for (int i = 0; i < N; ++i) ord[i] = v[i].second;\n        cityOrders.push_back(std::move(ord));\n    }\n\n    // 5) Lexicographic by (y, x)\n    {\n        vector<pair<pair<int,int>,int>> v(N);\n        for (int i = 0; i < N; ++i) {\n            v[i] = {{cy[i], cx[i]}, i};\n        }\n        sort(v.begin(), v.end());\n        vector<int> ord(N);\n        for (int i = 0; i < N; ++i) ord[i] = v[i].second;\n        cityOrders.push_back(std::move(ord));\n    }\n\n    // --------- Precompute size orders ---------\n    vector<pair<int,int>> sizeDesc, sizeAsc, sizeOrig;\n    sizeDesc.reserve(M);\n    sizeAsc.reserve(M);\n    sizeOrig.reserve(M);\n    for (int i = 0; i < M; ++i) {\n        sizeDesc.emplace_back(G_in[i], i);\n        sizeAsc.emplace_back(G_in[i], i);\n        sizeOrig.emplace_back(G_in[i], i);\n    }\n    sort(sizeDesc.begin(), sizeDesc.end(),\n         [](const auto &a, const auto &b) {\n             if (a.first != b.first) return a.first > b.first; // larger first\n             return a.second < b.second;\n         });\n    sort(sizeAsc.begin(), sizeAsc.end(),\n         [](const auto &a, const auto &b) {\n             if (a.first != b.first) return a.first < b.first; // smaller first\n             return a.second < b.second;\n         });\n    // sizeOrig kept in original order\n\n    vector<vector<pair<int,int>>> sizeOrders = {sizeDesc, sizeAsc, sizeOrig};\n\n    // --------- Build candidate solutions ---------\n    vector<Solution> candidates;\n    candidates.reserve(cityOrders.size() * sizeOrders.size());\n\n    auto build_solution = [&](const vector<int> &cityOrder,\n                              const vector<pair<int,int>> &sizeOrder) {\n        Solution sol;\n        sol.groups.assign(M, {});\n        int ptr = 0;\n        for (auto &p : sizeOrder) {\n            int sz = p.first;\n            int gid = p.second;\n            sol.groups[gid].reserve(sz);\n            for (int k = 0; k < sz; ++k) {\n                sol.groups[gid].push_back(cityOrder[ptr++]);\n            }\n        }\n        sol.edges.assign(M, {});\n        sol.cost = 0;\n        for (int g = 0; g < M; ++g) {\n            buildMSTForGroup(sol.groups[g], sol.edges[g], sol.cost);\n        }\n        candidates.push_back(std::move(sol));\n    };\n\n    for (const auto &ord : cityOrders) {\n        for (const auto &szOrd : sizeOrders) {\n            build_solution(ord, szOrd);\n        }\n    }\n\n    // --------- Choose best candidate ---------\n    int bestIdx = 0;\n    long long bestCost = candidates[0].cost;\n    for (int i = 1; i < (int)candidates.size(); ++i) {\n        if (candidates[i].cost < bestCost) {\n            bestCost = candidates[i].cost;\n            bestIdx = i;\n        }\n    }\n    Solution &bestSol = candidates[bestIdx];\n\n    // --------- Output final answer ---------\n    cout << \"!\\n\";\n    for (int g = 0; g < M; ++g) {\n        const auto &nodes = bestSol.groups[g];\n        int sz = (int)nodes.size();\n        for (int i = 0; i < sz; ++i) {\n            if (i) cout << ' ';\n            cout << nodes[i];\n        }\n        cout << '\\n';\n        const auto &edges = bestSol.edges[g];\n        for (auto &e : edges) {\n            cout << e.first << ' ' << e.second << '\\n';\n        }\n    }\n\n    return 0;\n}","ahc046":"#include <bits/stdc++.h>\nusing namespace std;\n\n// Directions: Up, Down, Left, Right\nconst int DX[4] = {-1, 1, 0, 0};\nconst int DY[4] = {0, 0, -1, 1};\nconst char DCH[4] = {'U', 'D', 'L', 'R'};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M;\n    if (!(cin >> N >> M)) return 0;\n\n    vector<pair<int,int>> points(M);\n    for (int k = 0; k < M; ++k) {\n        cin >> points[k].first >> points[k].second;\n    }\n\n    vector<char> actions; actions.reserve(2 * N * M);\n    vector<char> dirs;    dirs.reserve(2 * N * M);\n\n    int totalCells = N * N;\n\n    // BFS for each segment from points[k-1] to points[k]\n    for (int k = 1; k < M; ++k) {\n        int sx = points[k-1].first;\n        int sy = points[k-1].second;\n        int gx = points[k].first;\n        int gy = points[k].second;\n\n        int sidx = sx * N + sy;\n        int gidx = gx * N + gy;\n\n        // BFS arrays\n        static int dist[400];\n        static int prev_idx[400];\n        static char prev_action[400];\n        static char prev_dir[400];\n\n        const int INF = 1e9;\n        for (int i = 0; i < totalCells; ++i) {\n            dist[i] = INF;\n        }\n\n        queue<int> q;\n        dist[sidx] = 0;\n        prev_idx[sidx] = -1;\n        q.push(sidx);\n\n        while (!q.empty()) {\n            int v = q.front(); q.pop();\n            if (v == gidx) break;\n\n            int x = v / N;\n            int y = v % N;\n\n            for (int d = 0; d < 4; ++d) {\n                // Move\n                {\n                    int nx = x + DX[d];\n                    int ny = y + DY[d];\n                    if (0 <= nx && nx < N && 0 <= ny && ny < N) {\n                        int to = nx * N + ny;\n                        if (dist[to] == INF) {\n                            dist[to] = dist[v] + 1;\n                            prev_idx[to] = v;\n                            prev_action[to] = 'M';\n                            prev_dir[to] = DCH[d];\n                            q.push(to);\n                        }\n                    }\n                }\n                // Slide to border (no internal blocks)\n                {\n                    int nx = x, ny = y;\n                    if (d == 0) nx = 0;          // Up\n                    else if (d == 1) nx = N - 1; // Down\n                    else if (d == 2) ny = 0;     // Left\n                    else if (d == 3) ny = N - 1; // Right\n\n                    int to = nx * N + ny;\n                    if (to != v && dist[to] == INF) {\n                        dist[to] = dist[v] + 1;\n                        prev_idx[to] = v;\n                        prev_action[to] = 'S';\n                        prev_dir[to] = DCH[d];\n                        q.push(to);\n                    }\n                }\n            }\n        }\n\n        // Reconstruct path from gidx back to sidx\n        vector<char> seg_actions;\n        vector<char> seg_dirs;\n        int cur = gidx;\n        while (cur != sidx) {\n            seg_actions.push_back(prev_action[cur]);\n            seg_dirs.push_back(prev_dir[cur]);\n            cur = prev_idx[cur];\n        }\n        // Reverse to get correct order\n        for (int i = (int)seg_actions.size() - 1; i >= 0; --i) {\n            actions.push_back(seg_actions[i]);\n            dirs.push_back(seg_dirs[i]);\n        }\n    }\n\n    // Output\n    int T = (int)actions.size();\n    // We are guaranteed T <= 2*N*M from argument (<=1482 when no blocks)\n    for (int t = 0; t < T; ++t) {\n        cout << actions[t] << ' ' << dirs[t] << '\\n';\n    }\n\n    return 0;\n}"},"8":{"ahc001":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Rect {\n    int a, b, c, d; // [a,c) x [b,d)\n};\n\nint n;\nvector<int> xs, ys;\nvector<long long> rs;\n\n// Satisfaction for s <= r\ninline double satisfaction(long long s, long long r) {\n    if (s <= 0) return 0.0;\n    double q = (double)s / (double)r; // q in (0,1]\n    double t = 1.0 - q;\n    return 1.0 - t * t; // = 2q - q^2\n}\n\n// Positive-area overlap?\ninline bool overlap(const Rect &x, const Rect &y) {\n    return (x.a < y.c && y.a < x.c && x.b < y.d && y.b < x.d);\n}\n\n// Greedy growth for a given order. Fills rect and area, returns total score.\ndouble run_order(const vector<int> &order, vector<Rect> &rect, vector<long long> &area) {\n    rect.assign(n, Rect());\n    area.assign(n, 1);\n\n    // Initialize as 1x1 cells at seeds\n    for (int i = 0; i < n; ++i) {\n        rect[i].a = xs[i];\n        rect[i].c = xs[i] + 1;\n        rect[i].b = ys[i];\n        rect[i].d = ys[i] + 1;\n        area[i] = 1;\n    }\n\n    for (int pos = 0; pos < n; ++pos) {\n        int i = order[pos];\n        long long target = rs[i];\n        if (target <= 1) continue;\n\n        while (area[i] < target) {\n            Rect &cur = rect[i];\n            int w = cur.c - cur.a;\n            int h = cur.d - cur.b;\n            if (w <= 0 || h <= 0) break;\n            long long remaining = target - area[i];\n\n            int bestDir = -1;\n            int bestL = 0;\n            long long bestDelta = 0;\n\n            // 0: up (increase d)\n            if (cur.d < 10000 && remaining >= w) {\n                long long L_area = remaining / w;\n                if (L_area > 0) {\n                    int limit = 10000 - cur.d;\n                    if (limit > 0) {\n                        for (int j = 0; j < n; ++j) {\n                            if (j == i) continue;\n                            const Rect &s = rect[j];\n                            // x-overlap?\n                            if (s.a >= cur.c || s.c <= cur.a) continue;\n                            if (cur.d >= s.d) continue; // s below or touching\n                            if (s.b <= cur.d) {\n                                // s.b <= d < s.d, any extension hits s\n                                limit = 0;\n                                break;\n                            } else {\n                                int cand = s.b - cur.d;\n                                if (cand < limit) {\n                                    limit = cand;\n                                    if (limit <= 0) {\n                                        limit = 0;\n                                        break;\n                                    }\n                                }\n                            }\n                        }\n                        if (limit > 0) {\n                            int L = (int)min<long long>(limit, L_area);\n                            if (L > 0) {\n                                long long delta = 1LL * L * w;\n                                if (delta > bestDelta) {\n                                    bestDelta = delta;\n                                    bestDir = 0;\n                                    bestL = L;\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n\n            // 1: down (decrease b)\n            if (cur.b > 0 && remaining >= w) {\n                long long L_area = remaining / w;\n                if (L_area > 0) {\n                    int limit = cur.b;\n                    if (limit > 0) {\n                        for (int j = 0; j < n; ++j) {\n                            if (j == i) continue;\n                            const Rect &s = rect[j];\n                            // x-overlap?\n                            if (s.a >= cur.c || s.c <= cur.a) continue;\n                            if (s.b >= cur.b) continue; // s above or touching\n                            if (s.d > cur.b) {\n                                // s.b < b < s.d\n                                limit = 0;\n                                break;\n                            } else {\n                                int cand = cur.b - s.d;\n                                if (cand < limit) {\n                                    limit = cand;\n                                    if (limit <= 0) {\n                                        limit = 0;\n                                        break;\n                                    }\n                                }\n                            }\n                        }\n                        if (limit > 0) {\n                            int L = (int)min<long long>(limit, L_area);\n                            if (L > 0) {\n                                long long delta = 1LL * L * w;\n                                if (delta > bestDelta) {\n                                    bestDelta = delta;\n                                    bestDir = 1;\n                                    bestL = L;\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n\n            // 2: left (decrease a)\n            if (cur.a > 0 && remaining >= h) {\n                long long L_area = remaining / h;\n                if (L_area > 0) {\n                    int limit = cur.a;\n                    if (limit > 0) {\n                        for (int j = 0; j < n; ++j) {\n                            if (j == i) continue;\n                            const Rect &s = rect[j];\n                            // y-overlap?\n                            if (s.d <= cur.b || cur.d <= s.b) continue;\n                            if (s.a >= cur.a) {\n                                // s to the right or touching\n                                continue;\n                            } else {\n                                if (s.c > cur.a) {\n                                    // s crosses x = cur.a\n                                    limit = 0;\n                                    break;\n                                } else {\n                                    int cand = cur.a - s.c;\n                                    if (cand < limit) {\n                                        limit = cand;\n                                        if (limit <= 0) {\n                                            limit = 0;\n                                            break;\n                                        }\n                                    }\n                                }\n                            }\n                        }\n                        if (limit > 0) {\n                            int L = (int)min<long long>(limit, L_area);\n                            if (L > 0) {\n                                long long delta = 1LL * L * h;\n                                if (delta > bestDelta) {\n                                    bestDelta = delta;\n                                    bestDir = 2;\n                                    bestL = L;\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n\n            // 3: right (increase c)\n            if (cur.c < 10000 && remaining >= h) {\n                long long L_area = remaining / h;\n                if (L_area > 0) {\n                    int limit = 10000 - cur.c;\n                    if (limit > 0) {\n                        for (int j = 0; j < n; ++j) {\n                            if (j == i) continue;\n                            const Rect &s = rect[j];\n                            // y-overlap?\n                            if (s.d <= cur.b || cur.d <= s.b) continue;\n                            if (cur.c >= s.c) {\n                                // s to the left or touching\n                                continue;\n                            } else {\n                                if (s.a <= cur.c) {\n                                    // s crosses x = cur.c\n                                    limit = 0;\n                                    break;\n                                } else {\n                                    int cand = s.a - cur.c;\n                                    if (cand < limit) {\n                                        limit = cand;\n                                        if (limit <= 0) {\n                                            limit = 0;\n                                            break;\n                                        }\n                                    }\n                                }\n                            }\n                        }\n                        if (limit > 0) {\n                            int L = (int)min<long long>(limit, L_area);\n                            if (L > 0) {\n                                long long delta = 1LL * L * h;\n                                if (delta > bestDelta) {\n                                    bestDelta = delta;\n                                    bestDir = 3;\n                                    bestL = L;\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n\n            if (bestDir == -1 || bestL <= 0 || bestDelta <= 0) break;\n\n            switch (bestDir) {\n                case 0: cur.d += bestL; break;\n                case 1: cur.b -= bestL; break;\n                case 2: cur.a -= bestL; break;\n                case 3: cur.c += bestL; break;\n            }\n            area[i] += bestDelta;\n        }\n    }\n\n    double score = 0.0;\n    for (int i = 0; i < n; ++i) {\n        score += satisfaction(area[i], rs[i]);\n    }\n    return score;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> n;\n    xs.resize(n);\n    ys.resize(n);\n    rs.resize(n);\n    for (int i = 0; i < n; ++i) {\n        cin >> xs[i] >> ys[i] >> rs[i];\n    }\n\n    // Time management\n    const double ORDER_PHASE_END = 2.0; // seconds\n    const double SA_PHASE_END    = 4.6; // seconds\n\n    auto time_start = chrono::steady_clock::now();\n    auto elapsed = [&]() -> double {\n        return chrono::duration<double>(chrono::steady_clock::now() - time_start).count();\n    };\n\n    // RNG: deterministic based on input (stability)\n    uint64_t seed = 88172645463325252ULL;\n    seed ^= (uint64_t)n * 1000003ULL;\n    for (int i = 0; i < n; ++i) {\n        uint64_t v = ((uint64_t)xs[i] << 17) ^ ((uint64_t)ys[i] << 3) ^ (uint64_t)rs[i];\n        seed ^= std::rotl(v, i % 47);\n        seed *= 1000003ULL;\n        seed += 1234567ULL;\n    }\n    std::mt19937_64 rng(seed);\n\n    vector<int> base(n);\n    iota(base.begin(), base.end(), 0);\n\n    vector<Rect> rect, bestRect;\n    vector<long long> area, bestArea;\n    double bestScore = -1.0;\n\n    auto try_order = [&](const vector<int> &order) {\n        double sc = run_order(order, rect, area);\n        if (sc > bestScore) {\n            bestScore = sc;\n            bestRect = rect;\n            bestArea = area;\n        }\n    };\n\n    // Deterministic orders\n\n    // 1) increasing r\n    {\n        vector<int> ord = base;\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            if (rs[a] != rs[b]) return rs[a] < rs[b];\n            return a < b;\n        });\n        try_order(ord);\n    }\n    // 2) decreasing r\n    {\n        vector<int> ord = base;\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            if (rs[a] != rs[b]) return rs[a] > rs[b];\n            return a < b;\n        });\n        try_order(ord);\n    }\n    // 3) increasing x\n    {\n        vector<int> ord = base;\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            if (xs[a] != xs[b]) return xs[a] < xs[b];\n            return a < b;\n        });\n        try_order(ord);\n    }\n    // 4) increasing y\n    {\n        vector<int> ord = base;\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            if (ys[a] != ys[b]) return ys[a] < ys[b];\n            return a < b;\n        });\n        try_order(ord);\n    }\n\n    // Random permutations until ORDER_PHASE_END\n    {\n        vector<int> ord = base;\n        while (elapsed() < ORDER_PHASE_END) {\n            shuffle(ord.begin(), ord.end(), rng);\n            try_order(ord);\n        }\n    }\n\n    // Local search (simulated annealing) starting from bestRect\n    vector<Rect> curRect = bestRect;\n    vector<long long> curArea = bestArea;\n    vector<double> curP(n);\n    double curScore = 0.0;\n    for (int i = 0; i < n; ++i) {\n        curP[i] = satisfaction(curArea[i], rs[i]);\n        curScore += curP[i];\n    }\n    bestScore = curScore;\n    bestRect = curRect;\n    bestArea = curArea;\n\n    double sa_start_time = elapsed();\n    double sa_total = SA_PHASE_END - sa_start_time;\n    if (sa_total > 0.0) {\n        uniform_int_distribution<int> distRect(0, n - 1);\n        uniform_real_distribution<double> dist01(0.0, 1.0);\n\n        const double T0 = 1e-3;\n        const double T1 = 1e-5;\n        const double P_PAIR = 0.25;\n\n        while (true) {\n            double tnow = elapsed();\n            if (tnow >= SA_PHASE_END) break;\n            double sa_elapsed = tnow - sa_start_time;\n            double progress = sa_elapsed / sa_total;\n            if (progress > 1.0) progress = 1.0;\n            double T = T0 + (T1 - T0) * progress; // linear cooling\n\n            bool moved = false;\n\n            // Try pair move with some probability\n            double choosePair = dist01(rng);\n            if (choosePair < P_PAIR) {\n                for (int attempt = 0; attempt < 2 && !moved; ++attempt) {\n                    int i = distRect(rng);\n                    int dir = (int)(rng() % 4); // 0:left,1:right,2:down,3:up\n                    const Rect &ri = curRect[i];\n                    int j = -1;\n\n                    // find full-side neighbor j\n                    for (int k = 0; k < n; ++k) if (k != i) {\n                        const Rect &rj = curRect[k];\n                        if (dir == 0) { // left\n                            if (rj.c == ri.a && rj.b == ri.b && rj.d == ri.d) { j = k; break; }\n                        } else if (dir == 1) { // right\n                            if (rj.a == ri.c && rj.b == ri.b && rj.d == ri.d) { j = k; break; }\n                        } else if (dir == 2) { // down\n                            if (rj.d == ri.b && rj.a == ri.a && rj.c == ri.c) { j = k; break; }\n                        } else { // up\n                            if (rj.b == ri.d && rj.a == ri.a && rj.c == ri.c) { j = k; break; }\n                        }\n                    }\n\n                    if (j == -1) continue;\n\n                    Rect riOld = ri;\n                    Rect rjOld = curRect[j];\n                    long long Ai = curArea[i];\n                    long long Aj = curArea[j];\n                    double Pi = curP[i];\n                    double Pj = curP[j];\n\n                    Rect ri1 = riOld, rj1 = rjOld, ri2 = riOld, rj2 = rjOld;\n                    long long Ai1 = Ai, Aj1 = Aj, Ai2 = Ai, Aj2 = Aj;\n                    double newPi1 = Pi, newPj1 = Pj, newPi2 = Pi, newPj2 = Pj;\n                    double bestDelta = -1e100;\n                    int bestCase = -1;\n\n                    // stripe area (amount of area transferred by 1-unit border move)\n                    long long stripe = 0;\n                    if (dir == 0 || dir == 1) {\n                        stripe = (long long)(riOld.d - riOld.b); // vertical adjacency\n                    } else {\n                        stripe = (long long)(riOld.c - riOld.a); // horizontal adjacency\n                    }\n                    if (stripe <= 0) continue;\n\n                    // Case A: shrink j, expand i\n                    {\n                        bool ok = true;\n                        Rect riA = riOld, rjA = rjOld;\n                        long long AiA = Ai, AjA = Aj;\n\n                        if (dir == 0) { // j left, shrink j right, expand i left\n                            int wj = rjOld.c - rjOld.a;\n                            if (wj <= 1) ok = false;\n                            if (ok && xs[j] == rjOld.c - 1) ok = false; // seed at shrinking side\n                            if (ok && Ai + stripe > rs[i]) ok = false;\n                            if (ok) {\n                                riA.a = riOld.a - 1;\n                                rjA.c = rjOld.c - 1;\n                                AiA = Ai + stripe;\n                                AjA = Aj - stripe;\n                            }\n                        } else if (dir == 1) { // j right, shrink j left, expand i right\n                            int wj = rjOld.c - rjOld.a;\n                            if (wj <= 1) ok = false;\n                            if (ok && xs[j] == rjOld.a) ok = false;\n                            if (ok && Ai + stripe > rs[i]) ok = false;\n                            if (ok) {\n                                rjA.a = rjOld.a + 1;\n                                riA.c = riOld.c + 1;\n                                AiA = Ai + stripe;\n                                AjA = Aj - stripe;\n                            }\n                        } else if (dir == 2) { // j below, shrink j top, expand i down\n                            int hj = rjOld.d - rjOld.b;\n                            if (hj <= 1) ok = false;\n                            if (ok && ys[j] == rjOld.d - 1) ok = false;\n                            if (ok && Ai + stripe > rs[i]) ok = false;\n                            if (ok) {\n                                rjA.d = rjOld.d - 1;\n                                riA.b = riOld.b - 1;\n                                AiA = Ai + stripe;\n                                AjA = Aj - stripe;\n                            }\n                        } else { // dir == 3, j above, shrink j bottom, expand i up\n                            int hj = rjOld.d - rjOld.b;\n                            if (hj <= 1) ok = false;\n                            if (ok && ys[j] == rjOld.b) ok = false;\n                            if (ok && Ai + stripe > rs[i]) ok = false;\n                            if (ok) {\n                                rjA.b = rjOld.b + 1;\n                                riA.d = riOld.d + 1;\n                                AiA = Ai + stripe;\n                                AjA = Aj - stripe;\n                            }\n                        }\n\n                        if (ok && AiA > 0 && AjA > 0) {\n                            double PiA = satisfaction(AiA, rs[i]);\n                            double PjA = satisfaction(AjA, rs[j]);\n                            double delta = (PiA - Pi) + (PjA - Pj);\n                            if (delta > bestDelta) {\n                                bestDelta = delta;\n                                bestCase = 0;\n                                ri1 = riA;\n                                rj1 = rjA;\n                                Ai1 = AiA;\n                                Aj1 = AjA;\n                                newPi1 = PiA;\n                                newPj1 = PjA;\n                            }\n                        }\n                    }\n\n                    // Case B: shrink i, expand j\n                    {\n                        bool ok = true;\n                        Rect riB = riOld, rjB = rjOld;\n                        long long AiB = Ai, AjB = Aj;\n\n                        if (dir == 0) { // j left, shrink i left, expand j right\n                            int wi = riOld.c - riOld.a;\n                            if (wi <= 1) ok = false;\n                            if (ok && xs[i] == riOld.a) ok = false;\n                            if (ok && Aj + stripe > rs[j]) ok = false;\n                            if (ok) {\n                                riB.a = riOld.a + 1;\n                                rjB.c = rjOld.c + 1;\n                                AiB = Ai - stripe;\n                                AjB = Aj + stripe;\n                            }\n                        } else if (dir == 1) { // j right, shrink i right, expand j left\n                            int wi = riOld.c - riOld.a;\n                            if (wi <= 1) ok = false;\n                            if (ok && xs[i] == riOld.c - 1) ok = false;\n                            if (ok && Aj + stripe > rs[j]) ok = false;\n                            if (ok) {\n                                riB.c = riOld.c - 1;\n                                rjB.a = rjOld.a - 1;\n                                AiB = Ai - stripe;\n                                AjB = Aj + stripe;\n                            }\n                        } else if (dir == 2) { // j below, shrink i down, expand j up\n                            int hi = riOld.d - riOld.b;\n                            if (hi <= 1) ok = false;\n                            if (ok && ys[i] == riOld.b) ok = false;\n                            if (ok && Aj + stripe > rs[j]) ok = false;\n                            if (ok) {\n                                riB.b = riOld.b + 1;\n                                rjB.d = rjOld.d + 1;\n                                AiB = Ai - stripe;\n                                AjB = Aj + stripe;\n                            }\n                        } else { // dir == 3, j above, shrink i up, expand j down\n                            int hi = riOld.d - riOld.b;\n                            if (hi <= 1) ok = false;\n                            if (ok && ys[i] == riOld.d - 1) ok = false;\n                            if (ok && Aj + stripe > rs[j]) ok = false;\n                            if (ok) {\n                                riB.d = riOld.d - 1;\n                                rjB.b = rjOld.b - 1;\n                                AiB = Ai - stripe;\n                                AjB = Aj + stripe;\n                            }\n                        }\n\n                        if (ok && AiB > 0 && AjB > 0) {\n                            double PiB = satisfaction(AiB, rs[i]);\n                            double PjB = satisfaction(AjB, rs[j]);\n                            double delta = (PiB - Pi) + (PjB - Pj);\n                            if (delta > bestDelta) {\n                                bestDelta = delta;\n                                bestCase = 1;\n                                ri2 = riB;\n                                rj2 = rjB;\n                                Ai2 = AiB;\n                                Aj2 = AjB;\n                                newPi2 = PiB;\n                                newPj2 = PjB;\n                            }\n                        }\n                    }\n\n                    const double EPS = 1e-12;\n                    if (bestCase != -1 && bestDelta > EPS) {\n                        if (bestCase == 0) {\n                            curRect[i] = ri1;\n                            curRect[j] = rj1;\n                            curArea[i] = Ai1;\n                            curArea[j] = Aj1;\n                            curP[i] = newPi1;\n                            curP[j] = newPj1;\n                        } else {\n                            curRect[i] = ri2;\n                            curRect[j] = rj2;\n                            curArea[i] = Ai2;\n                            curArea[j] = Aj2;\n                            curP[i] = newPi2;\n                            curP[j] = newPj2;\n                        }\n                        curScore += bestDelta;\n                        if (curScore > bestScore) {\n                            bestScore = curScore;\n                            bestRect = curRect;\n                            bestArea = curArea;\n                        }\n                        moved = true;\n                    }\n                }\n            }\n\n            if (moved) continue;\n\n            // Single-rectangle SA move\n\n            // Choose a rectangle, biasing toward under-satisfied ones\n            int i = distRect(rng);\n            for (int tries = 0; tries < 4; ++tries) {\n                double fill0 = (double)curArea[i] / (double)rs[i];\n                if (fill0 < 0.99) break;\n                i = distRect(rng);\n            }\n\n            Rect old = curRect[i];\n            long long oldArea = curArea[i];\n            double oldPi = curP[i];\n\n            int w = old.c - old.a;\n            int h = old.d - old.b;\n            if (w <= 0 || h <= 0) continue;\n\n            double fill = (double)oldArea / (double)rs[i];\n\n            // Decide operation type (0..3 expand, 4..7 shrink, 8..11 shift)\n            int op;\n            if (fill < 0.98) {\n                // mostly expand and shift\n                uint64_t r = rng() % 10;\n                if (r < 6) {        // 60% expand\n                    op = (int)(rng() % 4); // 0..3\n                } else if (r < 9) { // 30% shift\n                    op = 8 + (int)(rng() % 4); // 8..11\n                } else {            // 10% shrink\n                    op = 4 + (int)(rng() % 4); // 4..7\n                }\n            } else {\n                // mostly shrink and shift\n                uint64_t r = rng() % 10;\n                if (r < 5) { // 50% shrink\n                    op = 4 + (int)(rng() % 4);\n                } else if (r < 8) { // 30% shift\n                    op = 8 + (int)(rng() % 4);\n                } else { // 20% expand\n                    op = (int)(rng() % 4);\n                }\n            }\n\n            Rect cand = old;\n            long long newArea = oldArea;\n            bool ok = true;\n            bool changed = false;\n\n            switch (op) {\n                case 0: { // expand left (a--)\n                    if (old.a == 0) { ok = false; break; }\n                    if (oldArea + h > rs[i]) { ok = false; break; }\n                    cand.a = old.a - 1;\n                    newArea = oldArea + h;\n                    // overlap check\n                    for (int j = 0; j < n; ++j) {\n                        if (j == i) continue;\n                        if (overlap(cand, curRect[j])) { ok = false; break; }\n                    }\n                    if (!ok) break;\n                    changed = true;\n                    break;\n                }\n                case 1: { // expand right (c++)\n                    if (old.c == 10000) { ok = false; break; }\n                    if (oldArea + h > rs[i]) { ok = false; break; }\n                    cand.c = old.c + 1;\n                    newArea = oldArea + h;\n                    for (int j = 0; j < n; ++j) {\n                        if (j == i) continue;\n                        if (overlap(cand, curRect[j])) { ok = false; break; }\n                    }\n                    if (!ok) break;\n                    changed = true;\n                    break;\n                }\n                case 2: { // expand down (b--)\n                    if (old.b == 0) { ok = false; break; }\n                    if (oldArea + w > rs[i]) { ok = false; break; }\n                    cand.b = old.b - 1;\n                    newArea = oldArea + w;\n                    for (int j = 0; j < n; ++j) {\n                        if (j == i) continue;\n                        if (overlap(cand, curRect[j])) { ok = false; break; }\n                    }\n                    if (!ok) break;\n                    changed = true;\n                    break;\n                }\n                case 3: { // expand up (d++)\n                    if (old.d == 10000) { ok = false; break; }\n                    if (oldArea + w > rs[i]) { ok = false; break; }\n                    cand.d = old.d + 1;\n                    newArea = oldArea + w;\n                    for (int j = 0; j < n; ++j) {\n                        if (j == i) continue;\n                        if (overlap(cand, curRect[j])) { ok = false; break; }\n                    }\n                    if (!ok) break;\n                    changed = true;\n                    break;\n                }\n                case 4: { // shrink left (a++)\n                    if (w <= 1) { ok = false; break; }\n                    // seed must stay inside: xs[i] != old.a\n                    if (xs[i] == old.a) { ok = false; break; }\n                    cand.a = old.a + 1;\n                    newArea = oldArea - h;\n                    changed = true;\n                    break;\n                }\n                case 5: { // shrink right (c--)\n                    if (w <= 1) { ok = false; break; }\n                    if (xs[i] == old.c - 1) { ok = false; break; }\n                    cand.c = old.c - 1;\n                    newArea = oldArea - h;\n                    changed = true;\n                    break;\n                }\n                case 6: { // shrink down (b++)\n                    if (h <= 1) { ok = false; break; }\n                    if (ys[i] == old.b) { ok = false; break; }\n                    cand.b = old.b + 1;\n                    newArea = oldArea - w;\n                    changed = true;\n                    break;\n                }\n                case 7: { // shrink up (d--)\n                    if (h <= 1) { ok = false; break; }\n                    if (ys[i] == old.d - 1) { ok = false; break; }\n                    cand.d = old.d - 1;\n                    newArea = oldArea - w;\n                    changed = true;\n                    break;\n                }\n                case 8: { // shift left (a--, c--)\n                    if (old.a == 0) { ok = false; break; }\n                    // seed must stay inside after shift\n                    if (xs[i] == old.c - 1) { ok = false; break; }\n                    cand.a = old.a - 1;\n                    cand.c = old.c - 1;\n                    // area unchanged\n                    for (int j = 0; j < n; ++j) {\n                        if (j == i) continue;\n                        if (overlap(cand, curRect[j])) { ok = false; break; }\n                    }\n                    if (!ok) break;\n                    changed = true;\n                    break;\n                }\n                case 9: { // shift right (a++, c++)\n                    if (old.c == 10000) { ok = false; break; }\n                    if (xs[i] == old.a) { ok = false; break; }\n                    cand.a = old.a + 1;\n                    cand.c = old.c + 1;\n                    for (int j = 0; j < n; ++j) {\n                        if (j == i) continue;\n                        if (overlap(cand, curRect[j])) { ok = false; break; }\n                    }\n                    if (!ok) break;\n                    changed = true;\n                    break;\n                }\n                case 10: { // shift down (b--, d--)\n                    if (old.b == 0) { ok = false; break; }\n                    if (ys[i] == old.d - 1) { ok = false; break; }\n                    cand.b = old.b - 1;\n                    cand.d = old.d - 1;\n                    for (int j = 0; j < n; ++j) {\n                        if (j == i) continue;\n                        if (overlap(cand, curRect[j])) { ok = false; break; }\n                    }\n                    if (!ok) break;\n                    changed = true;\n                    break;\n                }\n                case 11: { // shift up (b++, d++)\n                    if (old.d == 10000) { ok = false; break; }\n                    if (ys[i] == old.b) { ok = false; break; }\n                    cand.b = old.b + 1;\n                    cand.d = old.d + 1;\n                    for (int j = 0; j < n; ++j) {\n                        if (j == i) continue;\n                        if (overlap(cand, curRect[j])) { ok = false; break; }\n                    }\n                    if (!ok) break;\n                    changed = true;\n                    break;\n                }\n            }\n\n            if (!ok || !changed) continue;\n            if (!(cand.a < cand.c && cand.b < cand.d)) continue;\n\n            double newPi = satisfaction(newArea, rs[i]);\n            double delta = newPi - oldPi;\n            double newScore = curScore + delta;\n\n            if (delta >= 0.0) {\n                // Always accept non-worse moves\n                curRect[i] = cand;\n                curArea[i] = newArea;\n                curP[i] = newPi;\n                curScore = newScore;\n                if (curScore > bestScore) {\n                    bestScore = curScore;\n                    bestRect = curRect;\n                    bestArea = curArea;\n                }\n            } else {\n                double prob = exp(delta / T);\n                double r = dist01(rng);\n                if (r < prob) {\n                    // Accept worse move\n                    curRect[i] = cand;\n                    curArea[i] = newArea;\n                    curP[i] = newPi;\n                    curScore = newScore;\n                    if (curScore > bestScore) {\n                        bestScore = curScore;\n                        bestRect = curRect;\n                        bestArea = curArea;\n                    }\n                }\n                // else reject\n            }\n        }\n    }\n\n    // Final greedy fill on the best layout to exploit freed spaces\n    auto greedy_finalize = [&](vector<Rect> &rectRef, vector<long long> &areaRef) {\n        vector<int> ord(n);\n        iota(ord.begin(), ord.end(), 0);\n        // Process companies with larger shortage first\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            long long da = rs[a] - areaRef[a];\n            long long db = rs[b] - areaRef[b];\n            if (da != db) return da > db;\n            return a < b;\n        });\n\n        for (int idx = 0; idx < n; ++idx) {\n            if (elapsed() > 4.9) break; // safety margin\n            int i = ord[idx];\n            long long target = rs[i];\n            if (areaRef[i] >= target) continue;\n\n            while (areaRef[i] < target) {\n                if (elapsed() > 4.9) break;\n                Rect &cur = rectRef[i];\n                int w = cur.c - cur.a;\n                int h = cur.d - cur.b;\n                if (w <= 0 || h <= 0) break;\n                long long remaining = target - areaRef[i];\n\n                int bestDir = -1;\n                int bestL = 0;\n                long long bestDelta = 0;\n\n                // 0: up (increase d)\n                if (cur.d < 10000 && remaining >= w) {\n                    long long L_area = remaining / w;\n                    if (L_area > 0) {\n                        int limit = 10000 - cur.d;\n                        if (limit > 0) {\n                            for (int j = 0; j < n; ++j) {\n                                if (j == i) continue;\n                                const Rect &s = rectRef[j];\n                                // x-overlap?\n                                if (s.a >= cur.c || s.c <= cur.a) continue;\n                                if (cur.d >= s.d) continue; // s below or touching\n                                if (s.b <= cur.d) {\n                                    // s.b <= d < s.d, any extension hits s\n                                    limit = 0;\n                                    break;\n                                } else {\n                                    int cand = s.b - cur.d;\n                                    if (cand < limit) {\n                                        limit = cand;\n                                        if (limit <= 0) {\n                                            limit = 0;\n                                            break;\n                                        }\n                                    }\n                                }\n                            }\n                            if (limit > 0) {\n                                int L = (int)min<long long>(limit, L_area);\n                                if (L > 0) {\n                                    long long delta = 1LL * L * w;\n                                    if (delta > bestDelta) {\n                                        bestDelta = delta;\n                                        bestDir = 0;\n                                        bestL = L;\n                                    }\n                                }\n                            }\n                        }\n                    }\n                }\n\n                // 1: down (decrease b)\n                if (cur.b > 0 && remaining >= w) {\n                    long long L_area = remaining / w;\n                    if (L_area > 0) {\n                        int limit = cur.b;\n                        if (limit > 0) {\n                            for (int j = 0; j < n; ++j) {\n                                if (j == i) continue;\n                                const Rect &s = rectRef[j];\n                                // x-overlap?\n                                if (s.a >= cur.c || s.c <= cur.a) continue;\n                                if (s.b >= cur.b) continue; // s above or touching\n                                if (s.d > cur.b) {\n                                    // s.b < b < s.d\n                                    limit = 0;\n                                    break;\n                                } else {\n                                    int cand = cur.b - s.d;\n                                    if (cand < limit) {\n                                        limit = cand;\n                                        if (limit <= 0) {\n                                            limit = 0;\n                                            break;\n                                        }\n                                    }\n                                }\n                            }\n                            if (limit > 0) {\n                                int L = (int)min<long long>(limit, L_area);\n                                if (L > 0) {\n                                    long long delta = 1LL * L * w;\n                                    if (delta > bestDelta) {\n                                        bestDelta = delta;\n                                        bestDir = 1;\n                                        bestL = L;\n                                    }\n                                }\n                            }\n                        }\n                    }\n                }\n\n                // 2: left (decrease a)\n                if (cur.a > 0 && remaining >= h) {\n                    long long L_area = remaining / h;\n                    if (L_area > 0) {\n                        int limit = cur.a;\n                        if (limit > 0) {\n                            for (int j = 0; j < n; ++j) {\n                                if (j == i) continue;\n                                const Rect &s = rectRef[j];\n                                // y-overlap?\n                                if (s.d <= cur.b || cur.d <= s.b) continue;\n                                if (s.a >= cur.a) {\n                                    // s to the right or touching\n                                    continue;\n                                } else {\n                                    if (s.c > cur.a) {\n                                        // s crosses x = cur.a\n                                        limit = 0;\n                                        break;\n                                    } else {\n                                        int cand = cur.a - s.c;\n                                        if (cand < limit) {\n                                            limit = cand;\n                                            if (limit <= 0) {\n                                                limit = 0;\n                                                break;\n                                            }\n                                        }\n                                    }\n                                }\n                            }\n                            if (limit > 0) {\n                                int L = (int)min<long long>(limit, L_area);\n                                if (L > 0) {\n                                    long long delta = 1LL * L * h;\n                                    if (delta > bestDelta) {\n                                        bestDelta = delta;\n                                        bestDir = 2;\n                                        bestL = L;\n                                    }\n                                }\n                            }\n                        }\n                    }\n                }\n\n                // 3: right (increase c)\n                if (cur.c < 10000 && remaining >= h) {\n                    long long L_area = remaining / h;\n                    if (L_area > 0) {\n                        int limit = 10000 - cur.c;\n                        if (limit > 0) {\n                            for (int j = 0; j < n; ++j) {\n                                if (j == i) continue;\n                                const Rect &s = rectRef[j];\n                                // y-overlap?\n                                if (s.d <= cur.b || cur.d <= s.b) continue;\n                                if (cur.c >= s.c) {\n                                    // s to the left or touching\n                                    continue;\n                                } else {\n                                    if (s.a <= cur.c) {\n                                        // s crosses x = cur.c\n                                        limit = 0;\n                                        break;\n                                    } else {\n                                        int cand = s.a - cur.c;\n                                        if (cand < limit) {\n                                            limit = cand;\n                                            if (limit <= 0) {\n                                                limit = 0;\n                                                break;\n                                            }\n                                        }\n                                    }\n                                }\n                            }\n                            if (limit > 0) {\n                                int L = (int)min<long long>(limit, L_area);\n                                if (L > 0) {\n                                    long long delta = 1LL * L * h;\n                                    if (delta > bestDelta) {\n                                        bestDelta = delta;\n                                        bestDir = 3;\n                                        bestL = L;\n                                    }\n                                }\n                            }\n                        }\n                    }\n                }\n\n                if (bestDir == -1 || bestL <= 0 || bestDelta <= 0) break;\n\n                switch (bestDir) {\n                    case 0: cur.d += bestL; break;\n                    case 1: cur.b -= bestL; break;\n                    case 2: cur.a -= bestL; break;\n                    case 3: cur.c += bestL; break;\n                }\n                areaRef[i] += bestDelta;\n            }\n        }\n    };\n\n    greedy_finalize(bestRect, bestArea);\n\n    // Output best layout\n    for (int i = 0; i < n; ++i) {\n        cout << bestRect[i].a << ' ' << bestRect[i].b << ' '\n             << bestRect[i].c << ' ' << bestRect[i].d << '\\n';\n    }\n\n    return 0;\n}","ahc002":"#include <bits/stdc++.h>\nusing namespace std;\n\n// Fast xorshift RNG\nstruct XorShift64 {\n    uint64_t x;\n    XorShift64() {\n        uint64_t seed = chrono::steady_clock::now().time_since_epoch().count();\n        x = seed ^ (seed << 13);\n    }\n    inline uint64_t next() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return x;\n    }\n    inline uint32_t next_u32() {\n        return static_cast<uint32_t>(next());\n    }\n};\n\nstruct Path {\n    int score;\n    vector<int> seq;\n};\n\nconstexpr int H = 50;\nconstexpr int W = 50;\nconstexpr int N = H * W;\nconstexpr int MAX_TILES = 2500;\n\nint tileID[N];                 // tile index for each cell\nint valCell[N];                // score of each cell\nint nei[N][4];                 // neighbors (cell indices)\nint neiCnt[N];                 // number of neighbors for each cell\nint visitedTime[MAX_TILES];    // last iteration stamp when tile was visited\nint startCell;                 // starting cell index\nint maxTileId;                 // maximum tile id in input\n\nint iterStamp = 0;\nXorShift64 rng;\n\n// Check if tile t is visited in current walk\ninline bool isVisitedTile(int t) {\n    return visitedTime[t] == iterStamp;\n}\n\n// Build one path using a given mode (0,1,2)\nPath build_path(int mode) {\n    ++iterStamp;\n    Path path;\n    path.seq.reserve(N);\n    path.score = 0;\n\n    int cur = startCell;\n    path.seq.push_back(cur);\n    path.score += valCell[cur];\n    visitedTime[tileID[cur]] = iterStamp;\n\n    while (true) {\n        int cand[4];\n        int candCount = 0;\n\n        // Collect candidate neighbors: adjacent cells whose tile is not yet visited\n        for (int k = 0; k < neiCnt[cur]; ++k) {\n            int v = nei[cur][k];\n            int t = tileID[v];\n            if (isVisitedTile(t)) continue; // tile already visited\n            cand[candCount++] = v;\n        }\n\n        if (candCount == 0) break;\n\n        int deg[4];\n\n        // Compute \"forward degree\" for each candidate: how many moves are possible after stepping there\n        for (int i = 0; i < candCount; ++i) {\n            int v = cand[i];\n            int tv = tileID[v];\n            int d = 0;\n            for (int k = 0; k < neiCnt[v]; ++k) {\n                int w = nei[v][k];\n                int tw = tileID[w];\n                if (tw == tv) continue;                 // same tile, won't be allowed after step\n                if (isVisitedTile(tw)) continue;        // tile already used\n                ++d;\n            }\n            deg[i] = d;\n        }\n\n        int chosenIdx = 0;\n\n        if (mode == 0) {\n            // Mode 0: balanced\n            // Prefer class 0 (deg>=2), then 1 (deg==1), then 2 (deg==0)\n            // Within class: smaller deg first, then higher value\n            int bestClass = 3;\n            int bestDeg = 1000;\n            int bestVal = -1;\n            for (int i = 0; i < candCount; ++i) {\n                int d = deg[i];\n                int cls = (d >= 2 ? 0 : (d == 1 ? 1 : 2));\n                int v = cand[i];\n                int pv = valCell[v];\n                bool better = false;\n\n                if (cls < bestClass) {\n                    better = true;\n                } else if (cls == bestClass) {\n                    if (d < bestDeg) {\n                        better = true;\n                    } else if (d == bestDeg) {\n                        if (pv > bestVal) {\n                            better = true;\n                        } else if (pv == bestVal) {\n                            // random tie-break\n                            if (rng.next_u32() & 1u) better = true;\n                        }\n                    }\n                }\n\n                if (better) {\n                    bestClass = cls;\n                    bestDeg = d;\n                    bestVal = pv;\n                    chosenIdx = i;\n                }\n            }\n        } else if (mode == 1) {\n            // Mode 1: Warnsdorff-like (minimize deg), but avoid deg=0 if possible.\n            bool hasPositive = false;\n            for (int i = 0; i < candCount; ++i) {\n                if (deg[i] > 0) { hasPositive = true; break; }\n            }\n\n            int bestDeg = 1000;\n            int bestVal = -1;\n            for (int i = 0; i < candCount; ++i) {\n                int d = deg[i];\n                if (hasPositive && d == 0) continue; // skip dead-ends if any extension exists\n                int v = cand[i];\n                int pv = valCell[v];\n                bool better = false;\n\n                if (d < bestDeg) {\n                    better = true;\n                } else if (d == bestDeg) {\n                    if (pv > bestVal) {\n                        better = true;\n                    } else if (pv == bestVal) {\n                        if (rng.next_u32() & 1u) better = true;\n                    }\n                }\n\n                if (better) {\n                    bestDeg = d;\n                    bestVal = pv;\n                    chosenIdx = i;\n                }\n            }\n        } else {\n            // Mode 2: value-first, but avoid deg=0 if possible.\n            bool hasPositive = false;\n            for (int i = 0; i < candCount; ++i) {\n                if (deg[i] > 0) { hasPositive = true; break; }\n            }\n\n            int bestVal = -1;\n            int bestDeg = -1;\n            for (int i = 0; i < candCount; ++i) {\n                int d = deg[i];\n                if (hasPositive && d == 0) continue; // skip dead-ends if any extension exists\n                int v = cand[i];\n                int pv = valCell[v];\n                bool better = false;\n\n                if (pv > bestVal) {\n                    better = true;\n                } else if (pv == bestVal) {\n                    if (d > bestDeg) {\n                        better = true;\n                    } else if (d == bestDeg) {\n                        if (rng.next_u32() & 1u) better = true;\n                    }\n                }\n\n                if (better) {\n                    bestVal = pv;\n                    bestDeg = d;\n                    chosenIdx = i;\n                }\n            }\n        }\n\n        // Small random exploration: 5% chance choose totally random candidate\n        if (candCount > 1 && (rng.next_u32() % 20u == 0u)) {\n            chosenIdx = rng.next_u32() % candCount;\n        }\n\n        int nextCell = cand[chosenIdx];\n        cur = nextCell;\n        path.seq.push_back(cur);\n        path.score += valCell[cur];\n        visitedTime[tileID[cur]] = iterStamp;\n    }\n\n    return path;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int si, sj;\n    if (!(cin >> si >> sj)) {\n        return 0;\n    }\n\n    maxTileId = -1;\n\n    // Read tiles\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            int t;\n            cin >> t;\n            int idx = i * W + j;\n            tileID[idx] = t;\n            if (t > maxTileId) maxTileId = t;\n        }\n    }\n\n    // Read cell values\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            int p;\n            cin >> p;\n            int idx = i * W + j;\n            valCell[idx] = p;\n        }\n    }\n\n    // Precompute neighbors on the grid (4-neighborhood)\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            int idx = i * W + j;\n            int cnt = 0;\n            if (i > 0)     nei[idx][cnt++] = (i - 1) * W + j;\n            if (i + 1 < H) nei[idx][cnt++] = (i + 1) * W + j;\n            if (j > 0)     nei[idx][cnt++] = i * W + (j - 1);\n            if (j + 1 < W) nei[idx][cnt++] = i * W + (j + 1);\n            neiCnt[idx] = cnt;\n        }\n    }\n\n    // Initialize visitedTime\n    for (int i = 0; i <= maxTileId; ++i) visitedTime[i] = 0;\n\n    startCell = si * W + sj;\n\n    auto startTime = chrono::steady_clock::now();\n    const double TIME_LIMIT = 1.9; // seconds\n\n    Path best;\n    best.score = -1;\n\n    int iterations = 0;\n    while (true) {\n        int mode = static_cast<int>(rng.next_u32() % 3u); // 0,1,2\n        Path cur = build_path(mode);\n\n        if (cur.score > best.score ||\n            (cur.score == best.score && cur.seq.size() > best.seq.size())) {\n            best = std::move(cur);\n        }\n\n        ++iterations;\n        if ((iterations & 7) == 0) { // check time every 8 iterations\n            auto now = chrono::steady_clock::now();\n            double elapsed = chrono::duration<double>(now - startTime).count();\n            if (elapsed > TIME_LIMIT) break;\n        }\n    }\n\n    // Convert best.seq (cells) into moves string\n    string ans;\n    ans.reserve(best.seq.size());\n    for (size_t k = 1; k < best.seq.size(); ++k) {\n        int prev = best.seq[k - 1];\n        int cur = best.seq[k];\n        int pi = prev / W, pj = prev % W;\n        int ci = cur / W, cj = cur % W;\n        if (ci == pi) {\n            if (cj == pj + 1) ans.push_back('R');\n            else if (cj == pj - 1) ans.push_back('L');\n        } else if (cj == pj) {\n            if (ci == pi + 1) ans.push_back('D');\n            else if (ci == pi - 1) ans.push_back('U');\n        }\n        // No other case should occur because we only move to neighbors.\n    }\n\n    cout << ans << '\\n';\n    return 0;\n}","ahc003":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const int H = 30;\nstatic const int W = 30;\nstatic const int N = H * W;\nstatic const int EH = H * (W - 1); // number of horizontal edges\nstatic const int EV = (H - 1) * W; // number of vertical edges\nstatic const int E  = EH + EV;\nstatic const double INF = 1e100;\n\n// Edge indices for canonical orientations\nint h_id[H][W - 1]; // horizontal: (i,j)-(i,j+1) -> h_id[i][j]\nint v_id[H - 1][W]; // vertical:   (i,j)-(i+1,j) -> v_id[i][j]\n\n// Adjacency list: (to, edge_id)\nvector<pair<int,int>> adj[N];\n\n// Our edge weight estimates and temporary jittered weights\nvector<double> w(E), eff_w(E);\n\n// Dijkstra buffers\ndouble dist_arr[N];\nint prev_v_arr[N];\n\n// RNG for jitter\nmt19937_64 rng(71236782123ULL);\n\ninline double rand01() {\n    return std::generate_canonical<double, 53>(rng); // [0,1)\n}\n\ninline int vid(int i, int j) {\n    return i * W + j;\n}\n\n// Fallback: simple Manhattan path and its edges, with predicted cost under w[]\nvoid build_manhattan(int si, int sj, int ti, int tj,\n                     string &path, vector<int> &edges, double &pred_cost) {\n    path.clear();\n    int ci = si, cj = sj;\n    while (ci < ti) { path.push_back('D'); ++ci; }\n    while (ci > ti) { path.push_back('U'); --ci; }\n    while (cj < tj) { path.push_back('R'); ++cj; }\n    while (cj > tj) { path.push_back('L'); --cj; }\n\n    // Convert to edges and cost\n    edges.clear();\n    edges.reserve(path.size());\n    pred_cost = 0.0;\n    ci = si;\n    cj = sj;\n    for (char c : path) {\n        int eid = -1;\n        if (c == 'U') {\n            int ni = ci - 1;\n            eid = v_id[ni][cj];\n            ci = ni;\n        } else if (c == 'D') {\n            eid = v_id[ci][cj];\n            ci = ci + 1;\n        } else if (c == 'L') {\n            int nj = cj - 1;\n            eid = h_id[ci][nj];\n            cj = nj;\n        } else if (c == 'R') {\n            eid = h_id[ci][cj];\n            cj = cj + 1;\n        }\n        edges.push_back(eid);\n        pred_cost += w[eid];\n    }\n}\n\n// Run one Dijkstra with jittered weights, build a candidate path, its edges, and predicted cost\nvoid build_candidate(int si, int sj, int ti, int tj, double jitter,\n                     string &path, vector<int> &edges, double &pred_cost) {\n    // Build jittered effective weights\n    for (int e = 0; e < E; ++e) {\n        double u = 2.0 * rand01() - 1.0; // [-1,1)\n        double factor = 1.0 + jitter * u;\n        if (factor < 0.5) factor = 0.5; // safety\n        eff_w[e] = w[e] * factor;\n        if (eff_w[e] < 1.0) eff_w[e] = 1.0; // strictly positive\n    }\n\n    int s = vid(si, sj);\n    int t = vid(ti, tj);\n\n    // Initialize Dijkstra arrays\n    for (int i = 0; i < N; ++i) {\n        dist_arr[i] = INF;\n        prev_v_arr[i] = -1;\n    }\n    dist_arr[s] = 0.0;\n\n    using P = pair<double,int>;\n    priority_queue<P, vector<P>, greater<P>> pq;\n    pq.emplace(0.0, s);\n\n    while (!pq.empty()) {\n        auto [d, u] = pq.top();\n        pq.pop();\n        if (d != dist_arr[u]) continue;\n        if (u == t) break;\n        for (auto &pe : adj[u]) {\n            int v = pe.first;\n            int eid = pe.second;\n            double nd = d + eff_w[eid];\n            if (nd < dist_arr[v]) {\n                dist_arr[v] = nd;\n                prev_v_arr[v] = u;\n                pq.emplace(nd, v);\n            }\n        }\n    }\n\n    if (prev_v_arr[t] == -1) {\n        // Fallback: Manhattan path (should not happen in connected grid)\n        build_manhattan(si, sj, ti, tj, path, edges, pred_cost);\n        return;\n    }\n\n    // Reconstruct vertex sequence from s to t\n    vector<int> vs_rev;\n    vs_rev.reserve(64);\n    int cur = t;\n    while (cur != s) {\n        vs_rev.push_back(cur);\n        cur = prev_v_arr[cur];\n    }\n    vs_rev.push_back(s); // now vs_rev: [t, ..., s]\n\n    vector<int> vs;\n    vs.reserve(vs_rev.size());\n    for (int idx = (int)vs_rev.size() - 1; idx >= 0; --idx) {\n        vs.push_back(vs_rev[idx]);\n    }\n    int L = (int)vs.size() - 1; // number of edges\n\n    // Build move string and edges, and compute predicted cost under w\n    path.clear();\n    path.reserve(L);\n    edges.clear();\n    edges.reserve(L);\n    pred_cost = 0.0;\n\n    for (int k = 0; k < L; ++k) {\n        int u = vs[k];\n        int v = vs[k + 1];\n        int ui = u / W, uj = u % W;\n        int vi = v / W, vj = v % W;\n\n        char c;\n        int eid = -1;\n\n        if (vi == ui) {\n            if (vj == uj + 1) { // right\n                c = 'R';\n                eid = h_id[ui][uj];\n            } else { // vj == uj - 1, left\n                c = 'L';\n                eid = h_id[ui][vj];\n            }\n        } else { // vj == uj\n            if (vi == ui + 1) { // down\n                c = 'D';\n                eid = v_id[ui][uj];\n            } else { // vi == ui - 1, up\n                c = 'U';\n                eid = v_id[vi][uj];\n            }\n        }\n\n        path.push_back(c);\n        edges.push_back(eid);\n        pred_cost += w[eid];\n    }\n}\n\n// Convert move string into edge list (used only for fallback if needed elsewhere)\nvoid path_to_edges(int si, int sj, const string &path, vector<int> &edges) {\n    edges.clear();\n    edges.reserve(path.size());\n    int i = si, j = sj;\n    for (char c : path) {\n        int eid = -1;\n        if (c == 'U') {\n            int ni = i - 1;\n            eid = v_id[ni][j];\n            i = ni;\n        } else if (c == 'D') {\n            eid = v_id[i][j];\n            i = i + 1;\n        } else if (c == 'L') {\n            int nj = j - 1;\n            eid = h_id[i][nj];\n            j = nj;\n        } else if (c == 'R') {\n            eid = h_id[i][j];\n            j = j + 1;\n        }\n        edges.push_back(eid);\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // Build graph and edge indexing\n    int eid = 0;\n    // Horizontal edges\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W - 1; ++j) {\n            h_id[i][j] = eid;\n            int u = vid(i, j);\n            int v = vid(i, j + 1);\n            adj[u].emplace_back(v, eid);\n            adj[v].emplace_back(u, eid);\n            ++eid;\n        }\n    }\n    // Vertical edges\n    for (int i = 0; i < H - 1; ++i) {\n        for (int j = 0; j < W; ++j) {\n            v_id[i][j] = eid;\n            int u = vid(i, j);\n            int v = vid(i + 1, j);\n            adj[u].emplace_back(v, eid);\n            adj[v].emplace_back(u, eid);\n            ++eid;\n        }\n    }\n\n    // Initialize weights\n    w.assign(E, 5000.0);\n    eff_w.assign(E, 5000.0);\n\n    const double ETA = 0.5; // learning rate multiplier\n\n    vector<int> best_edges, tmp_edges;\n    string best_path, tmp_path;\n\n    for (int q = 0; q < 1000; ++q) {\n        int si, sj, ti, tj;\n        if (!(cin >> si >> sj >> ti >> tj)) {\n            return 0; // EOF / error\n        }\n\n        // Jitter amplitude for this query (same as baseline)\n        const double JITTER0 = 0.03;\n        double jitter = JITTER0 * max(0.0, 1.0 - (double)q / 800.0);\n        if (jitter < 0.0) jitter = 0.0;\n\n        int num_candidates = (jitter > 1e-12 ? 4 : 1);\n\n        double best_cost = INF;\n        best_path.clear();\n        best_edges.clear();\n\n        for (int it = 0; it < num_candidates; ++it) {\n            double pred_cost = 0.0;\n            build_candidate(si, sj, ti, tj, jitter, tmp_path, tmp_edges, pred_cost);\n            if (pred_cost < best_cost) {\n                best_cost = pred_cost;\n                best_path = tmp_path;\n                best_edges = tmp_edges;\n            }\n        }\n\n        // Output chosen path\n        cout << best_path << '\\n';\n        cout.flush();\n\n        long long y_ll;\n        if (!(cin >> y_ll)) {\n            return 0; // EOF / error\n        }\n        double y = (double)y_ll;\n\n        int L = (int)best_edges.size();\n        if (L == 0) continue; // should not happen (Manhattan distance >= 10)\n\n        double pred = best_cost; // predicted cost under w for chosen path\n        double error = y - pred;\n\n        double lr = ETA / (double)L;\n        for (int e : best_edges) {\n            w[e] += lr * error;\n            if (w[e] < 1000.0) w[e] = 1000.0;\n            else if (w[e] > 9000.0) w[e] = 9000.0;\n        }\n    }\n\n    return 0;\n}","ahc004":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const int MAX_N = 20;\nstatic const int MAX_M = 800;\nstatic const int ALPHA = 8;\nstatic const int MAXW  = (MAX_M + 63) / 64;\n\nint N, M;\nint WORDS; // number of 64-bit words used for bitsets\nvector<string> patterns;\n\n// bitset over up to MAX_M bits\nstruct BS {\n    uint64_t w[MAXW];\n};\n\n// bitset helpers\ninline void bs_clear(BS &b) {\n    memset(b.w, 0, sizeof(b.w));\n}\ninline void bs_or_inplace(BS &a, const BS &b) {\n    for (int i = 0; i < WORDS; ++i) a.w[i] |= b.w[i];\n}\ninline void bs_xor(BS &res, const BS &a, const BS &b) {\n    for (int i = 0; i < WORDS; ++i) res.w[i] = a.w[i] ^ b.w[i];\n}\ninline void bs_or(BS &res, const BS &a, const BS &b) {\n    for (int i = 0; i < WORDS; ++i) res.w[i] = a.w[i] | b.w[i];\n}\ninline bool bs_test(const BS &b, int idx) {\n    return (b.w[idx >> 6] >> (idx & 63)) & 1ULL;\n}\ninline void bs_set(BS &b, int idx) {\n    b.w[idx >> 6] |= 1ULL << (idx & 63);\n}\ninline void bs_reset(BS &b, int idx) {\n    b.w[idx >> 6] &= ~(1ULL << (idx & 63));\n}\n\n// iterate over set bits of b, calling f(idx) for each\ntemplate <class F>\ninline void bs_for_each(const BS &b, F f) {\n    for (int w = 0; w < WORDS; ++w) {\n        uint64_t x = b.w[w];\n        while (x) {\n            int lsb = __builtin_ctzll(x);\n            int idx = (w << 6) + lsb;\n            if (idx >= M) return; // safety; bits >= M are not used\n            f(idx);\n            x &= x - 1; // clear lowest set bit\n        }\n    }\n}\n\n// Aho\u2013Corasick automaton\nstruct Node {\n    int next[ALPHA];\n    int link;\n    BS out; // bitset of patterns that end at this state (including via failure)\n    Node() {\n        fill(next, next + ALPHA, -1);\n        link = 0;\n        bs_clear(out);\n    }\n};\nvector<Node> ac;\n\n// grid and evaluation structures\nchar grid[MAX_N][MAX_N];\nBS row_bs[MAX_N], col_bs[MAX_N];\nint pattern_cov_count[MAX_M];\nint current_c = 0;\n\n// RNG\nmt19937_64 rng;\n\ninline int ch_idx(char c) {\n    return c - 'A'; // 'A'..'H' -> 0..7\n}\n\nvoid build_automaton() {\n    ac.clear();\n    ac.emplace_back(); // root\n\n    // build trie and set pattern bits\n    for (int i = 0; i < M; ++i) {\n        const string &s = patterns[i];\n        int v = 0;\n        for (char ch : s) {\n            int c = ch_idx(ch);\n            if (ac[v].next[c] == -1) {\n                ac[v].next[c] = (int)ac.size();\n                ac.emplace_back();\n            }\n            v = ac[v].next[c];\n        }\n        bs_set(ac[v].out, i);\n    }\n\n    // build failure links\n    queue<int> q;\n\n    for (int c = 0; c < ALPHA; ++c) {\n        int u = ac[0].next[c];\n        if (u != -1) {\n            ac[u].link = 0;\n            q.push(u);\n        } else {\n            ac[0].next[c] = 0;\n        }\n    }\n\n    while (!q.empty()) {\n        int v = q.front(); q.pop();\n        int link = ac[v].link;\n\n        // propagate pattern bits from failure link\n        bs_or_inplace(ac[v].out, ac[link].out);\n\n        for (int c = 0; c < ALPHA; ++c) {\n            int u = ac[v].next[c];\n            if (u != -1) {\n                ac[u].link = ac[link].next[c];\n                q.push(u);\n            } else {\n                ac[v].next[c] = ac[link].next[c];\n            }\n        }\n    }\n}\n\n// scan a line through AC, return bitset of patterns appearing\ninline BS scan_line(const char *s, int len) {\n    BS res;\n    bs_clear(res);\n    int v = 0;\n    for (int i = 0; i < len; ++i) {\n        int c = ch_idx(s[i]);\n        v = ac[v].next[c];\n        bs_or_inplace(res, ac[v].out);\n    }\n    return res;\n}\n\n// recompute one row r and update global counts\nvoid recalc_row(int r) {\n    char line[2 * MAX_N];\n    for (int j = 0; j < N; ++j) line[j] = grid[r][j];\n    for (int j = 0; j < N; ++j) line[N + j] = line[j];\n\n    BS mark = scan_line(line, 2 * N);\n    BS changed;\n    bs_xor(changed, row_bs[r], mark);\n\n    bs_for_each(changed, [&](int i) {\n        bool oldFlag = bs_test(row_bs[r], i);\n        bool newFlag = bs_test(mark, i);\n        if (oldFlag == newFlag) return;\n\n        if (newFlag) {\n            bs_set(row_bs[r], i);\n            if (pattern_cov_count[i] == 0) current_c++;\n            pattern_cov_count[i]++;\n        } else {\n            bs_reset(row_bs[r], i);\n            pattern_cov_count[i]--;\n            if (pattern_cov_count[i] == 0) current_c--;\n        }\n    });\n}\n\n// recompute one column c and update global counts\nvoid recalc_col(int c) {\n    char line[2 * MAX_N];\n    for (int i = 0; i < N; ++i) line[i] = grid[i][c];\n    for (int i = 0; i < N; ++i) line[N + i] = line[i];\n\n    BS mark = scan_line(line, 2 * N);\n    BS changed;\n    bs_xor(changed, col_bs[c], mark);\n\n    bs_for_each(changed, [&](int i) {\n        bool oldFlag = bs_test(col_bs[c], i);\n        bool newFlag = bs_test(mark, i);\n        if (oldFlag == newFlag) return;\n\n        if (newFlag) {\n            bs_set(col_bs[c], i);\n            if (pattern_cov_count[i] == 0) current_c++;\n            pattern_cov_count[i]++;\n        } else {\n            bs_reset(col_bs[c], i);\n            pattern_cov_count[i]--;\n            if (pattern_cov_count[i] == 0) current_c--;\n        }\n    });\n}\n\n// targeted pattern \"kick\": choose a poorly-covered pattern and place it greedily\nvoid apply_pattern_kick() {\n    if (M == 0) return;\n\n    uniform_int_distribution<int> base_dist(0, M - 1);\n    int base = base_dist(rng);\n    int pid = -1;\n\n    // coverage == 0 preferred\n    for (int j = 0; j < M; ++j) {\n        int id = (base + j) % M;\n        if (pattern_cov_count[id] == 0) {\n            pid = id;\n            break;\n        }\n    }\n    // then coverage == 1\n    if (pid == -1) {\n        for (int j = 0; j < M; ++j) {\n            int id = (base + j) % M;\n            if (pattern_cov_count[id] == 1) {\n                pid = id;\n                break;\n            }\n        }\n    }\n    // fallback to random\n    if (pid == -1) pid = base;\n\n    const string &s = patterns[pid];\n    int len = (int)s.size();\n\n    int bestScore = -1;\n    int bestDir = 0; // 0: horizontal, 1: vertical\n    int bestR = 0, bestC = 0;\n\n    // horizontal placements\n    for (int r = 0; r < N; ++r) {\n        for (int c0 = 0; c0 < N; ++c0) {\n            int score = 0;\n            int c = c0;\n            for (int t = 0; t < len; ++t) {\n                if (grid[r][c] == s[t]) score++;\n                c++;\n                if (c == N) c = 0;\n            }\n            if (score > bestScore) {\n                bestScore = score;\n                bestDir = 0;\n                bestR = r;\n                bestC = c0;\n            } else if (score == bestScore && (rng() & 1)) {\n                bestScore = score;\n                bestDir = 0;\n                bestR = r;\n                bestC = c0;\n            }\n        }\n    }\n\n    // vertical placements\n    for (int c = 0; c < N; ++c) {\n        for (int r0 = 0; r0 < N; ++r0) {\n            int score = 0;\n            int r = r0;\n            for (int t = 0; t < len; ++t) {\n                if (grid[r][c] == s[t]) score++;\n                r++;\n                if (r == N) r = 0;\n            }\n            if (score > bestScore) {\n                bestScore = score;\n                bestDir = 1;\n                bestR = r0;\n                bestC = c;\n            } else if (score == bestScore && (rng() & 1)) {\n                bestScore = score;\n                bestDir = 1;\n                bestR = r0;\n                bestC = c;\n            }\n        }\n    }\n\n    bool rowChanged[MAX_N] = {false};\n    bool colChanged[MAX_N] = {false};\n\n    // apply best placement\n    if (bestDir == 0) {\n        int r = bestR;\n        int c = bestC;\n        for (int t = 0; t < len; ++t) {\n            if (grid[r][c] != s[t]) {\n                grid[r][c] = s[t];\n                rowChanged[r] = true;\n                colChanged[c] = true;\n            }\n            c++;\n            if (c == N) c = 0;\n        }\n    } else {\n        int c = bestC;\n        int r = bestR;\n        for (int t = 0; t < len; ++t) {\n            if (grid[r][c] != s[t]) {\n                grid[r][c] = s[t];\n                rowChanged[r] = true;\n                colChanged[c] = true;\n            }\n            r++;\n            if (r == N) r = 0;\n        }\n    }\n\n    // recompute affected rows/columns\n    for (int r = 0; r < N; ++r) if (rowChanged[r]) recalc_row(r);\n    for (int c = 0; c < N; ++c) if (colChanged[c]) recalc_col(c);\n}\n\ndouble my_rand_double() {\n    // 53-bit mantissa random double in [0,1)\n    return (rng() >> 11) * (1.0 / (1ULL << 53));\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> M;\n    patterns.resize(M);\n    for (int i = 0; i < M; ++i) cin >> patterns[i];\n\n    WORDS = (M + 63) / 64;\n\n    // init RNG\n    uint64_t seed = chrono::high_resolution_clock::now().time_since_epoch().count();\n    rng.seed(seed);\n\n    build_automaton();\n\n    uniform_int_distribution<int> letter_dist(0, ALPHA - 1);\n\n    // initial grid: random letters\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            grid[i][j] = char('A' + letter_dist(rng));\n\n    // constructive pass: random order of patterns, greedily align with existing letters\n    vector<int> order(M);\n    iota(order.begin(), order.end(), 0);\n    shuffle(order.begin(), order.end(), rng);\n\n    for (int idx = 0; idx < M; ++idx) {\n        int pid = order[idx];\n        const string &s = patterns[pid];\n        int len = (int)s.size();\n\n        int bestScore = -1;\n        int bestDir = 0;\n        int bestR = 0, bestC = 0;\n\n        // horizontal candidates\n        for (int r = 0; r < N; ++r) {\n            for (int c0 = 0; c0 < N; ++c0) {\n                int score = 0;\n                int c = c0;\n                for (int t = 0; t < len; ++t) {\n                    if (grid[r][c] == s[t]) score++;\n                    c++;\n                    if (c == N) c = 0;\n                }\n                if (score > bestScore) {\n                    bestScore = score;\n                    bestDir = 0;\n                    bestR = r;\n                    bestC = c0;\n                } else if (score == bestScore && my_rand_double() < 0.5) {\n                    bestScore = score;\n                    bestDir = 0;\n                    bestR = r;\n                    bestC = c0;\n                }\n            }\n        }\n\n        // vertical candidates\n        for (int c = 0; c < N; ++c) {\n            for (int r0 = 0; r0 < N; ++r0) {\n                int score = 0;\n                int r = r0;\n                for (int t = 0; t < len; ++t) {\n                    if (grid[r][c] == s[t]) score++;\n                    r++;\n                    if (r == N) r = 0;\n                }\n                if (score > bestScore) {\n                    bestScore = score;\n                    bestDir = 1;\n                    bestR = r0;\n                    bestC = c;\n                } else if (score == bestScore && my_rand_double() < 0.5) {\n                    bestScore = score;\n                    bestDir = 1;\n                    bestR = r0;\n                    bestC = c;\n                }\n            }\n        }\n\n        // apply best placement\n        if (bestDir == 0) {\n            int r = bestR;\n            int c = bestC;\n            for (int t = 0; t < len; ++t) {\n                grid[r][c] = s[t];\n                c++;\n                if (c == N) c = 0;\n            }\n        } else {\n            int c = bestC;\n            int r = bestR;\n            for (int t = 0; t < len; ++t) {\n                grid[r][c] = s[t];\n                r++;\n                if (r == N) r = 0;\n            }\n        }\n    }\n\n    // Initialize evaluation\n    for (int r = 0; r < N; ++r) bs_clear(row_bs[r]);\n    for (int c = 0; c < N; ++c) bs_clear(col_bs[c]);\n    fill(pattern_cov_count, pattern_cov_count + M, 0);\n    current_c = 0;\n\n    for (int r = 0; r < N; ++r) recalc_row(r);\n    for (int c = 0; c < N; ++c) recalc_col(c);\n\n    // SA parameters\n    const double TIME_LIMIT = 2.78; // seconds for SA part\n    auto start_time = chrono::high_resolution_clock::now();\n    double T0 = 1.5;\n    double T1 = 0.05;\n\n    // keep best grid\n    char best_grid[MAX_N][MAX_N];\n    int best_c = current_c;\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            best_grid[i][j] = grid[i][j];\n\n    int iter = 0;\n    int stagnation = 0; // iterations since last improvement of best_c\n    uniform_int_distribution<int> row_dist(0, N - 1);\n    uniform_int_distribution<int> col_dist(0, N - 1);\n\n    double progress = 0.0;\n    double T = T0;\n\n    while (true) {\n        ++iter;\n        if ((iter & 511) == 0) {\n            auto now = chrono::high_resolution_clock::now();\n            double elapsed = chrono::duration<double>(now - start_time).count();\n            if (elapsed > TIME_LIMIT) break;\n            progress = elapsed / TIME_LIMIT;\n            if (progress > 1.0) progress = 1.0;\n            T = T0 + (T1 - T0) * progress;\n        }\n\n        // periodic targeted kicks early\n        if ((iter % 2000 == 0) && (progress < 0.5)) {\n            apply_pattern_kick();\n            if (current_c > best_c) {\n                best_c = current_c;\n                stagnation = 0;\n                for (int i = 0; i < N; ++i)\n                    for (int j = 0; j < N; ++j)\n                        best_grid[i][j] = grid[i][j];\n            }\n        }\n\n        // stagnation-based stronger kicks\n        if (stagnation > 25000 && progress < 0.7) {\n            for (int t = 0; t < 3; ++t) apply_pattern_kick();\n            stagnation = 0;\n            if (current_c > best_c) {\n                best_c = current_c;\n                for (int i = 0; i < N; ++i)\n                    for (int j = 0; j < N; ++j)\n                        best_grid[i][j] = grid[i][j];\n            }\n        }\n\n        int r = row_dist(rng);\n        int c = col_dist(rng);\n        char oldCh = grid[r][c];\n\n        char newCh;\n        do {\n            newCh = char('A' + letter_dist(rng));\n        } while (newCh == oldCh);\n\n        // candidate row\n        char row_line[2 * MAX_N];\n        for (int j = 0; j < N; ++j)\n            row_line[j] = (j == c) ? newCh : grid[r][j];\n        for (int j = 0; j < N; ++j)\n            row_line[N + j] = row_line[j];\n\n        BS mark_row = scan_line(row_line, 2 * N);\n\n        // candidate column\n        char col_line[2 * MAX_N];\n        for (int i = 0; i < N; ++i)\n            col_line[i] = (i == r) ? newCh : grid[i][c];\n        for (int i = 0; i < N; ++i)\n            col_line[N + i] = col_line[i];\n\n        BS mark_col = scan_line(col_line, 2 * N);\n\n        // changed patterns on row and column\n        BS changed_row, changed_col, changed_union;\n        bs_xor(changed_row, row_bs[r], mark_row);\n        bs_xor(changed_col, col_bs[c], mark_col);\n        bs_or(changed_union, changed_row, changed_col);\n\n        int new_c = current_c;\n\n        // compute new_c considering only changed patterns\n        bs_for_each(changed_union, [&](int i) {\n            int oldCov = pattern_cov_count[i];\n            int newCov = oldCov;\n\n            bool oldRow = bs_test(row_bs[r], i);\n            bool newRow = bs_test(mark_row, i);\n            newCov += (int)newRow - (int)oldRow;\n\n            bool oldCol = bs_test(col_bs[c], i);\n            bool newCol = bs_test(mark_col, i);\n            newCov += (int)newCol - (int)oldCol;\n\n            if (oldCov == 0 && newCov > 0) new_c++;\n            else if (oldCov > 0 && newCov == 0) new_c--;\n        });\n\n        int delta = new_c - current_c;\n        bool accept = false;\n        if (delta >= 0) {\n            accept = true;\n        } else {\n            double prob = exp((double)delta / T);\n            if (prob > my_rand_double()) accept = true;\n        }\n\n        if (accept) {\n            // commit the change\n            grid[r][c] = newCh;\n            bs_for_each(changed_union, [&](int i) {\n                int oldCov = pattern_cov_count[i];\n                int newCov = oldCov;\n\n                bool oldRow = bs_test(row_bs[r], i);\n                bool newRow = bs_test(mark_row, i);\n                newCov += (int)newRow - (int)oldRow;\n\n                bool oldCol = bs_test(col_bs[c], i);\n                bool newCol = bs_test(mark_col, i);\n                newCov += (int)newCol - (int)oldCol;\n\n                pattern_cov_count[i] = newCov;\n\n                if (newRow) bs_set(row_bs[r], i);\n                else bs_reset(row_bs[r], i);\n                if (newCol) bs_set(col_bs[c], i);\n                else bs_reset(col_bs[c], i);\n            });\n            current_c = new_c;\n\n            if (current_c > best_c) {\n                best_c = current_c;\n                stagnation = 0;\n                for (int i = 0; i < N; ++i)\n                    for (int j = 0; j < N; ++j)\n                        best_grid[i][j] = grid[i][j];\n            } else {\n                stagnation++;\n            }\n        } else {\n            stagnation++;\n        }\n    }\n\n    // Output best grid\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) cout << best_grid[i][j];\n        cout << '\\n';\n    }\n\n    return 0;\n}","ahc005":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Edge {\n    int to;\n    int w;\n};\n\nconst int INF = 1e9;\n\n// Compute travel time of a route (sequence of cell IDs).\n// Cost to move into cell v is cost[v].\nlong long computeTravelTime(const vector<int> &route, const vector<int> &cost) {\n    long long t = 0;\n    for (int i = 1; i < (int)route.size(); ++i) {\n        t += cost[route[i]];\n    }\n    return t;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, si, sj;\n    if (!(cin >> N >> si >> sj)) return 0;\n    vector<string> grid(N);\n    for (int i = 0; i < N; ++i) cin >> grid[i];\n\n    // Map each road cell to an ID\n    static int idOf[70][70];\n    int r = 0;\n    vector<pair<int,int>> pos;   // id -> (i,j)\n    vector<int> cost;            // id -> cell cost (5-9)\n    pos.reserve(N * N);\n    cost.reserve(N * N);\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (grid[i][j] != '#') {\n                idOf[i][j] = r++;\n                pos.emplace_back(i, j);\n                cost.push_back(grid[i][j] - '0');\n            } else {\n                idOf[i][j] = -1;\n            }\n        }\n    }\n\n    if (r == 0) {\n        cout << \"\\n\";\n        return 0;\n    }\n\n    int startId = idOf[si][sj];\n\n    // Build graph of road cells\n    vector<vector<Edge>> G(r);\n    int di[4] = {-1, 1, 0, 0};\n    int dj[4] = {0, 0, -1, 1};\n    for (int id = 0; id < r; ++id) {\n        auto [i, j] = pos[id];\n        for (int d = 0; d < 4; ++d) {\n            int ni = i + di[d], nj = j + dj[d];\n            if (0 <= ni && ni < N && 0 <= nj && nj < N && idOf[ni][nj] != -1) {\n                int v = idOf[ni][nj];\n                G[id].push_back({v, cost[v]});\n            }\n        }\n    }\n\n    // ---------- Fallback DFS route (visit all cells) ----------\n    auto buildDFSRoute = [&]() -> vector<int> {\n        vector<int> route;\n        route.reserve(2 * r + 5);\n        vector<char> used(r, 0);\n        vector<int> st;\n        vector<int> edgeIdx(r, 0);\n\n        route.push_back(startId);\n        used[startId] = 1;\n        st.push_back(startId);\n\n        while (!st.empty()) {\n            int u = st.back();\n            bool advanced = false;\n            int &ei = edgeIdx[u];\n            while (ei < (int)G[u].size()) {\n                int v = G[u][ei].to;\n                ++ei;\n                if (!used[v]) {\n                    used[v] = 1;\n                    st.push_back(v);\n                    route.push_back(v);\n                    advanced = true;\n                    break;\n                }\n            }\n            if (!advanced) {\n                st.pop_back();\n                if (!st.empty()) {\n                    route.push_back(st.back());\n                }\n            }\n        }\n        return route; // starts and ends at startId\n    };\n\n    vector<int> fallbackRoute = buildDFSRoute();\n    long long fallbackTime = computeTravelTime(fallbackRoute, cost);\n\n    // ---------- Build horizontal and vertical segments ----------\n    vector<vector<int>> rowSegCells;\n    vector<int> rowSegIdOfCell(r, -1);\n    for (int i = 0; i < N; ++i) {\n        int j = 0;\n        while (j < N) {\n            if (grid[i][j] == '#') {\n                ++j;\n                continue;\n            }\n            int segIdx = (int)rowSegCells.size();\n            rowSegCells.emplace_back();\n            while (j < N && grid[i][j] != '#') {\n                int id = idOf[i][j];\n                rowSegIdOfCell[id] = segIdx;\n                rowSegCells.back().push_back(id);\n                ++j;\n            }\n        }\n    }\n\n    vector<vector<int>> colSegCells;\n    vector<int> colSegIdOfCell(r, -1);\n    for (int j = 0; j < N; ++j) {\n        int i = 0;\n        while (i < N) {\n            if (grid[i][j] == '#') {\n                ++i;\n                continue;\n            }\n            int segIdx = (int)colSegCells.size();\n            colSegCells.emplace_back();\n            while (i < N && grid[i][j] != '#') {\n                int id = idOf[i][j];\n                colSegIdOfCell[id] = segIdx;\n                colSegCells.back().push_back(id);\n                ++i;\n            }\n        }\n    }\n\n    // ---------- Precompute visibility (coverage) for all cells ----------\n    vector<vector<int>> coverageAll(r);\n    for (int id = 0; id < r; ++id) {\n        auto &v = coverageAll[id];\n        auto &rowV = rowSegCells[rowSegIdOfCell[id]];\n        auto &colV = colSegCells[colSegIdOfCell[id]];\n        v.reserve(rowV.size() + colV.size());\n        for (int x : rowV) v.push_back(x);\n        for (int x : colV) v.push_back(x);\n    }\n\n    // ---------- Build candidate vantage cells (mostly intersections) ----------\n    vector<char> isIntersection(r, 0);\n    vector<char> hasInterRow(rowSegCells.size(), 0);\n    vector<char> hasInterCol(colSegCells.size(), 0);\n\n    for (int id = 0; id < r; ++id) {\n        auto [i, j] = pos[id];\n        bool hor = false, ver = false;\n        if (j > 0 && idOf[i][j-1] != -1) hor = true;\n        if (j+1 < N && idOf[i][j+1] != -1) hor = true;\n        if (i > 0 && idOf[i-1][j] != -1) ver = true;\n        if (i+1 < N && idOf[i+1][j] != -1) ver = true;\n        if (hor && ver) {\n            isIntersection[id] = 1;\n            hasInterRow[rowSegIdOfCell[id]] = 1;\n            hasInterCol[colSegIdOfCell[id]] = 1;\n        }\n    }\n\n    vector<char> isCandidate(r, 0);\n    vector<int> candidateCells;\n    candidateCells.reserve(r);\n\n    // Intersections\n    for (int id = 0; id < r; ++id) {\n        if (isIntersection[id]) {\n            isCandidate[id] = 1;\n            candidateCells.push_back(id);\n        }\n    }\n    // Midpoints of segments without intersections\n    for (int s = 0; s < (int)rowSegCells.size(); ++s) {\n        if (!hasInterRow[s]) {\n            int mid = rowSegCells[s][rowSegCells[s].size() / 2];\n            if (!isCandidate[mid]) {\n                isCandidate[mid] = 1;\n                candidateCells.push_back(mid);\n            }\n        }\n    }\n    for (int s = 0; s < (int)colSegCells.size(); ++s) {\n        if (!hasInterCol[s]) {\n            int mid = colSegCells[s][colSegCells[s].size() / 2];\n            if (!isCandidate[mid]) {\n                isCandidate[mid] = 1;\n                candidateCells.push_back(mid);\n            }\n        }\n    }\n    // Ensure start cell is candidate\n    if (!isCandidate[startId]) {\n        isCandidate[startId] = 1;\n        candidateCells.push_back(startId);\n    }\n\n    // Coverage of candidates, and which cells are coverable by some candidate\n    int C = (int)candidateCells.size();\n    vector<vector<int>> candCover;\n    candCover.reserve(C);\n    vector<char> cellCovered(r, 0);\n    for (int idx = 0; idx < C; ++idx) {\n        int cell = candidateCells[idx];\n        candCover.push_back(coverageAll[cell]);\n        for (int x : candCover.back()) cellCovered[x] = 1;\n    }\n\n    // Patch: if some cell is not covered by any candidate, add it itself as candidate\n    for (int id = 0; id < r; ++id) {\n        if (!cellCovered[id]) {\n            candidateCells.push_back(id);\n            candCover.push_back(coverageAll[id]);\n            for (int x : coverageAll[id]) cellCovered[x] = 1;\n        }\n    }\n    C = (int)candidateCells.size();\n\n    // ---------- Greedy set cover on candidates (cell-based) ----------\n    vector<int> vantageCells;        // resulting vantage cell IDs\n    vantageCells.reserve(C);\n\n    vector<char> coveredCells(r, 0);\n    int coveredCount = 0;\n    vector<char> candSelected(C, 0);\n\n    auto selectCandidate = [&](int idx) {\n        if (candSelected[idx]) return;\n        candSelected[idx] = 1;\n        int cell = candidateCells[idx];\n        vantageCells.push_back(cell);\n        for (int x : candCover[idx]) {\n            if (!coveredCells[x]) {\n                coveredCells[x] = 1;\n                ++coveredCount;\n            }\n        }\n    };\n\n    // Use start cell as the first vantage\n    int startCandIdx = -1;\n    for (int idx = 0; idx < C; ++idx) {\n        if (candidateCells[idx] == startId) {\n            startCandIdx = idx;\n            break;\n        }\n    }\n    if (startCandIdx == -1) {\n        // Safeguard (shouldn't happen)\n        vantageCells.push_back(startId);\n        for (int x : coverageAll[startId]) {\n            if (!coveredCells[x]) {\n                coveredCells[x] = 1;\n                ++coveredCount;\n            }\n        }\n    } else {\n        selectCandidate(startCandIdx);\n    }\n\n    while (coveredCount < r) {\n        int bestIdx = -1;\n        int bestGain = -1;\n        for (int idx = 0; idx < C; ++idx) {\n            if (candSelected[idx]) continue;\n            int gain = 0;\n            for (int x : candCover[idx]) {\n                if (!coveredCells[x]) ++gain;\n            }\n            if (gain > bestGain) {\n                bestGain = gain;\n                bestIdx = idx;\n            } else if (gain == bestGain && gain > 0 && bestIdx != -1) {\n                // Tie-break: closer to start (Manhattan)\n                int cellNew = candidateCells[idx];\n                int cellBest = candidateCells[bestIdx];\n                auto [ni, nj] = pos[cellNew];\n                auto [bi, bj] = pos[cellBest];\n                int manNew = abs(ni - si) + abs(nj - sj);\n                int manBest = abs(bi - si) + abs(bj - sj);\n                if (manNew < manBest) bestIdx = idx;\n            }\n        }\n\n        if (bestIdx == -1 || bestGain <= 0) {\n            // Safeguard: directly add some uncovered cell as vantage\n            int uncoveredId = -1;\n            for (int id = 0; id < r; ++id) {\n                if (!coveredCells[id]) {\n                    uncoveredId = id;\n                    break;\n                }\n            }\n            if (uncoveredId == -1) break; // should not happen\n            vantageCells.push_back(uncoveredId);\n            for (int x : coverageAll[uncoveredId]) {\n                if (!coveredCells[x]) {\n                    coveredCells[x] = 1;\n                    ++coveredCount;\n                }\n            }\n        } else {\n            selectCandidate(bestIdx);\n        }\n    }\n\n    // Deduplicate vantages (just in case)\n    sort(vantageCells.begin(), vantageCells.end());\n    vantageCells.erase(unique(vantageCells.begin(), vantageCells.end()), vantageCells.end());\n\n    // ---------- Eliminate redundant vantages using coverage frequencies ----------\n    {\n        int V = (int)vantageCells.size();\n        if (V > 0) {\n            vector<int> freq(r, 0);\n\n            // Base coverage from starting cell (we always start there)\n            for (int c : coverageAll[startId]) freq[c]++;\n\n            // Add contributions from all vantages\n            for (int v : vantageCells) {\n                for (int c : coverageAll[v]) freq[c]++;\n            }\n\n            // Process vantages in ascending order of coverage size (remove small ones first)\n            vector<int> orderIdx(V);\n            iota(orderIdx.begin(), orderIdx.end(), 0);\n            sort(orderIdx.begin(), orderIdx.end(), [&](int a, int b) {\n                return coverageAll[vantageCells[a]].size() < coverageAll[vantageCells[b]].size();\n            });\n\n            vector<char> removed(V, 0);\n            for (int idx : orderIdx) {\n                int v = vantageCells[idx];\n                bool canRemove = true;\n                for (int c : coverageAll[v]) {\n                    if (freq[c] <= 1) { // would leave some cell uncovered\n                        canRemove = false;\n                        break;\n                    }\n                }\n                if (!canRemove) continue;\n                // Remove this vantage\n                removed[idx] = 1;\n                for (int c : coverageAll[v]) {\n                    --freq[c];\n                }\n            }\n\n            vector<int> reduced;\n            reduced.reserve(V);\n            for (int i = 0; i < V; ++i) {\n                if (!removed[i]) reduced.push_back(vantageCells[i]);\n            }\n            vantageCells.swap(reduced);\n        }\n    }\n\n    // ---------- Dijkstra helpers ----------\n    vector<int> dist(r), prevv(r);\n\n    auto dijkstraToDest = [&](int src, int dest) {\n        fill(dist.begin(), dist.end(), INF);\n        fill(prevv.begin(), prevv.end(), -1);\n        priority_queue<pair<int,int>, vector<pair<int,int>>, greater<pair<int,int>>> pq;\n        dist[src] = 0;\n        pq.push({0, src});\n        while (!pq.empty()) {\n            auto [d, u] = pq.top();\n            pq.pop();\n            if (d != dist[u]) continue;\n            if (u == dest) break;\n            for (auto &e : G[u]) {\n                int v = e.to;\n                int nd = d + e.w;\n                if (nd < dist[v]) {\n                    dist[v] = nd;\n                    prevv[v] = u;\n                    pq.push({nd, v});\n                }\n            }\n        }\n    };\n\n    auto appendPath = [&](vector<int> &route, int src, int dest) {\n        if (src == dest) return;\n        dijkstraToDest(src, dest);\n        vector<int> tmp;\n        int x = dest;\n        while (x != src && x != -1) {\n            tmp.push_back(x);\n            x = prevv[x];\n        }\n        for (int i = (int)tmp.size() - 1; i >= 0; --i) {\n            route.push_back(tmp[i]);\n        }\n    };\n\n    auto dijkstraNearestTarget = [&](int src,\n                                     const vector<char> &isTarget,\n                                     const vector<char> &visitedTarget) -> int {\n        fill(dist.begin(), dist.end(), INF);\n        fill(prevv.begin(), prevv.end(), -1);\n        priority_queue<pair<int,int>, vector<pair<int,int>>, greater<pair<int,int>>> pq;\n        dist[src] = 0;\n        pq.push({0, src});\n        int target = -1;\n        while (!pq.empty()) {\n            auto [d, u] = pq.top();\n            pq.pop();\n            if (d != dist[u]) continue;\n            if (isTarget[u] && !visitedTarget[u]) {\n                target = u;\n                break;\n            }\n            for (auto &e : G[u]) {\n                int v = e.to;\n                int nd = d + e.w;\n                if (nd < dist[v]) {\n                    dist[v] = nd;\n                    prevv[v] = u;\n                    pq.push({nd, v});\n                }\n            }\n        }\n        return target;\n    };\n\n    // ---------- Route 1: Greedy nearest neighbor on vantages ----------\n    auto buildRouteGreedyNN = [&](const vector<int> &vantages) -> vector<int> {\n        vector<int> route;\n        route.reserve(2 * r + 5);\n\n        vector<char> isTarget(r, 0), visitedTarget(r, 0);\n        for (int id : vantages) isTarget[id] = 1;\n\n        int remainingTargets = 0;\n        for (int id : vantages) {\n            if (id == startId) {\n                visitedTarget[id] = 1;\n            } else {\n                ++remainingTargets;\n            }\n        }\n\n        route.push_back(startId);\n        int curr = startId;\n\n        while (remainingTargets > 0) {\n            int target = dijkstraNearestTarget(curr, isTarget, visitedTarget);\n            if (target == -1) break; // should not happen (connected component)\n\n            // Reconstruct path curr -> target using prevv from dijkstraNearestTarget\n            vector<int> tmp;\n            int x = target;\n            while (x != curr && x != -1) {\n                tmp.push_back(x);\n                x = prevv[x];\n            }\n            for (int i = (int)tmp.size() - 1; i >= 0; --i) {\n                int node = tmp[i];\n                route.push_back(node);\n                if (isTarget[node] && !visitedTarget[node]) {\n                    visitedTarget[node] = 1;\n                    --remainingTargets;\n                }\n            }\n            curr = target;\n        }\n\n        // Return to start\n        if (curr != startId) {\n            appendPath(route, curr, startId);\n        }\n        return route;\n    };\n\n    vector<int> routeNN = buildRouteGreedyNN(vantageCells);\n    long long timeNN = computeTravelTime(routeNN, cost);\n\n    // ---------- Route 2: TSP over vantages ----------\n    vector<int> routeTSP;\n    long long timeTSP = (1LL << 60);\n\n    if (!vantageCells.empty()) {\n        // Build node list: start + all vantages (without duplicating start)\n        vector<int> nodes;\n        nodes.reserve(vantageCells.size() + 1);\n        nodes.push_back(startId);\n        for (int v : vantageCells) {\n            if (v != startId) nodes.push_back(v);\n        }\n        int K = (int)nodes.size();\n\n        if (K >= 2) {\n            const int MAX_TSP_REAL_DIST_NODES = 320; // lowered threshold to avoid TLE\n            bool useRealDist = (K <= MAX_TSP_REAL_DIST_NODES);\n\n            vector<vector<int>> distNode(K, vector<int>(K, 0));\n\n            if (useRealDist) {\n                // Map cell id -> node index\n                vector<int> nodeIndex(r, -1);\n                for (int i = 0; i < K; ++i) nodeIndex[nodes[i]] = i;\n\n                // Dijkstra from each node to compute distances to all others\n                for (int i = 0; i < K; ++i) {\n                    int src = nodes[i];\n                    fill(dist.begin(), dist.end(), INF);\n                    dist[src] = 0;\n                    priority_queue<pair<int,int>, vector<pair<int,int>>, greater<pair<int,int>>> pq;\n                    pq.push({0, src});\n                    int remaining = K;\n                    while (!pq.empty() && remaining > 0) {\n                        auto [d, u] = pq.top();\n                        pq.pop();\n                        if (d != dist[u]) continue;\n                        int idxU = nodeIndex[u];\n                        if (idxU != -1) {\n                            distNode[i][idxU] = d;\n                            --remaining;\n                        }\n                        for (auto &e : G[u]) {\n                            int v = e.to;\n                            int nd = d + e.w;\n                            if (nd < dist[v]) {\n                                dist[v] = nd;\n                                pq.push({nd, v});\n                            }\n                        }\n                    }\n                }\n            } else {\n                // Approximate distances by Manhattan\n                for (int i = 0; i < K; ++i) {\n                    auto [xi, yi] = pos[nodes[i]];\n                    for (int j = i + 1; j < K; ++j) {\n                        auto [xj, yj] = pos[nodes[j]];\n                        int d = abs(xi - xj) + abs(yi - yj);\n                        distNode[i][j] = distNode[j][i] = d;\n                    }\n                }\n            }\n\n            // Initial route: nearest neighbor on distNode\n            vector<int> order(K);\n            vector<char> usedNode(K, 0);\n            order[0] = 0;\n            usedNode[0] = 1;\n            for (int t = 1; t < K; ++t) {\n                int prevIdx = order[t - 1];\n                int best = -1;\n                int bestD = INT_MAX;\n                for (int j = 0; j < K; ++j) {\n                    if (usedNode[j]) continue;\n                    int d = distNode[prevIdx][j];\n                    if (d < bestD) {\n                        bestD = d;\n                        best = j;\n                    }\n                }\n                if (best == -1) best = 0; // safety\n                order[t] = best;\n                usedNode[best] = 1;\n            }\n\n            // Local search: 2-opt + Or-opt, with multi-start kicks\n            auto tourLen = [&](const vector<int> &ord) -> long long {\n                long long len = 0;\n                for (int i = 0; i < K; ++i) {\n                    int a = ord[i];\n                    int b = ord[(i + 1) % K];\n                    len += distNode[a][b];\n                }\n                return len;\n            };\n\n            auto twoOptImprove = [&](vector<int> &ord) {\n                if (K < 3) return;\n                bool improved = true;\n                while (improved) {\n                    improved = false;\n                    for (int i = 1; i < K - 1 && !improved; ++i) {\n                        int a = ord[i - 1];\n                        int b = ord[i];\n                        for (int j = i + 1; j < K; ++j) {\n                            int c = ord[j];\n                            int d = (j + 1 < K ? ord[j + 1] : ord[0]);\n                            int curCost = distNode[a][b] + distNode[c][d];\n                            int newCost = distNode[a][c] + distNode[b][d];\n                            if (newCost < curCost) {\n                                reverse(ord.begin() + i, ord.begin() + j + 1);\n                                improved = true;\n                                break;\n                            }\n                        }\n                    }\n                }\n            };\n\n            auto orOptImprove = [&](vector<int> &ord) {\n                if (K < 3) return;\n                int maxIter = 4;\n                for (int iter = 0; iter < maxIter; ++iter) {\n                    bool anyImproved = false;\n                    for (int i = 1; i < K; ++i) {\n                        int prev = ord[i - 1];\n                        int cur = ord[i];\n                        int next = (i == K - 1 ? ord[0] : ord[i + 1]);\n                        for (int j = 0; j < K; ++j) {\n                            if (j == i || j == i - 1) continue;\n                            int a = ord[j];\n                            int b = (j == K - 1 ? ord[0] : ord[j + 1]);\n                            if (a == cur || b == cur) continue;\n\n                            int delta = 0;\n                            // Remove cur from between prev and next\n                            delta -= distNode[prev][cur] + distNode[cur][next] - distNode[prev][next];\n                            // Insert cur between a and b\n                            delta += distNode[a][cur] + distNode[cur][b] - distNode[a][b];\n\n                            if (delta < 0) {\n                                int node = cur;\n                                if (j < i) {\n                                    // remove at i\n                                    for (int k = i; k < K - 1; ++k) ord[k] = ord[k + 1];\n                                    // insert after j (position j+1)\n                                    for (int k = K - 1; k > j + 1; --k) ord[k] = ord[k - 1];\n                                    ord[j + 1] = node;\n                                } else { // j > i\n                                    // remove at i\n                                    for (int k = i; k < K - 1; ++k) ord[k] = ord[k + 1];\n                                    // after removal, original index j becomes j-1\n                                    int newJ = j - 1;\n                                    for (int k = K - 1; k > newJ + 1; --k) ord[k] = ord[k - 1];\n                                    ord[newJ + 1] = node;\n                                }\n                                anyImproved = true;\n                                goto NEXT_OR_ITER;\n                            }\n                        }\n                    }\n                NEXT_OR_ITER:\n                    if (!anyImproved) break;\n                }\n\n                // Final small 2-opt pass\n                twoOptImprove(ord);\n            };\n\n            auto localImprove = [&](vector<int> &ord) {\n                twoOptImprove(ord);\n                if (K <= 400) { // Or-opt for moderate K only\n                    orOptImprove(ord);\n                }\n            };\n\n            localImprove(order);\n\n            long long bestLen = tourLen(order);\n            vector<int> bestOrder = order;\n\n            // Multi-start with random \"kicks\"\n            static mt19937_64 rng(1234567ULL);\n            if (K >= 4) {\n                int kicks;\n                if (K >= 320) kicks = 4;\n                else if (K >= 160) kicks = 4;\n                else if (K >= 80) kicks = 3;\n                else if (K >= 40) kicks = 3;\n                else kicks = 2;\n\n                auto randomKick = [&](vector<int> &ord) {\n                    if (K < 4) return;\n                    int a = 1 + (int)(rng() % (K - 3));\n                    int b = a + 1 + (int)(rng() % (K - 2 - a));\n                    int c = b + 1 + (int)(rng() % (K - 1 - b));\n                    vector<int> newOrd;\n                    newOrd.reserve(K);\n                    for (int i = 0; i < a; ++i) newOrd.push_back(ord[i]);      // S1\n                    for (int i = b; i < c; ++i) newOrd.push_back(ord[i]);      // S3\n                    for (int i = a; i < b; ++i) newOrd.push_back(ord[i]);      // S2\n                    for (int i = c; i < K; ++i) newOrd.push_back(ord[i]);      // S4\n                    ord.swap(newOrd);\n                };\n\n                for (int it = 0; it < kicks; ++it) {\n                    vector<int> tmp = bestOrder;\n                    randomKick(tmp);\n                    localImprove(tmp);\n                    long long len = tourLen(tmp);\n                    if (len < bestLen) {\n                        bestLen = len;\n                        bestOrder.swap(tmp);\n                    }\n                }\n                order.swap(bestOrder);\n            }\n\n            // Build actual route following this order (0..K-1), starting at startId\n            routeTSP.reserve(2 * r + 5);\n            routeTSP.push_back(startId);\n            int curr = startId;\n            for (int idxPos = 1; idxPos < K; ++idxPos) {\n                int nodeIdx = order[idxPos];\n                int dest = nodes[nodeIdx];\n                if (dest == curr) continue;\n                appendPath(routeTSP, curr, dest);\n                curr = dest;\n            }\n            if (curr != startId) {\n                appendPath(routeTSP, curr, startId);\n            }\n            timeTSP = computeTravelTime(routeTSP, cost);\n        }\n    }\n\n    // ---------- Choose the best route among: DFS fallback, NN, TSP ----------\n    vector<int> bestRoute = fallbackRoute;\n    long long bestTime = fallbackTime;\n\n    if (!routeNN.empty() && timeNN < bestTime) {\n        bestTime = timeNN;\n        bestRoute = std::move(routeNN);\n    }\n    if (!routeTSP.empty() && timeTSP < bestTime) {\n        bestTime = timeTSP;\n        bestRoute = std::move(routeTSP);\n    }\n\n    // If route has no movement, add a tiny loop to avoid t=0\n    if ((int)bestRoute.size() == 1) {\n        int u = startId;\n        int v = -1;\n        for (auto &e : G[u]) {\n            v = e.to;\n            break;\n        }\n        if (v != -1) {\n            bestRoute.push_back(v);\n            bestRoute.push_back(u);\n        }\n    }\n\n    // ---------- Convert node sequence to direction string ----------\n    string ans;\n    ans.reserve(bestRoute.size());\n    for (int i = 1; i < (int)bestRoute.size(); ++i) {\n        auto [i1, j1] = pos[bestRoute[i-1]];\n        auto [i2, j2] = pos[bestRoute[i]];\n        if (i2 == i1 - 1 && j2 == j1) ans.push_back('U');\n        else if (i2 == i1 + 1 && j2 == j1) ans.push_back('D');\n        else if (j2 == j1 - 1 && i2 == i1) ans.push_back('L');\n        else if (j2 == j1 + 1 && i2 == i1) ans.push_back('R');\n        else {\n            // Should not happen with valid shortest paths\n        }\n    }\n\n    cout << ans << '\\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    if (!(cin >> N >> M >> K >> R)) return 0;\n\n    // Task requirements d[i][k]\n    vector<vector<int>> d(N, vector<int>(K));\n    for (int i = 0; i < N; ++i) {\n        for (int k = 0; k < K; ++k) cin >> d[i][k];\n    }\n\n    // Dependencies: u -> v\n    vector<vector<int>> out(N);\n    vector<int> indeg(N, 0);\n    for (int e = 0; e < R; ++e) {\n        int u, v;\n        cin >> u >> v;\n        --u; --v;\n        out[u].push_back(v);\n        indeg[v]++;\n    }\n\n    // Precompute depth-from-end (longest path length to any sink)\n    vector<int> depth(N, 0);\n    for (int i = N - 1; i >= 0; --i) {\n        int best = 0;\n        for (int v : out[i]) {\n            best = max(best, depth[v] + 1);\n        }\n        depth[i] = best;\n    }\n\n    // Precompute simple difficulty measure (L1 norm)\n    vector<int> diffL1(N, 0);\n    for (int i = 0; i < N; ++i) {\n        int s = 0;\n        for (int k = 0; k < K; ++k) s += d[i][k];\n        diffL1[i] = s;\n    }\n\n    // Task states\n    const int NOT_STARTED = 0;\n    const int IN_PROGRESS = 1;\n    const int DONE = 2;\n    vector<int> state(N, NOT_STARTED);\n    vector<int> degRem = indeg;\n    int tasksDone = 0;\n\n    // Worker states\n    vector<int> curTask(M, -1);\n    vector<int> startDay(M, -1);\n\n    // Worker skill vectors s_j[k]\n    vector<vector<double>> skill(M, vector<double>(K, 0.0));\n    // History of (task, w_obs) per worker for fitting\n    vector<vector<int>> histTasks(M);\n    vector<vector<double>> histW(M);\n\n    const int    FIT_ITERS = 5;\n    const double LR        = 0.05;\n    const double SKILL_MAX = 100.0;\n\n    // Fitting function for one worker (small batch GD over its history)\n    auto fitWorker = [&](int j) {\n        auto &s  = skill[j];\n        auto &ht = histTasks[j];\n        auto &hw = histW[j];\n        int S = (int)ht.size();\n        if (S == 0) return;\n        for (int it = 0; it < FIT_ITERS; ++it) {\n            for (int idx = 0; idx < S; ++idx) {\n                int ti = ht[idx];\n                double w_obs = hw[idx];\n\n                // Compute w_pred = sum_k max(0, d[ti][k] - s[k])\n                const auto &dv = d[ti];\n                double w_pred = 0.0;\n                for (int k = 0; k < K; ++k) {\n                    double diff = (double)dv[k] - s[k];\n                    if (diff > 0.0) w_pred += diff;\n                }\n\n                double e = w_pred - w_obs;\n                if (e == 0.0) continue;\n                double step = LR * e;\n\n                // Gradient: for dims where d > s, s[k] += step\n                for (int k = 0; k < K; ++k) {\n                    if ((double)dv[k] > s[k]) {\n                        s[k] += step;\n                        if (s[k] < 0.0) s[k] = 0.0;\n                        if (s[k] > SKILL_MAX) s[k] = SKILL_MAX;\n                    }\n                }\n            }\n        }\n    };\n\n    int day = 0;\n    const int MAX_CAND = 400;  // number of candidate tasks per day to consider\n\n    while (true) {\n        day++;\n\n        // Compute available tasks (not started and all prerequisites done)\n        vector<int> available;\n        if (tasksDone < N) {\n            available.reserve(N);\n            for (int i = 0; i < N; ++i) {\n                if (state[i] == NOT_STARTED && degRem[i] == 0) {\n                    available.push_back(i);\n                }\n            }\n        }\n\n        // Collect free workers\n        vector<int> freeWorkers;\n        freeWorkers.reserve(M);\n        for (int j = 0; j < M; ++j) {\n            if (curTask[j] == -1) freeWorkers.push_back(j);\n        }\n\n        vector<pair<int,int>> assigns; // (worker, task)\n\n        if (!freeWorkers.empty() && !available.empty()) {\n            // Sort available tasks by priority: depth desc, diffL1 desc, id asc\n            auto cmpTask = [&](int x, int y) {\n                if (depth[x] != depth[y]) return depth[x] > depth[y];\n                if (diffL1[x] != diffL1[y]) return diffL1[x] > diffL1[y];\n                return x < y;\n            };\n\n            int sz = (int)available.size();\n            if (sz > MAX_CAND) {\n                int limit = MAX_CAND;\n                partial_sort(available.begin(), available.begin() + limit,\n                             available.end(), cmpTask);\n                available.resize(limit);\n                sz = limit;\n            } else {\n                sort(available.begin(), available.end(), cmpTask);\n            }\n\n            // Build all (worker, task) options with predicted cost = t_pred\n            struct Option {\n                double cost;\n                int w;\n                int task;\n            };\n            vector<Option> options;\n            options.reserve(freeWorkers.size() * sz);\n\n            for (int widx = 0; widx < (int)freeWorkers.size(); ++widx) {\n                int j = freeWorkers[widx];\n                const auto &sj = skill[j];\n                for (int tidx = 0; tidx < sz; ++tidx) {\n                    int ti = available[tidx];\n                    const auto &dv = d[ti];\n                    double w_pred = 0.0;\n                    for (int k = 0; k < K; ++k) {\n                        double diff = (double)dv[k] - sj[k];\n                        if (diff > 0.0) w_pred += diff;\n                    }\n                    if (w_pred < 0.0) w_pred = 0.0;\n                    double t_pred = (w_pred < 1.0 ? 1.0 : w_pred);\n                    options.push_back(Option{t_pred, j, ti});\n                }\n            }\n\n            sort(options.begin(), options.end(),\n                 [](const Option &a, const Option &b) {\n                     if (a.cost != b.cost) return a.cost < b.cost;\n                     if (a.w != b.w) return a.w < b.w;\n                     return a.task < b.task;\n                 });\n\n            vector<char> workerUsed(M, 0);\n            vector<char> taskUsed(N, 0);\n            assigns.reserve(freeWorkers.size());\n\n            for (const auto &opt : options) {\n                if ((int)assigns.size() == (int)freeWorkers.size()) break;\n                int j  = opt.w;\n                int ti = opt.task;\n                if (workerUsed[j] || taskUsed[ti]) continue;\n                workerUsed[j] = 1;\n                taskUsed[ti]  = 1;\n                assigns.emplace_back(j, ti);\n            }\n        }\n\n        // Output assignments and update worker/task states\n        int m = (int)assigns.size();\n        cout << m;\n        for (auto &p : assigns) {\n            int j  = p.first;\n            int ti = p.second;\n            cout << ' ' << (j + 1) << ' ' << (ti + 1);\n            curTask[j] = ti;\n            startDay[j] = day;\n            state[ti] = IN_PROGRESS;\n        }\n        cout << '\\n' << flush;\n\n        // Read feedback: list of finished workers\n        int n;\n        if (!(cin >> n)) return 0;\n        if (n == -1) break;\n\n        vector<int> finishedWorkers;\n        finishedWorkers.reserve(n);\n        for (int i = 0; i < n; ++i) {\n            int f;\n            cin >> f;\n            finishedWorkers.push_back(f - 1); // zero-based\n        }\n\n        // Process completions\n        for (int idx = 0; idx < n; ++idx) {\n            int j = finishedWorkers[idx];\n            int ti = (j >= 0 && j < M) ? curTask[j] : -1;\n            if (ti < 0) continue;\n\n            int st = startDay[j];\n            if (st < 1) st = day;  // safety\n            int t_obs = day - st + 1;\n            if (t_obs < 1) t_obs = 1;\n            int w_obs_int = t_obs - 1;\n            if (w_obs_int < 0) w_obs_int = 0;\n            double w_obs = (double)w_obs_int;\n\n            // Record sample for worker j\n            histTasks[j].push_back(ti);\n            histW[j].push_back(w_obs);\n            // Re-fit worker j's skill vector\n            fitWorker(j);\n\n            // Mark task completion\n            state[ti] = DONE;\n            tasksDone++;\n            curTask[j] = -1;\n            startDay[j] = -1;\n\n            // Update indegrees of children\n            for (int v : out[ti]) {\n                degRem[v]--;\n            }\n        }\n    }\n\n    return 0;\n}","ahc006":"#include <bits/stdc++.h>\nusing namespace std;\n\n// ---------------------------------------------------------------\n// Types and globals\n// ---------------------------------------------------------------\n\nstruct TourResult {\n    vector<int> tour; // sequence of node indices, starts and ends with 0 (office)\n    int cost;\n};\n\nstatic int distMat[52][52];   // for TSP up to 51 nodes (0..50)\nstatic int nodeX[52], nodeY[52];\n\nconst int OFFICE_X = 400;\nconst int OFFICE_Y = 400;\n\n// RNG: simple xorshift\nstruct XorShift {\n    uint64_t x;\n    XorShift(uint64_t seed = 88172645463393265ULL) { x = seed; }\n    uint64_t next_u64() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return x;\n    }\n    uint32_t next_u32() { return (uint32_t)next_u64(); }\n    uint32_t next_uint(uint32_t mod) { return (uint32_t)(next_u64() % mod); }\n    double next_double() {\n        return (next_u64() >> 11) * (1.0 / (1ULL << 53));\n    }\n};\n\n// Manhattan distance\ninline int manhattan(int x1, int y1, int x2, int y2) {\n    return abs(x1 - x2) + abs(y1 - y2);\n}\n\n// ---------------------------------------------------------------\n// TSP solver: nearest neighbor + 2-opt\n// Points: X[i], Y[i] for i=0..m-1 correspond to nodes 1..m.\n// Node 0 is the office at (400,400).\n// ---------------------------------------------------------------\nTourResult solve_tsp_points(const vector<int>& X, const vector<int>& Y) {\n    int m = (int)X.size();       // number of non-office nodes (<=50)\n    int nNodes = m + 1;          // nodes 0..m\n\n    // Build node coordinates (0: office)\n    nodeX[0] = OFFICE_X;\n    nodeY[0] = OFFICE_Y;\n    for (int i = 1; i <= m; ++i) {\n        nodeX[i] = X[i - 1];\n        nodeY[i] = Y[i - 1];\n    }\n\n    // Distance matrix\n    for (int i = 0; i <= m; ++i) {\n        for (int j = 0; j <= m; ++j) {\n            distMat[i][j] = manhattan(nodeX[i], nodeY[i], nodeX[j], nodeY[j]);\n        }\n    }\n\n    // Nearest neighbor construction, start at office (0)\n    vector<int> tour;\n    tour.reserve(nNodes + 1);\n    vector<char> used(nNodes, 0);\n    int cur = 0;\n    used[0] = 1;\n    tour.push_back(0);\n    for (int step = 0; step < m; ++step) {\n        int best = -1;\n        int bestDist = INT_MAX;\n        for (int v = 1; v <= m; ++v) {\n            if (!used[v]) {\n                int d = distMat[cur][v];\n                if (d < bestDist) {\n                    bestDist = d;\n                    best = v;\n                }\n            }\n        }\n        used[best] = 1;\n        tour.push_back(best);\n        cur = best;\n    }\n    tour.push_back(0); // return to office\n\n    // 2-opt improvement with fixed endpoints at office\n    int M = (int)tour.size(); // should be m+2\n    bool improved = true;\n    while (improved) {\n        improved = false;\n        for (int i = 1; i <= M - 3; ++i) {\n            int a = tour[i - 1];\n            int b = tour[i];\n            for (int k = i + 1; k <= M - 2; ++k) {\n                int c = tour[k];\n                int d = tour[k + 1];\n                int delta = distMat[a][c] + distMat[b][d]\n                          - distMat[a][b] - distMat[c][d];\n                if (delta < 0) {\n                    reverse(tour.begin() + i, tour.begin() + k + 1);\n                    improved = true;\n                    goto next_iteration;\n                }\n            }\n        }\n        next_iteration:;\n    }\n\n    int cost = 0;\n    for (int i = 0; i < M - 1; ++i) {\n        cost += distMat[tour[i]][tour[i + 1]];\n    }\n\n    TourResult res;\n    res.tour = move(tour);\n    res.cost = cost;\n    return res;\n}\n\n// ---------------------------------------------------------------\n// Evaluate a selection of orders:\n//   selection: vector of indices (0-based) of orders.\n//   Returns total cost of 0->restaurants->0 + 0->destinations->0,\n//   and stores the restaurant and destination tours.\n// ---------------------------------------------------------------\nint evaluate_selection(\n    const vector<int>& selection,\n    const vector<int>& a, const vector<int>& b,\n    const vector<int>& c, const vector<int>& d,\n    vector<int>& outRtour,\n    vector<int>& outDtour\n) {\n    int m = (int)selection.size(); // 50\n    vector<int> XR(m), YR(m), XD(m), YD(m);\n    for (int i = 0; i < m; ++i) {\n        int idx = selection[i];\n        XR[i] = a[idx];\n        YR[i] = b[idx];\n        XD[i] = c[idx];\n        YD[i] = d[idx];\n    }\n\n    TourResult rRes = solve_tsp_points(XR, YR);\n    TourResult dRes = solve_tsp_points(XD, YD);\n\n    outRtour = rRes.tour;\n    outDtour = dRes.tour;\n\n    return rRes.cost + dRes.cost;\n}\n\n// ---------------------------------------------------------------\n// Compute cost of a pickup-delivery route:\n// kind[pos]: 0=pickup, 1=delivery, 2=office (for pos=0 and last)\n// oid[pos]: local order id (0..M-1) if kind is 0 or 1\n// ---------------------------------------------------------------\nint compute_route_cost(\n    int M,\n    const vector<int>& kind,\n    const vector<int>& oid,\n    const vector<int>& rx,\n    const vector<int>& ry,\n    const vector<int>& dx,\n    const vector<int>& dy\n) {\n    int routeSize = 2 * M + 2; // positions 0..routeSize-1\n    auto getCoord = [&](int pos, int &x, int &y) {\n        if (pos == 0 || pos == routeSize - 1) {\n            x = OFFICE_X; y = OFFICE_Y;\n        } else if (kind[pos] == 0) { // pickup -> restaurant\n            int id = oid[pos];\n            x = rx[id]; y = ry[id];\n        } else { // delivery\n            int id = oid[pos];\n            x = dx[id]; y = dy[id];\n        }\n    };\n\n    int total = 0;\n    int px, py;\n    getCoord(0, px, py);\n    for (int pos = 1; pos < routeSize; ++pos) {\n        int cx, cy;\n        getCoord(pos, cx, cy);\n        total += manhattan(px, py, cx, cy);\n        px = cx; py = cy;\n    }\n    return total;\n}\n\n// ---------------------------------------------------------------\n// Main\n// ---------------------------------------------------------------\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    const int N = 1000;\n    vector<int> a(N), b(N), c(N), d(N);\n    for (int i = 0; i < N; ++i) {\n        if (!(cin >> a[i] >> b[i] >> c[i] >> d[i])) {\n            return 0;\n        }\n    }\n\n    auto globalStart = chrono::steady_clock::now();\n    const double TOTAL_LIMIT = 1.95;      // total time limit for safety\n    const double SELECTION_LIMIT = 1.75;  // time for selection phase\n\n    XorShift rng(\n        (uint64_t)chrono::high_resolution_clock::now()\n            .time_since_epoch().count()\n    );\n\n    // -----------------------------------------------------------\n    // Initial selection by single-trip heuristic\n    // -----------------------------------------------------------\n    vector<int> single_trip(N);\n    for (int i = 0; i < N; ++i) {\n        int d0R = manhattan(OFFICE_X, OFFICE_Y, a[i], b[i]);\n        int dRD = manhattan(a[i], b[i], c[i], d[i]);\n        int dD0 = manhattan(c[i], d[i], OFFICE_X, OFFICE_Y);\n        single_trip[i] = d0R + dRD + dD0;\n    }\n\n    vector<int> idx(N);\n    iota(idx.begin(), idx.end(), 0);\n    sort(idx.begin(), idx.end(), [&](int i, int j) {\n        return single_trip[i] < single_trip[j];\n    });\n\n    const int M = 50;\n    vector<int> currentSel(M);\n    for (int i = 0; i < M; ++i) currentSel[i] = idx[i];\n\n    vector<char> inCurrent(N, 0);\n    for (int i = 0; i < M; ++i) inCurrent[currentSel[i]] = 1;\n\n    // Evaluate initial selection\n    vector<int> bestRtour, bestDtour;\n    vector<int> tmpRtour, tmpDtour;\n    int currentCost = evaluate_selection(currentSel, a, b, c, d, tmpRtour, tmpDtour);\n\n    vector<int> bestSel = currentSel;\n    bestRtour = tmpRtour;\n    bestDtour = tmpDtour;\n    int bestCost = currentCost;\n\n    // -----------------------------------------------------------\n    // Selection phase: greedy hill-climbing on the set of 50 orders\n    // -----------------------------------------------------------\n    while (true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - globalStart).count();\n        if (elapsed > SELECTION_LIMIT) break;\n\n        // Pick a random order to remove\n        int posOut = (int)rng.next_uint(M);\n        int outIdx = currentSel[posOut];\n\n        // Pick a random order to insert (not currently selected)\n        int inIdx;\n        do {\n            inIdx = (int)rng.next_uint(N);\n        } while (inCurrent[inIdx]);\n\n        vector<int> candidateSel = currentSel;\n        candidateSel[posOut] = inIdx;\n\n        int candCost = evaluate_selection(candidateSel, a, b, c, d, tmpRtour, tmpDtour);\n\n        // Greedy acceptance\n        if (candCost <= currentCost) {\n            currentSel.swap(candidateSel);\n            currentCost = candCost;\n            inCurrent[outIdx] = 0;\n            inCurrent[inIdx] = 1;\n        }\n\n        // Track global best\n        if (candCost < bestCost) {\n            bestCost = candCost;\n            bestSel = candidateSel;\n            bestRtour = tmpRtour;\n            bestDtour = tmpDtour;\n        }\n    }\n\n    // -----------------------------------------------------------\n    // Build local data for best selection\n    // -----------------------------------------------------------\n    vector<int> globalOfLocal(M);\n    for (int i = 0; i < M; ++i) {\n        globalOfLocal[i] = bestSel[i]; // map local id -> global order index\n    }\n\n    vector<int> rx(M), ry(M), dx(M), dy(M);\n    for (int i = 0; i < M; ++i) {\n        int gi = globalOfLocal[i];\n        rx[i] = a[gi];\n        ry[i] = b[gi];\n        dx[i] = c[gi];\n        dy[i] = d[gi];\n    }\n\n    // Extract sequences of local order ids from TSP tours\n    vector<int> seqP; seqP.reserve(M);\n    vector<int> seqD; seqD.reserve(M);\n\n    // Restaurants tour: [0, r1, ..., rM, 0]\n    for (int i = 1; i < (int)bestRtour.size() - 1; ++i) {\n        int node = bestRtour[i]; // 1..M\n        int local = node - 1;\n        seqP.push_back(local);\n    }\n    // Destinations tour: [0, d1, ..., dM, 0]\n    for (int i = 1; i < (int)bestDtour.size() - 1; ++i) {\n        int node = bestDtour[i];\n        int local = node - 1;\n        seqD.push_back(local);\n    }\n\n    if ((int)seqP.size() != M || (int)seqD.size() != M) {\n        // Fallback: trivial order 0..M-1 (should not normally happen)\n        seqP.clear(); seqD.clear();\n        for (int i = 0; i < M; ++i) {\n            seqP.push_back(i);\n            seqD.push_back(i);\n        }\n    }\n\n    // -----------------------------------------------------------\n    // Build baseline pickup-delivery route: 0, P..., D..., 0\n    // -----------------------------------------------------------\n    int routeSize = 2 * M + 2; // positions 0..routeSize-1\n    vector<int> kind(routeSize), oid(routeSize); // kind: 0=pickup,1=delivery,2=office\n    vector<int> posP(M), posD(M);\n\n    kind[0] = kind[routeSize - 1] = 2;\n    oid[0] = oid[routeSize - 1] = -1;\n\n    // pickups\n    for (int k = 0; k < M; ++k) {\n        int pos = 1 + k;\n        int local = seqP[k];\n        kind[pos] = 0;\n        oid[pos] = local;\n        posP[local] = pos;\n    }\n    // deliveries\n    for (int k = 0; k < M; ++k) {\n        int pos = 1 + M + k;\n        int local = seqD[k];\n        kind[pos] = 1;\n        oid[pos] = local;\n        posD[local] = pos;\n    }\n\n    // Baseline route cost: 0 -> all pickups -> all deliveries -> 0\n    int baselineCost = compute_route_cost(M, kind, oid, rx, ry, dx, dy);\n    vector<int> baselineKind = kind;\n    vector<int> baselineOid = oid;\n\n    // -----------------------------------------------------------\n    // Simulated Annealing on pickup-delivery sequence\n    // -----------------------------------------------------------\n    int currentRouteCost = baselineCost;\n    int bestRouteCost = baselineCost;\n    vector<int> bestKind = kind;\n    vector<int> bestOid = oid;\n\n    auto saStart = chrono::steady_clock::now();\n    double elapsed = chrono::duration<double>(saStart - globalStart).count();\n    double remaining = TOTAL_LIMIT - elapsed;\n\n    if (remaining > 0.05) {\n        const int MAX_ITER = 400000;\n        const int CHECK_INTERVAL = 2048;\n        const double T0 = 2000.0;\n        const double T1 = 2.0;\n\n        for (int it = 0; it < MAX_ITER; ++it) {\n            if ((it & (CHECK_INTERVAL - 1)) == 0) {\n                auto now = chrono::steady_clock::now();\n                double e = chrono::duration<double>(now - globalStart).count();\n                if (e > TOTAL_LIMIT) break;\n            }\n\n            int x = 1 + (int)rng.next_uint(2 * M); // 1..2M\n            int y = 1 + (int)rng.next_uint(2 * M);\n            if (x == y) continue;\n            if (x > y) swap(x, y);\n\n            int kx = kind[x];\n            int ky = kind[y];\n            int oid1 = oid[x];\n            int oid2 = oid[y];\n\n            // never touch offices\n            if (kx == 2 || ky == 2) continue;\n\n            // don't swap pickup and delivery of the same order\n            if (oid1 == oid2) continue;\n\n            // Precedence check\n            bool ok = true;\n            // Order 1\n            int p1 = posP[oid1];\n            int d1 = posD[oid1];\n            if (kx == 0) { // pickup moves to y\n                if (y >= d1) ok = false;\n            } else { // delivery moves to y\n                if (p1 >= y) ok = false;\n            }\n            if (!ok) continue;\n\n            // Order 2\n            int p2 = posP[oid2];\n            int d2 = posD[oid2];\n            if (ky == 0) { // pickup moves to x\n                if (x >= d2) ok = false;\n            } else { // delivery moves to x\n                if (p2 >= x) ok = false;\n            }\n            if (!ok) continue;\n\n            // Temperature schedule\n            double t = (double)it / MAX_ITER;\n            if (t > 1.0) t = 1.0;\n            double T = T0 + (T1 - T0) * t;\n\n            // Helper to get coordinates at a given position (before swap)\n            auto getCoordPos = [&](int pos, int &X, int &Y) {\n                if (pos == 0 || pos == routeSize - 1) {\n                    X = OFFICE_X; Y = OFFICE_Y;\n                } else if (kind[pos] == 0) {\n                    int id = oid[pos];\n                    X = rx[id]; Y = ry[id];\n                } else { // delivery\n                    int id = oid[pos];\n                    X = dx[id]; Y = dy[id];\n                }\n            };\n\n            int deltaCost = 0;\n            if (y == x + 1) {\n                // Adjacent swap: positions x and y=x+1\n                int Ax, Ay, Bx, By, Cx, Cy, Dx_, Dy_;\n                int xPrev = x - 1;\n                int yNext = y + 1;\n\n                getCoordPos(xPrev, Ax, Ay);\n                getCoordPos(x, Bx, By);   // event1\n                getCoordPos(y, Cx, Cy);   // event2\n                getCoordPos(yNext, Dx_, Dy_);\n\n                int before = manhattan(Ax, Ay, Bx, By)\n                           + manhattan(Bx, By, Cx, Cy)\n                           + manhattan(Cx, Cy, Dx_, Dy_);\n\n                int B2x, B2y, C2x, C2y;\n                // New B (at x) is event2\n                if (ky == 0) {\n                    int id = oid2;\n                    B2x = rx[id]; B2y = ry[id];\n                } else {\n                    int id = oid2;\n                    B2x = dx[id]; B2y = dy[id];\n                }\n                // New C (at y) is event1\n                if (kx == 0) {\n                    int id = oid1;\n                    C2x = rx[id]; C2y = ry[id];\n                } else {\n                    int id = oid1;\n                    C2x = dx[id]; C2y = dy[id];\n                }\n\n                int after = manhattan(Ax, Ay, B2x, B2y)\n                          + manhattan(B2x, B2y, C2x, C2y)\n                          + manhattan(C2x, C2y, Dx_, Dy_);\n\n                deltaCost = after - before;\n            } else {\n                // Non-adjacent swap\n                int xPrev = x - 1;\n                int xNext = x + 1;\n                int yPrev = y - 1;\n                int yNext = y + 1;\n\n                int Ax, Ay, Bx, By, Cx, Cy;\n                int Dx_, Dy_, Ex, Ey, Fx, Fy;\n\n                getCoordPos(xPrev, Ax, Ay);\n                getCoordPos(x, Bx, By);\n                getCoordPos(xNext, Cx, Cy);\n\n                getCoordPos(yPrev, Dx_, Dy_);\n                getCoordPos(y, Ex, Ey);\n                getCoordPos(yNext, Fx, Fy);\n\n                int before = manhattan(Ax, Ay, Bx, By)\n                           + manhattan(Bx, By, Cx, Cy)\n                           + manhattan(Dx_, Dy_, Ex, Ey)\n                           + manhattan(Ex, Ey, Fx, Fy);\n\n                int B2x, B2y, E2x, E2y;\n                // New node at x (B2) is event2\n                if (ky == 0) {\n                    int id = oid2;\n                    B2x = rx[id]; B2y = ry[id];\n                } else {\n                    int id = oid2;\n                    B2x = dx[id]; B2y = dy[id];\n                }\n                // New node at y (E2) is event1\n                if (kx == 0) {\n                    int id = oid1;\n                    E2x = rx[id]; E2y = ry[id];\n                } else {\n                    int id = oid1;\n                    E2x = dx[id]; E2y = dy[id];\n                }\n\n                int after = manhattan(Ax, Ay, B2x, B2y)\n                          + manhattan(B2x, B2y, Cx, Cy)\n                          + manhattan(Dx_, Dy_, E2x, E2y)\n                          + manhattan(E2x, E2y, Fx, Fy);\n\n                deltaCost = after - before;\n            }\n\n            if (deltaCost <= 0) {\n                // Always accept improvements\n            } else {\n                double prob = exp(- (double)deltaCost / T);\n                if (rng.next_double() >= prob) {\n                    continue; // reject\n                }\n            }\n\n            // Accept move\n            currentRouteCost += deltaCost;\n\n            // Update positions and route\n            swap(kind[x], kind[y]);\n            swap(oid[x], oid[y]);\n\n            // Update posP/posD for affected orders using old kinds (kx, ky)\n            if (kx == 0) posP[oid1] = y; else posD[oid1] = y;\n            if (ky == 0) posP[oid2] = x; else posD[oid2] = x;\n\n            if (currentRouteCost < bestRouteCost) {\n                bestRouteCost = currentRouteCost;\n                bestKind = kind;\n                bestOid = oid;\n            }\n        }\n    }\n\n    // Recompute exact costs and choose the better of baseline vs SA\n    int saCost = compute_route_cost(M, bestKind, bestOid, rx, ry, dx, dy);\n    vector<int> finalKind, finalOid;\n    int finalCost;\n    if (saCost < baselineCost) {\n        finalKind = bestKind;\n        finalOid = bestOid;\n        finalCost = saCost;\n    } else {\n        finalKind = baselineKind;\n        finalOid = baselineOid;\n        finalCost = baselineCost;\n    }\n\n    // -----------------------------------------------------------\n    // Final greedy local improvement on the route (only improving swaps)\n    // -----------------------------------------------------------\n    {\n        // Recompute posP and posD for final route\n        vector<int> posP2(M), posD2(M);\n        for (int pos = 1; pos <= 2 * M; ++pos) {\n            if (finalKind[pos] == 0) {\n                posP2[finalOid[pos]] = pos;\n            } else if (finalKind[pos] == 1) {\n                posD2[finalOid[pos]] = pos;\n            }\n        }\n\n        int routeCost = finalCost;\n        bool improved = true;\n        while (improved) {\n            improved = false;\n            for (int x = 1; x <= 2 * M; ++x) {\n                auto now = chrono::steady_clock::now();\n                double e = chrono::duration<double>(now - globalStart).count();\n                if (e > TOTAL_LIMIT) goto end_greedy_improve;\n\n                for (int y = x + 1; y <= 2 * M; ++y) {\n                    int kx = finalKind[x];\n                    int ky = finalKind[y];\n                    int oid1 = finalOid[x];\n                    int oid2 = finalOid[y];\n\n                    // skip offices\n                    if (kx == 2 || ky == 2) continue;\n                    // same order\n                    if (oid1 == oid2) continue;\n\n                    // precedence check\n                    bool ok = true;\n                    // order 1\n                    int p1 = posP2[oid1];\n                    int d1 = posD2[oid1];\n                    if (kx == 0) { // pickup moves to y\n                        if (y >= d1) ok = false;\n                    } else { // delivery moves to y\n                        if (p1 >= y) ok = false;\n                    }\n                    if (!ok) continue;\n                    // order 2\n                    int p2 = posP2[oid2];\n                    int d2 = posD2[oid2];\n                    if (ky == 0) { // pickup moves to x\n                        if (x >= d2) ok = false;\n                    } else { // delivery moves to x\n                        if (p2 >= x) ok = false;\n                    }\n                    if (!ok) continue;\n\n                    // delta cost\n                    auto getCoordPosFinal = [&](int pos, int &X, int &Y) {\n                        if (pos == 0 || pos == routeSize - 1) {\n                            X = OFFICE_X; Y = OFFICE_Y;\n                        } else if (finalKind[pos] == 0) {\n                            int id = finalOid[pos];\n                            X = rx[id]; Y = ry[id];\n                        } else {\n                            int id = finalOid[pos];\n                            X = dx[id]; Y = dy[id];\n                        }\n                    };\n\n                    int deltaCost = 0;\n                    if (y == x + 1) {\n                        int Ax, Ay, Bx, By, Cx, Cy, Dx_, Dy_;\n                        int xPrev = x - 1;\n                        int yNext = y + 1;\n\n                        getCoordPosFinal(xPrev, Ax, Ay);\n                        getCoordPosFinal(x, Bx, By);\n                        getCoordPosFinal(y, Cx, Cy);\n                        getCoordPosFinal(yNext, Dx_, Dy_);\n\n                        int before = manhattan(Ax, Ay, Bx, By)\n                                   + manhattan(Bx, By, Cx, Cy)\n                                   + manhattan(Cx, Cy, Dx_, Dy_);\n\n                        int B2x, B2y, C2x, C2y;\n                        // new B at x is event2\n                        if (ky == 0) {\n                            int id = oid2;\n                            B2x = rx[id]; B2y = ry[id];\n                        } else {\n                            int id = oid2;\n                            B2x = dx[id]; B2y = dy[id];\n                        }\n                        // new C at y is event1\n                        if (kx == 0) {\n                            int id = oid1;\n                            C2x = rx[id]; C2y = ry[id];\n                        } else {\n                            int id = oid1;\n                            C2x = dx[id]; C2y = dy[id];\n                        }\n\n                        int after = manhattan(Ax, Ay, B2x, B2y)\n                                  + manhattan(B2x, B2y, C2x, C2y)\n                                  + manhattan(C2x, C2y, Dx_, Dy_);\n\n                        deltaCost = after - before;\n                    } else {\n                        int xPrev = x - 1;\n                        int xNext = x + 1;\n                        int yPrev = y - 1;\n                        int yNext = y + 1;\n\n                        int Ax, Ay, Bx, By, Cx, Cy;\n                        int Dx_, Dy_, Ex, Ey, Fx, Fy;\n\n                        getCoordPosFinal(xPrev, Ax, Ay);\n                        getCoordPosFinal(x, Bx, By);\n                        getCoordPosFinal(xNext, Cx, Cy);\n\n                        getCoordPosFinal(yPrev, Dx_, Dy_);\n                        getCoordPosFinal(y, Ex, Ey);\n                        getCoordPosFinal(yNext, Fx, Fy);\n\n                        int before = manhattan(Ax, Ay, Bx, By)\n                                   + manhattan(Bx, By, Cx, Cy)\n                                   + manhattan(Dx_, Dy_, Ex, Ey)\n                                   + manhattan(Ex, Ey, Fx, Fy);\n\n                        int B2x, B2y, E2x, E2y;\n                        // new B at x is event2\n                        if (ky == 0) {\n                            int id = oid2;\n                            B2x = rx[id]; B2y = ry[id];\n                        } else {\n                            int id = oid2;\n                            B2x = dx[id]; B2y = dy[id];\n                        }\n                        // new E at y is event1\n                        if (kx == 0) {\n                            int id = oid1;\n                            E2x = rx[id]; E2y = ry[id];\n                        } else {\n                            int id = oid1;\n                            E2x = dx[id]; E2y = dy[id];\n                        }\n\n                        int after = manhattan(Ax, Ay, B2x, B2y)\n                                  + manhattan(B2x, B2y, Cx, Cy)\n                                  + manhattan(Dx_, Dy_, E2x, E2y)\n                                  + manhattan(E2x, E2y, Fx, Fy);\n\n                        deltaCost = after - before;\n                    }\n\n                    if (deltaCost < 0) {\n                        // apply improving swap\n                        routeCost += deltaCost;\n                        swap(finalKind[x], finalKind[y]);\n                        swap(finalOid[x], finalOid[y]);\n                        // update positions\n                        if (kx == 0) posP2[oid1] = y; else posD2[oid1] = y;\n                        if (ky == 0) posP2[oid2] = x; else posD2[oid2] = x;\n                        improved = true;\n                        goto restart_greedy;\n                    }\n                }\n            }\n            break;\n        restart_greedy:;\n        }\n    }\nend_greedy_improve:;\n\n    // -----------------------------------------------------------\n    // Build final path coordinates from final route (kind, oid)\n    // -----------------------------------------------------------\n    vector<pair<int,int>> path;\n    path.reserve(routeSize);\n    for (int pos = 0; pos < routeSize; ++pos) {\n        if (pos == 0 || pos == routeSize - 1) {\n            path.emplace_back(OFFICE_X, OFFICE_Y);\n        } else if (finalKind[pos] == 0) {\n            int local = finalOid[pos];\n            int gi = globalOfLocal[local];\n            path.emplace_back(a[gi], b[gi]);\n        } else {\n            int local = finalOid[pos];\n            int gi = globalOfLocal[local];\n            path.emplace_back(c[gi], d[gi]);\n        }\n    }\n\n    // -----------------------------------------------------------\n    // Output\n    // -----------------------------------------------------------\n    // First line: m and chosen order indices (1-based)\n    cout << M;\n    for (int i = 0; i < M; ++i) {\n        cout << ' ' << (bestSel[i] + 1);\n    }\n    cout << '\\n';\n\n    // Second line: n and route coordinates\n    int n = (int)path.size();\n    cout << n;\n    for (int i = 0; i < n; ++i) {\n        cout << ' ' << path[i].first << ' ' << path[i].second;\n    }\n    cout << '\\n';\n\n    return 0;\n}","ahc007":"#include <bits/stdc++.h>\nusing namespace std;\n\n// ---------- DSU (Union-Find) ----------\nstruct DSU {\n    int n;\n    vector<int> p, r;\n    DSU() {}\n    DSU(int n_) { init(n_); }\n    void init(int n_) {\n        n = n_;\n        p.resize(n);\n        r.assign(n, 0);\n        iota(p.begin(), p.end(), 0);\n    }\n    int find(int x) {\n        if (p[x] == x) return x;\n        return p[x] = find(p[x]);\n    }\n    bool same(int a, int b) {\n        return find(a) == find(b);\n    }\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\n// ---------- XorShift RNG ----------\nstruct XorShift {\n    uint32_t x = 123456789u;\n    uint32_t y = 362436069u;\n    uint32_t z = 521288629u;\n    uint32_t w = 88675123u;\n    uint32_t next() {\n        uint32_t t = x ^ (x << 11);\n        x = y; y = z; z = w;\n        w = w ^ (w >> 19) ^ (t ^ (t >> 8));\n        return w;\n    }\n    uint32_t nextUInt(uint32_t bound) {\n        return next() % bound;\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    const int N = 400;\n    const int M = 1995;\n    const int LOG = 9; // 2^9 = 512 > 400\n\n    // ----- Read coordinates -----\n    vector<int> x(N), y(N);\n    for (int i = 0; i < N; i++) {\n        if (!(cin >> x[i] >> y[i])) return 0;\n    }\n\n    // ----- Read edges -----\n    vector<int> u(M), v(M);\n    for (int i = 0; i < M; i++) {\n        cin >> u[i] >> v[i];\n    }\n\n    // ----- Precompute geometric distances d_i -----\n    vector<int> d(M);\n    for (int i = 0; i < M; i++) {\n        int dx = x[u[i]] - x[v[i]];\n        int dy = y[u[i]] - y[v[i]];\n        double dist = sqrt((double)dx * dx + (double)dy * dy);\n        d[i] = (int)llround(dist);\n    }\n\n    // ----- Compute geometric MST (for connectivity) -----\n    vector<int> idx(M);\n    iota(idx.begin(), idx.end(), 0);\n    sort(idx.begin(), idx.end(), [&](int a, int b) {\n        if (d[a] != d[b]) return d[a] < d[b];\n        return a < b;\n    });\n\n    vector<char> inTree(M, false);\n    DSU dsu0(N);\n    int used = 0;\n    for (int id : idx) {\n        if (!dsu0.same(u[id], v[id])) {\n            dsu0.unite(u[id], v[id]);\n            inTree[id] = true;\n            used++;\n            if (used == N - 1) break;\n        }\n    }\n\n    // ----- Build adjacency of geometric MST -----\n    vector<vector<pair<int,int>>> adj(N);\n    adj.assign(N, {});\n    for (int i = 0; i < M; i++) {\n        if (!inTree[i]) continue;\n        adj[u[i]].push_back({v[i], d[i]});\n        adj[v[i]].push_back({u[i], d[i]});\n    }\n\n    // ----- LCA precomputation for max edge on path in MST -----\n    vector<int> depth(N, 0);\n    vector<vector<int>> par(LOG, vector<int>(N));\n    vector<vector<int>> mx(LOG, vector<int>(N));\n\n    {\n        queue<int> q;\n        vector<char> vis(N, false);\n        int root = 0;\n        vis[root] = true;\n        depth[root] = 0;\n        par[0][root] = root;\n        mx[0][root] = 0;\n        q.push(root);\n        while (!q.empty()) {\n            int cur = q.front(); q.pop();\n            for (auto [to, w] : adj[cur]) {\n                if (!vis[to]) {\n                    vis[to] = true;\n                    depth[to] = depth[cur] + 1;\n                    par[0][to] = cur;\n                    mx[0][to] = w;\n                    q.push(to);\n                }\n            }\n        }\n        for (int k = 1; k < LOG; k++) {\n            for (int vtx = 0; vtx < N; vtx++) {\n                int p = par[k-1][vtx];\n                par[k][vtx] = par[k-1][p];\n                mx[k][vtx] = max(mx[k-1][vtx], mx[k-1][p]);\n            }\n        }\n    }\n\n    auto getMaxOnPath = [&](int a, int b) -> int {\n        if (a == b) return 0;\n        int res = 0;\n        if (depth[a] < depth[b]) swap(a, b);\n        int diff = depth[a] - depth[b];\n        for (int k = 0; k < LOG; k++) {\n            if (diff & (1 << k)) {\n                res = max(res, mx[k][a]);\n                a = par[k][a];\n            }\n        }\n        if (a == b) return res;\n        for (int k = LOG - 1; k >= 0; k--) {\n            if (par[k][a] != par[k][b]) {\n                res = max(res, mx[k][a]);\n                res = max(res, mx[k][b]);\n                a = par[k][a];\n                b = par[k][b];\n            }\n        }\n        res = max(res, mx[0][a]);\n        res = max(res, mx[0][b]);\n        return res;\n    };\n\n    // ----- H[i] = max d on MST path between u[i], v[i] (for non-tree edges) -----\n    vector<int> H(M, 0);\n    for (int i = 0; i < M; i++) {\n        if (inTree[i]) continue;\n        int h = getMaxOnPath(u[i], v[i]);\n        if (h <= 0) h = d[i];\n        H[i] = h;\n    }\n\n    // ----- Monte Carlo to approximate MST distribution under true weights -----\n    XorShift rng;\n    const int S = 2000;  // number of simulations (increased from 1600)\n\n    vector<vector<int>> chosenLens(M);\n    int avgCap = (S * 400) / M + 8; // rough average per edge\n    for (int i = 0; i < M; i++) {\n        chosenLens[i].reserve(avgCap);\n    }\n\n    vector<int> sampleLen(M);\n    vector<int> perm(M);\n\n    for (int s = 0; s < S; s++) {\n        for (int i = 0; i < M; i++) {\n            uint32_t range = (uint32_t)(2 * d[i] + 1); // [d[i], 3*d[i]]\n            sampleLen[i] = d[i] + (int)rng.nextUInt(range);\n            perm[i] = i;\n        }\n        sort(perm.begin(), perm.end(), [&](int a, int b) {\n            if (sampleLen[a] != sampleLen[b]) return sampleLen[a] < sampleLen[b];\n            return a < b;\n        });\n        DSU dsu(N);\n        int cnt = 0;\n        for (int eid : perm) {\n            if (!dsu.same(u[eid], v[eid])) {\n                dsu.unite(u[eid], v[eid]);\n                chosenLens[eid].push_back(sampleLen[eid]);\n                cnt++;\n                if (cnt == N - 1) break;\n            }\n        }\n    }\n\n    // ----- Compute thresholds thr[i] for non-tree edges -----\n    vector<int> thr(M);\n    for (int i = 0; i < M; i++) thr[i] = d[i]; // default\n\n    for (int i = 0; i < M; i++) {\n        if (inTree[i]) continue; // MST edges: threshold unused\n        auto &vec = chosenLens[i];\n        if (vec.empty()) {\n            thr[i] = d[i];\n            continue;\n        }\n        sort(vec.begin(), vec.end());\n\n        int Hi = H[i];\n        if (Hi <= 0) Hi = d[i];\n        double r = (double)d[i] / (double)Hi;\n        if (r < 1.0) r = 1.0;\n        if (r > 3.0) r = 3.0;\n\n        // Base quantile factor from geometric ratio r\n        double baseQ;\n        if (r <= 1.02)      baseQ = 0.82;\n        else if (r <= 1.20) baseQ = 0.78;\n        else if (r <= 1.50) baseQ = 0.72;\n        else if (r <= 1.80) baseQ = 0.66;\n        else if (r <= 2.20) baseQ = 0.60;\n        else                baseQ = 0.54;\n\n        // Adjust by empirical selection probability p\n        double p = (double)vec.size() / (double)S;\n        double delta = 0.0;\n        if (p >= 0.45)      delta += 0.03;\n        else if (p >= 0.30) delta += 0.015;\n        else if (p <= 0.03) delta -= 0.05;\n        else if (p <= 0.08) delta -= 0.03;\n        else if (p <= 0.15) delta -= 0.015;\n\n        double qf = baseQ + delta;\n        if (qf < 0.50) qf = 0.50;\n        if (qf > 0.90) qf = 0.90;\n\n        int cnt = (int)vec.size();\n        int idxQ = (int)(qf * cnt);\n        if (idxQ >= cnt) idxQ = cnt - 1;\n        if (idxQ < 0) idxQ = 0;\n\n        int t = vec[idxQ];\n        if (t < d[i]) t = d[i];\n        int maxLen = 3 * d[i];\n        if (t > maxLen) t = maxLen;\n        thr[i] = t;\n    }\n\n    // ----- Online phase -----\n    DSU dsuCur(N);\n\n    for (int i = 0; i < M; i++) {\n        long long l;\n        if (!(cin >> l)) return 0;\n\n        bool take = false;\n\n        if (!dsuCur.same(u[i], v[i])) {\n            if (inTree[i]) {\n                // Geometric MST edge: always accept when it connects different components\n                take = true;\n            } else {\n                // Non-tree edge: accept only if length is not too large\n                if (l <= thr[i]) {\n                    take = true;\n                }\n            }\n        } else {\n            take = false; // would form a cycle\n        }\n\n        if (take) {\n            dsuCur.unite(u[i], v[i]);\n        }\n\n        cout << (take ? 1 : 0) << '\\n';\n        cout.flush();\n    }\n\n    return 0;\n}","ahc008":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Pet {\n    int x, y, t;\n};\n\nstruct Human {\n    int x, y;\n};\n\nstatic const int H = 30;\nstatic const int W = 30;\n\nbool inside(int x, int y) {\n    return 1 <= x && x <= H && 1 <= y && y <= W;\n}\n\n// Check whether we are allowed to place a wall at (x,y)\nbool canWallCell(int x, int y,\n                 const vector<Pet> &pets,\n                 const vector<Human> &humans) {\n    if (!inside(x, y)) return false;\n    // Cannot place on a human\n    for (const auto &h : humans) {\n        if (h.x == x && h.y == y) return false;\n    }\n    // Cannot place on or adjacent (4-neighbor) to a pet\n    for (const auto &p : pets) {\n        int dx = abs(p.x - x);\n        int dy = abs(p.y - y);\n        if (dx + dy == 0) return false; // same cell\n        if (dx + dy == 1) return false; // 4-neighbor\n    }\n    return true;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    if (!(cin >> N)) {\n        return 0;\n    }\n    vector<Pet> pets(N);\n    for (int i = 0; i < N; i++) {\n        cin >> pets[i].x >> pets[i].y >> pets[i].t;\n    }\n    int M;\n    cin >> M;\n    vector<Human> humans(M);\n    for (int i = 0; i < M; i++) {\n        cin >> humans[i].x >> humans[i].y;\n    }\n\n    // Grid of walls: true means impassable\n    static bool wall[H + 1][W + 1];\n    for (int i = 1; i <= H; i++) {\n        for (int j = 1; j <= W; j++) wall[i][j] = false;\n    }\n\n    // We will build a vertical wall at column WALL_COL\n    const int WALL_COL = 16; // 1-indexed\n    const int WALK_COL = 17; // walkway column for the builder (to the right of the wall)\n    const int builder = 0;   // index of the builder human\n\n    // Row completion tracking for the wall\n    vector<bool> rowWalled(H + 1, false);\n    int walledCount = 0;\n\n    const int T_PRE = 50; // preparation phase duration\n\n    for (int turn = 0; turn < 300; turn++) {\n        string actions(M, '.');\n\n        // Decide actions for humans\n        if (M > 0) {\n            Human &hb = humans[builder];\n            int hx = hb.x;\n            int hy = hb.y;\n\n            char act = '.';\n\n            if (turn < T_PRE) {\n                // Preparation: move builder horizontally to walkway column\n                if (hy < WALK_COL) act = 'R';\n                else if (hy > WALK_COL) act = 'L';\n                else act = '.';\n            } else {\n                // Building phase\n                if (hy != WALK_COL) {\n                    // Ensure builder is on walkway column\n                    if (hy < WALK_COL) act = 'R';\n                    else if (hy > WALK_COL) act = 'L';\n                } else {\n                    // On walkway column; move up/down and place walls\n                    if (walledCount >= H) {\n                        act = '.';\n                    } else {\n                        // Determine if we can wall at current row\n                        bool thisRowUnwalled = !rowWalled[hx];\n\n                        bool canWallHere = false;\n                        if (thisRowUnwalled && !wall[hx][WALL_COL]) {\n                            if (canWallCell(hx, WALL_COL, pets, humans)) {\n                                canWallHere = true;\n                            }\n                        }\n                        if (thisRowUnwalled && canWallHere) {\n                            // Place wall to the left from (hx, WALK_COL) to (hx, WALL_COL)\n                            act = (WALK_COL > WALL_COL ? 'l' : 'r');\n                            wall[hx][WALL_COL] = true;\n                            rowWalled[hx] = true;\n                            walledCount++;\n                        } else {\n                            // Move to nearest other row that still needs a wall\n                            int bestRow = -1;\n                            int bestDist = INT_MAX;\n                            for (int r = 1; r <= H; r++) {\n                                if (!rowWalled[r] && r != hx) {\n                                    int d = abs(r - hx);\n                                    if (d < bestDist) {\n                                        bestDist = d;\n                                        bestRow = r;\n                                    }\n                                }\n                            }\n                            if (bestRow != -1) {\n                                if (bestRow > hx) act = 'D';\n                                else act = 'U';\n                            } else {\n                                // This row is the only remaining one; wait until it becomes safe\n                                act = '.';\n                            }\n                        }\n                    }\n                }\n            }\n            actions[builder] = act;\n        }\n\n        // Other humans\n        for (int i = 0; i < M; i++) {\n            if (i == builder) continue;\n            Human &h = humans[i];\n            char act = '.';\n            if (turn < T_PRE) {\n                // Move off the wall column if initially on it\n                if (h.y == WALL_COL) {\n                    // Simple: move left (safe, because WALL_COL=16, so >=2)\n                    act = 'L';\n                }\n            } else {\n                act = '.';\n            }\n            actions[i] = act;\n        }\n\n        // Output actions and flush\n        cout << actions << '\\n' << flush;\n\n        // Apply wall placements\n        for (int i = 0; i < M; i++) {\n            char c = actions[i];\n            if (c == 'u' || c == 'd' || c == 'l' || c == 'r') {\n                int x = humans[i].x;\n                int y = humans[i].y;\n                int nx = x, ny = y;\n                if (c == 'u') nx = x - 1;\n                else if (c == 'd') nx = x + 1;\n                else if (c == 'l') ny = y - 1;\n                else if (c == 'r') ny = y + 1;\n                if (inside(nx, ny)) {\n                    wall[nx][ny] = true;\n                }\n            }\n        }\n\n        // Apply human moves\n        for (int i = 0; i < M; i++) {\n            char c = actions[i];\n            if (c == 'U' || c == 'D' || c == 'L' || c == 'R') {\n                int x = humans[i].x;\n                int y = humans[i].y;\n                int nx = x, ny = y;\n                if (c == 'U') nx = x - 1;\n                else if (c == 'D') nx = x + 1;\n                else if (c == 'L') ny = y - 1;\n                else if (c == 'R') ny = y + 1;\n                if (inside(nx, ny) && !wall[nx][ny]) {\n                    humans[i].x = nx;\n                    humans[i].y = ny;\n                }\n            }\n        }\n\n        // Read pets' moves\n        vector<string> pmoves(N);\n        for (int i = 0; i < N; i++) {\n            cin >> pmoves[i];\n        }\n\n        // Apply pets' moves\n        for (int i = 0; i < N; i++) {\n            for (char c : pmoves[i]) {\n                int x = pets[i].x;\n                int y = pets[i].y;\n                int nx = x, ny = y;\n                if (c == 'U') nx = x - 1;\n                else if (c == 'D') nx = x + 1;\n                else if (c == 'L') ny = y - 1;\n                else if (c == 'R') ny = y + 1;\n                if (inside(nx, ny) && !wall[nx][ny]) {\n                    pets[i].x = nx;\n                    pets[i].y = ny;\n                } else {\n                    // According to rules, pets won't try to move into walls,\n                    // but we keep this check for safety.\n                }\n            }\n        }\n    }\n\n    return 0;\n}","ahc009":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const int H = 20;\nstatic const int W = 20;\nstatic const int N = H * W;\nstatic const int MAXL = 200;\n\n// DP arrays\nstatic double alpha_dp[MAXL + 1][N];\nstatic double beta_dp [MAXL + 1][N];\nstatic double prefix_score[MAXL + 1];\n\n// Directions\nint  dirIdx[256];\nchar dirChar[4] = {'U', 'D', 'L', 'R'};\n\n// Precomputed next cell\nint nextCell[4][N];\n\n// Globals\nint start_id, goal_id;\nint goal_r, goal_c;\nint L = MAXL;\ndouble forget_p;\n\n// RNG\nmt19937 rng(1234567);\n\n// Build adjacency graph from wall info\nvector<vector<int>> build_graph(const vector<string> &h, const vector<string> &v) {\n    vector<vector<int>> g(N);\n    auto cell_id = [](int r, int c) { return r * W + c; };\n\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            int id = cell_id(i, j);\n            if (j + 1 < W && h[i][j] == '0') {\n                int nid = cell_id(i, j + 1);\n                g[id].push_back(nid);\n                g[nid].push_back(id);\n            }\n            if (i + 1 < H && v[i][j] == '0') {\n                int nid = cell_id(i + 1, j);\n                g[id].push_back(nid);\n                g[nid].push_back(id);\n            }\n        }\n    }\n    return g;\n}\n\n// Decode direction from \"from\" to \"to\"\nchar decode_dir(int from, int to) {\n    int r1 = from / W, c1 = from % W;\n    int r2 = to   / W, c2 = to   % W;\n    if (r2 == r1 && c2 == c1 + 1) return 'R';\n    if (r2 == r1 && c2 == c1 - 1) return 'L';\n    if (r2 == r1 + 1 && c2 == c1) return 'D';\n    if (r2 == r1 - 1 && c2 == c1) return 'U';\n    return 'U'; // fallback; should not occur\n}\n\n// BFS shortest path with different neighbor-order modes\n// mode 0: canonical (as built)\n// mode 1: neighbors sorted by Manhattan distance to goal (goal-directed)\n// mode 2: randomized neighbor order\nvector<char> bfs_shortest_path_any(const vector<vector<int>> &g, int mode) {\n    vector<vector<int>> g2 = g;\n\n    if (mode == 1) {\n        auto manh = [&](int id) {\n            int r = id / W, c = id % W;\n            return abs(r - goal_r) + abs(c - goal_c);\n        };\n        for (int u = 0; u < N; ++u) {\n            auto &adj = g2[u];\n            sort(adj.begin(), adj.end(),\n                 [&](int a, int b) { return manh(a) < manh(b); });\n        }\n    } else if (mode == 2) {\n        for (int u = 0; u < N; ++u) {\n            auto &adj = g2[u];\n            shuffle(adj.begin(), adj.end(), rng);\n        }\n    }\n\n    vector<int> prev(N, -1);\n    queue<int> q;\n    q.push(start_id);\n    prev[start_id] = start_id;\n\n    while (!q.empty()) {\n        int vtx = q.front(); q.pop();\n        if (vtx == goal_id) break;\n        for (int to : g2[vtx]) {\n            if (prev[to] == -1) {\n                prev[to] = vtx;\n                q.push(to);\n            }\n        }\n    }\n\n    vector<char> path;\n    if (prev[goal_id] == -1) {\n        // Should not happen, graph is connected\n        path.push_back('R');\n        return path;\n    }\n    int cur = goal_id;\n    while (cur != start_id) {\n        int p = prev[cur];\n        path.push_back(decode_dir(p, cur));\n        cur = p;\n    }\n    reverse(path.begin(), path.end());\n    if (path.empty()) path.push_back('R');\n    return path;\n}\n\n// Build a simple goal-loop pattern: move to neighbors of goal and back\nvector<char> build_goal_loop_pattern() {\n    vector<char> pattern;\n    auto rev_dir = [](char c) {\n        if (c == 'U') return 'D';\n        if (c == 'D') return 'U';\n        if (c == 'L') return 'R';\n        return 'L'; // 'R'\n    };\n\n    for (char c : {'U', 'D', 'L', 'R'}) {\n        int d = dirIdx[(unsigned char)c];\n        int dest = nextCell[d][goal_id];\n        if (dest != goal_id) {\n            pattern.push_back(c);\n            pattern.push_back(rev_dir(c));\n        }\n    }\n    if (pattern.empty()) {\n        // Safeguard\n        pattern.push_back('U');\n        pattern.push_back('D');\n    }\n    return pattern;\n}\n\n// Evaluate route s[1..L]; fills alpha_dp, beta_dp, prefix_score; returns E[S]\ndouble evaluate_route(const vector<char> &s) {\n    const double p = forget_p;\n    const double q = 1.0 - p;\n\n    // Forward DP: alpha, prefix_score\n    memset(alpha_dp, 0, sizeof(alpha_dp));\n    alpha_dp[0][start_id] = 1.0;\n    prefix_score[0] = 0.0;\n\n    for (int t = 1; t <= L; ++t) {\n        memset(alpha_dp[t], 0, sizeof(alpha_dp[t]));\n        prefix_score[t] = prefix_score[t - 1];\n\n        int d = dirIdx[(unsigned char)s[t]];\n        double reward_weight = 401.0 - t;\n\n        for (int id = 0; id < N; ++id) {\n            double px = alpha_dp[t - 1][id];\n            if (px == 0.0) continue;\n\n            if (id == goal_id) {\n                alpha_dp[t][id] += px;\n                continue;\n            }\n\n            int dest = nextCell[d][id];\n\n            if (dest == id) {\n                // Blocked\n                alpha_dp[t][id] += px;\n            } else if (dest == goal_id) {\n                double moved = px * q;\n                prefix_score[t] += moved * reward_weight;\n                alpha_dp[t][goal_id] += moved;\n                alpha_dp[t][id] += px * p;\n            } else {\n                double moved = px * q;\n                alpha_dp[t][dest] += moved;\n                alpha_dp[t][id]   += px * p;\n            }\n        }\n    }\n\n    double total_score = prefix_score[L];\n\n    // Backward DP: beta\n    memset(beta_dp, 0, sizeof(beta_dp));\n    for (int id = 0; id < N; ++id) beta_dp[L][id] = 0.0;\n\n    for (int t = L - 1; t >= 0; --t) {\n        int d = dirIdx[(unsigned char)s[t + 1]];\n        double reward_weight = 401.0 - (t + 1);\n\n        for (int id = 0; id < N; ++id) {\n            if (id == goal_id) {\n                beta_dp[t][id] = 0.0;\n                continue;\n            }\n            int dest = nextCell[d][id];\n            double immediate = 0.0;\n            double future = 0.0;\n\n            if (dest == id) {\n                future = beta_dp[t + 1][id];\n            } else if (dest == goal_id) {\n                immediate = q * reward_weight;\n                future = p * beta_dp[t + 1][id];\n            } else {\n                future = q * beta_dp[t + 1][dest] + p * beta_dp[t + 1][id];\n            }\n            beta_dp[t][id] = immediate + future;\n        }\n    }\n\n    return total_score;\n}\n\n// Score if we change only s[k] to newDir, using current DP data\ndouble score_if_change_step(const vector<char> & /*s*/, int k, char newDir) {\n    const double p = forget_p;\n    const double q = 1.0 - p;\n\n    double res = prefix_score[k - 1];\n    int d = dirIdx[(unsigned char)newDir];\n\n    for (int id = 0; id < N; ++id) {\n        double px = alpha_dp[k - 1][id];\n        if (px == 0.0) continue;\n        if (id == goal_id) continue;\n\n        int dest = nextCell[d][id];\n        if (dest == id) {\n            res += px * beta_dp[k][id];\n        } else if (dest == goal_id) {\n            res += px * q * (401.0 - k);\n            res += px * p * beta_dp[k][id];\n        } else {\n            res += px * (q * beta_dp[k][dest] + p * beta_dp[k][id]);\n        }\n    }\n    return res;\n}\n\nstruct SeedRoute {\n    vector<char> route;\n    double score;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int si, sj, ti, tj;\n    if (!(cin >> si >> sj >> ti >> tj >> forget_p)) {\n        return 0;\n    }\n    vector<string> h(H), v(H - 1);\n    for (int i = 0; i < H; ++i) cin >> h[i];\n    for (int i = 0; i < H - 1; ++i) cin >> v[i];\n\n    start_id = si * W + sj;\n    goal_id  = ti * W + tj;\n    goal_r = ti;\n    goal_c = tj;\n\n    // Direction indices\n    dirIdx['U'] = 0;\n    dirIdx['D'] = 1;\n    dirIdx['L'] = 2;\n    dirIdx['R'] = 3;\n\n    // Precompute nextCell\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            int id = i * W + j;\n            // Up\n            if (i == 0 || v[i - 1][j] == '1') nextCell[0][id] = id;\n            else                              nextCell[0][id] = (i - 1) * W + j;\n            // Down\n            if (i == H - 1 || v[i][j] == '1') nextCell[1][id] = id;\n            else                               nextCell[1][id] = (i + 1) * W + j;\n            // Left\n            if (j == 0 || h[i][j - 1] == '1') nextCell[2][id] = id;\n            else                              nextCell[2][id] = i * W + (j - 1);\n            // Right\n            if (j == W - 1 || h[i][j] == '1') nextCell[3][id] = id;\n            else                              nextCell[3][id] = i * W + (j + 1);\n        }\n    }\n\n    // Build graph and goal loop pattern\n    vector<vector<int>> graph = build_graph(h, v);\n    vector<char> goal_pattern = build_goal_loop_pattern();\n    int goal_pat_len = (int)goal_pattern.size();\n\n    // Base BFS paths: canonical, goal-pref, and one randomized\n    vector<vector<char>> basePaths;\n    basePaths.push_back(bfs_shortest_path_any(graph, 0)); // canonical\n    basePaths.push_back(bfs_shortest_path_any(graph, 1)); // goal-directed\n    basePaths.push_back(bfs_shortest_path_any(graph, 2)); // random\n\n    // For higher forget probability, add doubled-step expansions (more robust)\n    if (forget_p >= 0.30) {\n        for (int idx = 0; idx < 2; ++idx) { // canonical & goal-directed\n            const auto &path = basePaths[idx];\n            vector<char> expPath;\n            expPath.reserve(path.size() * 2);\n            for (char c : path) {\n                expPath.push_back(c);\n                expPath.push_back(c);\n            }\n            if (expPath.empty()) expPath.push_back('R');\n            basePaths.push_back(expPath);\n        }\n    }\n\n    // Build candidate seed routes (3 templates per path) and evaluate them\n    vector<SeedRoute> seeds;\n\n    for (const auto &path_raw : basePaths) {\n        vector<char> path = path_raw;\n        if (path.empty()) path.push_back('R');\n        int D = (int)path.size();\n        if (D > L) D = L;\n\n        // Type 0: repeat path for entire length\n        {\n            vector<char> route(L + 1);\n            for (int t = 1; t <= L; ++t) {\n                route[t] = path[(t - 1) % D];\n            }\n            double sc = evaluate_route(route);\n            seeds.push_back({route, sc});\n        }\n\n        // Type 1: path once, then goal loop pattern\n        {\n            vector<char> route(L + 1);\n            for (int t = 1; t <= L; ++t) {\n                if (t <= D) {\n                    route[t] = path[t - 1];\n                } else {\n                    route[t] = goal_pattern[(t - D - 1) % goal_pat_len];\n                }\n            }\n            double sc = evaluate_route(route);\n            seeds.push_back({route, sc});\n        }\n\n        // Type 2: path twice (if room), then goal loop pattern\n        {\n            vector<char> route(L + 1);\n            int D2 = min(2 * D, L);\n            for (int t = 1; t <= L; ++t) {\n                if (t <= D) {\n                    route[t] = path[t - 1];\n                } else if (t <= D2) {\n                    route[t] = path[t - D - 1];\n                } else {\n                    int offset = t - D2 - 1;\n                    route[t] = goal_pattern[offset % goal_pat_len];\n                }\n            }\n            double sc = evaluate_route(route);\n            seeds.push_back({route, sc});\n        }\n    }\n\n    // Sort seeds by base score descending\n    sort(seeds.begin(), seeds.end(),\n         [](const SeedRoute &a, const SeedRoute &b) {\n             return a.score > b.score;\n         });\n\n    // Hill-climb from top K seeds, keep best result\n    const int K = min<int>(2, seeds.size());\n    const int MAX_ITER = 3;\n    const double EPS = 1e-9;\n\n    vector<int> order(L);\n    for (int i = 0; i < L; ++i) order[i] = i + 1;\n\n    double globalBestScore = -1.0;\n    vector<char> globalBestRoute(L + 1);\n\n    for (int sIdx = 0; sIdx < K; ++sIdx) {\n        vector<char> route = seeds[sIdx].route;\n\n        // Re-evaluate to sync DP arrays\n        double bestScore = evaluate_route(route);\n\n        for (int iter = 0; iter < MAX_ITER; ++iter) {\n            bool improved_any = false;\n            shuffle(order.begin(), order.end(), rng);\n\n            for (int idx = 0; idx < L; ++idx) {\n                int k = order[idx];\n                char orig = route[k];\n                char bestDir = orig;\n                double currScore = bestScore;\n\n                for (int di = 0; di < 4; ++di) {\n                    char c = dirChar[di];\n                    if (c == orig) continue;\n                    double newScore = score_if_change_step(route, k, c);\n                    if (newScore > currScore + EPS) {\n                        currScore = newScore;\n                        bestDir = c;\n                    }\n                }\n\n                if (bestDir != orig) {\n                    route[k] = bestDir;\n                    bestScore = evaluate_route(route);\n                    improved_any = true;\n                }\n            }\n            if (!improved_any) break;\n        }\n\n        if (bestScore > globalBestScore) {\n            globalBestScore = bestScore;\n            globalBestRoute = route;\n        }\n    }\n\n    // Output final route\n    string out;\n    out.reserve(L);\n    for (int t = 1; t <= L; ++t) out.push_back(globalBestRoute[t]);\n    cout << out << '\\n';\n\n    return 0;\n}","ahc010":"#include <bits/stdc++.h>\nusing namespace std;\n\nconstexpr int N = 30;\nconstexpr int M = 30;\nconstexpr int TOT_STATES = N * M * 4;\n\n// Input and current board\nint baseTile[N][M];   // initial tile types from input (0..7)\nint curTile[N][M];    // current effective tile type (0..7) after rotation\nint curRot[N][M];     // current rotation count (0..3) for each tile\n\n// Stage-1 best (local score)\nint bestLocalRot[N][M];\n// Final best (true score)\nint bestRot[N][M];\n\n// Rotation table: rotTable[t][r] = tile type after rotating t by r times 90deg CCW\nint rotTable[8][4];\n\n// Rail mapping: toTbl[t][d] = exit direction when entering tile type t from direction d\n// d: 0 = left, 1 = up, 2 = right, 3 = down\nint toTbl[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// Whether side d of tile type t has a rail\nbool useSide[8][4];\n\n// For loop detection in computeTrueScore (using precomputed transitions)\nbool visitedState[TOT_STATES];\nint  pathId[TOT_STATES];\nint  pathStep[TOT_STATES];\n\n// Precomputed \"next state\" transition: from (i, j, d) to next state's index, or -1 if dead-end\nint nextStateArr[TOT_STATES];\n\nint di[4] = {0, -1, 0, 1};  // left, up, right, down\nint dj[4] = {-1, 0, 1, 0};\n\nmt19937_64 rng(20240131);\n\n// Encode (i, j, d) into a single index 0..3599\ninline int encodeState(int i, int j, int d) {\n    return ((i * M + j) << 2) | d;  // 0..3599\n}\n\n// Compute local score = number of connected internal edges\nint computeLocalScore() {\n    int connected = 0;\n\n    // Horizontal internal edges: (i,j)-(i,j+1)\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < M - 1; ++j) {\n            int t1 = curTile[i][j];\n            int t2 = curTile[i][j + 1];\n            if (useSide[t1][2] && useSide[t2][0]) connected++;\n        }\n    }\n    // Vertical internal edges: (i,j)-(i+1,j)\n    for (int i = 0; i < N - 1; ++i) {\n        for (int j = 0; j < M; ++j) {\n            int t1 = curTile[i][j];\n            int t2 = curTile[i + 1][j];\n            if (useSide[t1][3] && useSide[t2][1]) connected++;\n        }\n    }\n    return connected;\n}\n\n// Incremental delta of local score when tile (i,j) type changes from oldT to newT\ninline int deltaLocalScoreTile(int i, int j, int oldT, int newT) {\n    int deltaConn = 0;\n\n    // Up neighbor\n    if (i > 0) {\n        int neighbor = curTile[i - 1][j];\n        bool neighborUsedDown = useSide[neighbor][3];\n        bool oldUsedUp = useSide[oldT][1];\n        bool newUsedUp = useSide[newT][1];\n        int before = (oldUsedUp && neighborUsedDown) ? 1 : 0;\n        int after  = (newUsedUp && neighborUsedDown) ? 1 : 0;\n        deltaConn += after - before;\n    }\n\n    // Down neighbor\n    if (i < N - 1) {\n        int neighbor = curTile[i + 1][j];\n        bool neighborUsedUp = useSide[neighbor][1];\n        bool oldUsedDown = useSide[oldT][3];\n        bool newUsedDown = useSide[newT][3];\n        int before = (oldUsedDown && neighborUsedUp) ? 1 : 0;\n        int after  = (newUsedDown && neighborUsedUp) ? 1 : 0;\n        deltaConn += after - before;\n    }\n\n    // Left neighbor\n    if (j > 0) {\n        int neighbor = curTile[i][j - 1];\n        bool neighborUsedRight = useSide[neighbor][2];\n        bool oldUsedLeft = useSide[oldT][0];\n        bool newUsedLeft = useSide[newT][0];\n        int before = (oldUsedLeft && neighborUsedRight) ? 1 : 0;\n        int after  = (newUsedLeft && neighborUsedRight) ? 1 : 0;\n        deltaConn += after - before;\n    }\n\n    // Right neighbor\n    if (j < M - 1) {\n        int neighbor = curTile[i][j + 1];\n        bool neighborUsedLeft = useSide[neighbor][0];\n        bool oldUsedRight = useSide[oldT][2];\n        bool newUsedRight = useSide[newT][2];\n        int before = (oldUsedRight && neighborUsedLeft) ? 1 : 0;\n        int after  = (newUsedRight && neighborUsedLeft) ? 1 : 0;\n        deltaConn += after - before;\n    }\n\n    return deltaConn;\n}\n\n// Build transitions for all states based on curTile\nvoid buildAllTransitions() {\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < M; ++j) {\n            int t = curTile[i][j];\n            for (int d = 0; d < 4; ++d) {\n                int idx = encodeState(i, j, d);\n                int d2 = toTbl[t][d];\n                if (d2 == -1) {\n                    nextStateArr[idx] = -1;\n                    continue;\n                }\n                int ni = i + di[d2];\n                int nj = j + dj[d2];\n                if (ni < 0 || ni >= N || nj < 0 || nj >= M) {\n                    nextStateArr[idx] = -1;\n                } else {\n                    int nd = (d2 + 2) & 3;\n                    nextStateArr[idx] = encodeState(ni, nj, nd);\n                }\n            }\n        }\n    }\n}\n\n// Update transitions only for tile (i,j) based on current curTile[i][j]\ninline void updateTransitionsForTile(int i, int j) {\n    int t = curTile[i][j];\n    for (int d = 0; d < 4; ++d) {\n        int idx = encodeState(i, j, d);\n        int d2 = toTbl[t][d];\n        if (d2 == -1) {\n            nextStateArr[idx] = -1;\n            continue;\n        }\n        int ni = i + di[d2];\n        int nj = j + dj[d2];\n        if (ni < 0 || ni >= N || nj < 0 || nj >= M) {\n            nextStateArr[idx] = -1;\n        } else {\n            int nd = (d2 + 2) & 3;\n            nextStateArr[idx] = encodeState(ni, nj, nd);\n        }\n    }\n}\n\n// Compute true score = product of lengths of two longest loops\nint computeTrueScore() {\n    fill(visitedState, visitedState + TOT_STATES, false);\n    fill(pathId, pathId + TOT_STATES, 0);\n\n    int best1 = 0, best2 = 0;\n    int curPathId = 1;\n\n    for (int s = 0; s < TOT_STATES; ++s) {\n        if (visitedState[s]) continue;\n        int nxt0 = nextStateArr[s];\n        if (nxt0 < 0) {\n            visitedState[s] = true;\n            continue;\n        }\n\n        int cur = s;\n        int len = 0;\n        ++curPathId;\n\n        while (true) {\n            visitedState[cur] = true;\n            pathId[cur] = curPathId;\n            pathStep[cur] = len;\n\n            int nxt = nextStateArr[cur];\n            if (nxt < 0) break;\n            ++len;\n            if (pathId[nxt] == curPathId) {\n                int cycLen = len - pathStep[nxt];\n                if (cycLen >= best1) {\n                    best2 = best1;\n                    best1 = cycLen;\n                } else if (cycLen > best2) {\n                    best2 = cycLen;\n                }\n                break;\n            }\n            if (visitedState[nxt]) break;\n            cur = nxt;\n        }\n    }\n\n    if (best2 == 0) return 0;\n    return best1 * best2;\n}\n\ninline double randDouble() {\n    return (double)(rng() >> 11) * (1.0 / (1ULL << 53));\n}\n\n// For multi-tile moves in SA\nstruct TileChange {\n    int i, j;\n    int oldRot, oldT;\n    int newRot, newT;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // Precompute rotation table\n    int rotMap[8] = {1, 2, 3, 0, 5, 4, 7, 6};\n    for (int t = 0; t < 8; ++t) {\n        rotTable[t][0] = t;\n        for (int r = 1; r < 4; ++r) {\n            rotTable[t][r] = rotMap[ rotTable[t][r - 1] ];\n        }\n    }\n\n    // Precompute useSide\n    for (int t = 0; t < 8; ++t) {\n        for (int d = 0; d < 4; ++d) {\n            useSide[t][d] = (toTbl[t][d] != -1);\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 < M; ++j) {\n            baseTile[i][j] = s[j] - '0';\n        }\n    }\n\n    auto timeStart = chrono::steady_clock::now();\n    const double GLOBAL_TIME_LIMIT = 1.95;  // slightly larger, still safe under 2.0\n\n    // ===== Stage 1: Multi-start greedy local search on local score =====\n    const int MAX_RUNS = 8;\n    const int MAX_PASS = 10;\n\n    vector<int> order(N * M);\n    iota(order.begin(), order.end(), 0);\n\n    int bestLocalScore = numeric_limits<int>::min();\n\n    for (int run = 0; run < MAX_RUNS; ++run) {\n        // Random initial rotations\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < M; ++j) {\n                int r = (int)(rng() & 3ULL);  // 0..3\n                curRot[i][j] = r;\n                curTile[i][j] = rotTable[ baseTile[i][j] ][r];\n            }\n        }\n\n        int curLocalScore = computeLocalScore();\n\n        for (int pass = 0; pass < MAX_PASS; ++pass) {\n            bool changed = false;\n            shuffle(order.begin(), order.end(), rng);\n\n            for (int idxCell : order) {\n                int i = idxCell / M;\n                int j = idxCell % M;\n\n                int oldRot = curRot[i][j];\n                int oldT = curTile[i][j];\n\n                int bestDelta = 0;\n                int bestR = oldRot;\n                int bestT = oldT;\n\n                // Try all 4 rotations\n                for (int r = 0; r < 4; ++r) {\n                    if (r == oldRot) continue;\n                    int newT = rotTable[ baseTile[i][j] ][r];\n                    if (newT == oldT) continue; // same effective type\n                    int delta = deltaLocalScoreTile(i, j, oldT, newT);\n                    if (delta > bestDelta) {\n                        bestDelta = delta;\n                        bestR = r;\n                        bestT = newT;\n                    }\n                }\n\n                if (bestDelta > 0) {\n                    curRot[i][j] = bestR;\n                    curTile[i][j] = bestT;\n                    curLocalScore += bestDelta;\n                    changed = true;\n                }\n            }\n\n            if (!changed) break;\n        }\n\n        if (curLocalScore > bestLocalScore) {\n            bestLocalScore = curLocalScore;\n            for (int i = 0; i < N; ++i)\n                for (int j = 0; j < M; ++j)\n                    bestLocalRot[i][j] = curRot[i][j];\n        }\n\n        double elapsed = chrono::duration<double>(chrono::steady_clock::now() - timeStart).count();\n        if (elapsed > GLOBAL_TIME_LIMIT * 0.20) {\n            // Keep enough time for stages 2 and 3\n            break;\n        }\n    }\n\n    // Initialize curRot/curTile from best local configuration\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < M; ++j) {\n            curRot[i][j] = bestLocalRot[i][j];\n            curTile[i][j] = rotTable[ baseTile[i][j] ][curRot[i][j]];\n        }\n    }\n\n    // Build transitions for Stage 2 & 3\n    buildAllTransitions();\n\n    // Initial true score from Stage-1 result\n    int curScore = computeTrueScore();\n    int bestScore = curScore;\n\n    // Copy as initial best rotations for Stage 2/3\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < M; ++j)\n            bestRot[i][j] = curRot[i][j];\n\n    // ===== Stage 2: Greedy hill-climb on true score (1 pass) =====\n    const int TRUE_PASSES = 1;\n    vector<int> order2(N * M);\n    iota(order2.begin(), order2.end(), 0);\n\n    for (int pass = 0; pass < TRUE_PASSES; ++pass) {\n        double elapsed = chrono::duration<double>(chrono::steady_clock::now() - timeStart).count();\n        if (elapsed > GLOBAL_TIME_LIMIT * 0.55) break; // leave time for SA\n\n        bool changed = false;\n        shuffle(order2.begin(), order2.end(), rng);\n\n        for (int idxCell : order2) {\n            double now = chrono::duration<double>(chrono::steady_clock::now() - timeStart).count();\n            if (now > GLOBAL_TIME_LIMIT * 0.55) break; // time check\n\n            int i = idxCell / M;\n            int j = idxCell % M;\n\n            int oldRot = curRot[i][j];\n            int oldT = curTile[i][j];\n            int base = baseTile[i][j];\n\n            int bestR = oldRot;\n            int bestT = oldT;\n            int bestCandScore = curScore;\n            int bestDiff = 0;\n\n            // Try all alternative effective tile types\n            for (int r = 0; r < 4; ++r) {\n                if (r == oldRot) continue;\n                int newT = rotTable[base][r];\n                if (newT == oldT) continue;\n\n                // apply candidate\n                curRot[i][j] = r;\n                curTile[i][j] = newT;\n                updateTransitionsForTile(i, j);\n\n                int sc = computeTrueScore();\n                int diff = sc - curScore;\n                if (diff > bestDiff) {\n                    bestDiff = diff;\n                    bestR = r;\n                    bestT = newT;\n                    bestCandScore = sc;\n                }\n\n                // revert\n                curRot[i][j] = oldRot;\n                curTile[i][j] = oldT;\n                updateTransitionsForTile(i, j);\n            }\n\n            if (bestDiff > 0) {\n                // apply best candidate\n                curRot[i][j] = bestR;\n                curTile[i][j] = bestT;\n                updateTransitionsForTile(i, j);\n                curScore = bestCandScore;\n                changed = true;\n\n                if (curScore > bestScore) {\n                    bestScore = curScore;\n                    for (int x = 0; x < N; ++x)\n                        for (int y = 0; y < M; ++y)\n                            bestRot[x][y] = curRot[x][y];\n                }\n            }\n        }\n\n        if (!changed) break;\n    }\n\n    // Reset current configuration to best found so far before SA\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < M; ++j) {\n            curRot[i][j] = bestRot[i][j];\n            curTile[i][j] = rotTable[ baseTile[i][j] ][curRot[i][j]];\n        }\n    }\n    buildAllTransitions();\n    curScore = bestScore;\n\n    // Precompute indices of cross tiles (type 4 or 5) to bias SA moves\n    vector<int> crossIdx;\n    crossIdx.reserve(N * M / 2);\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < M; ++j) {\n            int t0 = baseTile[i][j];\n            if (t0 == 4 || t0 == 5) {\n                crossIdx.push_back(i * M + j);\n            }\n        }\n    }\n\n    // ===== Stage 3: Simulated annealing on true score (single- & multi-tile moves) =====\n    const double T0  = 800.0; // global initial temperature\n    const double T1  = 3.0;   // global final temperature\n    const double TL0 = 6.0;   // local filter initial \"temperature\"\n    const double TL1 = 1.0;   // local filter final \"temperature\"\n\n    while (true) {\n        double elapsed = chrono::duration<double>(chrono::steady_clock::now() - timeStart).count();\n        if (elapsed > GLOBAL_TIME_LIMIT) break;\n        double progress = elapsed / GLOBAL_TIME_LIMIT;\n        if (progress > 1.0) progress = 1.0;\n        double T = T0 + (T1 - T0) * progress;\n        double TL = TL0 + (TL1 - TL0) * progress;\n\n        bool multi = (rng() % 6 == 0); // ~16% multi-tile moves\n\n        if (!multi) {\n            // ---- Single-tile move ----\n            int idxCell;\n            if (!crossIdx.empty() && (rng() % 4 != 0)) { // 75% from cross tiles\n                idxCell = crossIdx[ (int)(rng() % crossIdx.size()) ];\n            } else {\n                idxCell = (int)(rng() % (N * M));\n            }\n            int i = idxCell / M;\n            int j = idxCell % M;\n\n            int oldRot = curRot[i][j];\n            int oldT = curTile[i][j];\n            int base = baseTile[i][j];\n\n            int newRot, newT;\n            // Propose a different effective tile type via rotation\n            do {\n                newRot = (int)(rng() & 3ULL);  // 0..3\n                newT = rotTable[base][newRot];\n            } while (newT == oldT);\n\n            int localDelta = deltaLocalScoreTile(i, j, oldT, newT);\n\n            // Local pre-filter: skip strongly bad local moves with high probability\n            bool evaluate = false;\n            if (localDelta >= 0) {\n                evaluate = true;\n            } else {\n                double pLocal = exp((double)localDelta / TL); // localDelta <= -1\n                if (randDouble() < pLocal) evaluate = true;\n            }\n            if (!evaluate) continue;\n\n            // Apply tentative move\n            curRot[i][j] = newRot;\n            curTile[i][j] = newT;\n            updateTransitionsForTile(i, j);\n\n            int newScore = computeTrueScore();\n            int diff = newScore - curScore;\n\n            bool accept = false;\n            if (diff >= 0) {\n                accept = true;\n            } else {\n                double prob = exp((double)diff / T);\n                if (randDouble() < prob) accept = true;\n            }\n\n            if (accept) {\n                curScore = newScore;\n                if (newScore > bestScore) {\n                    bestScore = newScore;\n                    for (int x = 0; x < N; ++x)\n                        for (int y = 0; y < M; ++y)\n                            bestRot[x][y] = curRot[x][y];\n                }\n            } else {\n                // Revert move\n                curRot[i][j] = oldRot;\n                curTile[i][j] = oldT;\n                updateTransitionsForTile(i, j);\n            }\n        } else {\n            // ---- Multi-tile move (2 tiles) ----\n            const int K = 2;\n            TileChange ch[K];\n\n            // Select K distinct tiles (prefer cross tiles when available)\n            int chosenIdx[K];\n            for (int k = 0; k < K; ++k) {\n                int idxCell;\n                while (true) {\n                    if (!crossIdx.empty()) {\n                        idxCell = crossIdx[ (int)(rng() % crossIdx.size()) ];\n                    } else {\n                        idxCell = (int)(rng() % (N * M));\n                    }\n                    bool ok = true;\n                    for (int t = 0; t < k; ++t)\n                        if (idxCell == chosenIdx[t]) { ok = false; break; }\n                    if (ok) break;\n                }\n                chosenIdx[k] = idxCell;\n                int i = idxCell / M;\n                int j = idxCell % M;\n                ch[k].i = i;\n                ch[k].j = j;\n                ch[k].oldRot = curRot[i][j];\n                ch[k].oldT   = curTile[i][j];\n            }\n\n            int totalLocalDelta = 0;\n            bool anyChange = false;\n\n            // Propose new rotations and compute approximate local delta\n            for (int k = 0; k < K; ++k) {\n                int i = ch[k].i;\n                int j = ch[k].j;\n                int base = baseTile[i][j];\n                int newRot, newT;\n                int oldT = ch[k].oldT;\n\n                int tries = 0;\n                do {\n                    newRot = (int)(rng() & 3ULL);\n                    newT = rotTable[base][newRot];\n                    ++tries;\n                    if (tries > 8) break;\n                } while (newT == oldT);\n\n                if (newT == oldT) {\n                    anyChange = false;\n                    break;\n                }\n\n                ch[k].newRot = newRot;\n                ch[k].newT   = newT;\n                anyChange = true;\n\n                int ld = deltaLocalScoreTile(i, j, oldT, newT);\n                totalLocalDelta += ld;\n            }\n\n            if (!anyChange) continue;\n\n            // Local filter for multi-move\n            bool evaluate = false;\n            if (totalLocalDelta >= 0) {\n                evaluate = true;\n            } else {\n                double pLocal = exp((double)totalLocalDelta / TL);\n                if (randDouble() < pLocal) evaluate = true;\n            }\n            if (!evaluate) continue;\n\n            // Apply tentative multi-move\n            for (int k = 0; k < K; ++k) {\n                int i = ch[k].i;\n                int j = ch[k].j;\n                curRot[i][j] = ch[k].newRot;\n                curTile[i][j] = ch[k].newT;\n                updateTransitionsForTile(i, j);\n            }\n\n            int newScore = computeTrueScore();\n            int diff = newScore - curScore;\n\n            bool accept = false;\n            if (diff >= 0) {\n                accept = true;\n            } else {\n                double prob = exp((double)diff / T);\n                if (randDouble() < prob) accept = true;\n            }\n\n            if (accept) {\n                curScore = newScore;\n                if (newScore > bestScore) {\n                    bestScore = newScore;\n                    for (int x = 0; x < N; ++x)\n                        for (int y = 0; y < M; ++y)\n                            bestRot[x][y] = curRot[x][y];\n                }\n            } else {\n                // Revert multi-move\n                for (int k = 0; k < K; ++k) {\n                    int i = ch[k].i;\n                    int j = ch[k].j;\n                    curRot[i][j] = ch[k].oldRot;\n                    curTile[i][j] = ch[k].oldT;\n                    updateTransitionsForTile(i, j);\n                }\n            }\n        }\n    }\n\n    // ===== Output best rotations =====\n    string out;\n    out.reserve(N * M);\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < M; ++j) {\n            int r = bestRot[i][j] & 3;\n            out.push_back(char('0' + r));\n        }\n    }\n    cout << out << '\\n';\n\n    return 0;\n}","ahc011":"#include <bits/stdc++.h>\nusing namespace std;\n\n// ====== Global constants and types ======\n\nstatic const int MAXN = 10;\n\nint N, T;\n\n// Board representation\nstruct Board {\n    unsigned char a[MAXN][MAXN];\n};\n\n// Directions for graph connectivity (Up, Right, Down, Left)\nconst int DX[4]   = {-1, 0, 1, 0};\nconst int DY[4]   = { 0, 1, 0,-1};\n// Bit masks corresponding to U,R,D,L in that order\nconst int MASK[4] = {2, 4, 8, 1};\n// Opposite directions\nconst int OPP[4]  = {2, 3, 0, 1};\n\nstruct EvalRes {\n    int bestTree;    // size of largest tree component\n    int bestConn;    // size of largest connected component\n    int totalTree;   // sum of sizes of all tree components\n};\n\n// ====== Evaluation of a board configuration ======\n\nEvalRes evaluate(const Board &B) {\n    static bool vis[MAXN][MAXN];\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            vis[i][j] = false;\n\n    int bestTree = 0;\n    int bestConn = 0;\n    int totalTree = 0;\n\n    int qx[MAXN * MAXN];\n    int qy[MAXN * MAXN];\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (B.a[i][j] == 0 || vis[i][j]) continue;\n\n            int v = 0; // vertices in this component\n            int e = 0; // edges in this component\n\n            int head = 0, tail = 0;\n            vis[i][j] = true;\n            qx[tail] = i;\n            qy[tail] = j;\n            ++tail;\n\n            while (head < tail) {\n                int x = qx[head];\n                int y = qy[head];\n                ++head;\n\n                ++v;\n                unsigned char tile = B.a[x][y];\n\n                for (int dir = 0; dir < 4; ++dir) {\n                    if (!(tile & MASK[dir])) continue;\n                    int nx = x + DX[dir];\n                    int ny = y + DY[dir];\n                    if (nx < 0 || nx >= N || ny < 0 || ny >= N) continue;\n                    unsigned char nt = B.a[nx][ny];\n                    if (nt == 0) continue;\n                    if (!(nt & MASK[OPP[dir]])) continue;\n\n                    if (!vis[nx][ny]) {\n                        vis[nx][ny] = true;\n                        qx[tail] = nx;\n                        qy[tail] = ny;\n                        ++tail;\n                    }\n                    // count each undirected edge once\n                    if (x < nx || (x == nx && y < ny)) {\n                        ++e;\n                    }\n                }\n            }\n\n            bestConn = max(bestConn, v);\n            if (e == v - 1) {\n                bestTree = max(bestTree, v);\n                totalTree += v;\n            }\n        }\n    }\n\n    return {bestTree, bestConn, totalTree};\n}\n\n// Convert EvalRes to a scalar score (lexicographic: bestTree > totalTree > bestConn)\ninline long long evalScore(const EvalRes &er) {\n    // N <= 10, sizes <= 99, so these weights keep lexicographic priority.\n    return (long long)er.bestTree * 1000000LL\n         + (long long)er.totalTree * 1000LL\n         + (long long)er.bestConn;\n}\n\n// Comparison of two EvalRes according to the same lexicographic priority\ninline bool betterEval(const EvalRes &a, const EvalRes &b) {\n    if (a.bestTree != b.bestTree) return a.bestTree > b.bestTree;\n    if (a.totalTree != b.totalTree) return a.totalTree > b.totalTree;\n    if (a.bestConn != b.bestConn) return a.bestConn > b.bestConn;\n    return false;\n}\n\n// ====== Sliding puzzle mechanics ======\n\ninline bool legalMove(int r, int c, char mv) {\n    if (mv == 'U') return r > 0;\n    if (mv == 'D') return r + 1 < N;\n    if (mv == 'L') return c > 0;\n    if (mv == 'R') return c + 1 < N;\n    return false;\n}\n\n// Apply move to board and blank position\ninline void applyMove(Board &B, int &r, int &c, char mv) {\n    if (mv == 'U') {\n        swap(B.a[r][c], B.a[r-1][c]);\n        --r;\n    } else if (mv == 'D') {\n        swap(B.a[r][c], B.a[r+1][c]);\n        ++r;\n    } else if (mv == 'L') {\n        swap(B.a[r][c], B.a[r][c-1]);\n        --c;\n    } else if (mv == 'R') {\n        swap(B.a[r][c], B.a[r][c+1]);\n        ++c;\n    }\n}\n\n// Opposite sliding move\ninline char oppositeMove(char mv) {\n    if (mv == 'U') return 'D';\n    if (mv == 'D') return 'U';\n    if (mv == 'L') return 'R';\n    if (mv == 'R') return 'L';\n    return '?';\n}\n\n// ====== Time control ======\n\nusing Clock = chrono::steady_clock;\ninline double nowSec(const Clock::time_point &start) {\n    return chrono::duration<double>(Clock::now() - start).count();\n}\n\n// ====== Depth-limited DFS for lookahead scoring ======\n\nint LOOKAHEAD_DEPTH; // decided from N in main\n\n// Depth-limited DFS to find best reachable score within given depth\n// starting from board B and blank position (br, bc).\n// lastMove: last move applied to reach this state (to avoid immediate reverse),\n// depth: remaining depth to explore (0 means just evaluate this state).\nlong long dfsScore(const Board &B, int br, int bc, char lastMove, int depth) {\n    EvalRes er = evaluate(B);\n    long long best = evalScore(er);\n    if (depth == 0) return best;\n\n    static const char allMoves[4] = {'U', 'D', 'L', 'R'};\n    char cand[4];\n    int cnt = 0;\n    for (int k = 0; k < 4; ++k) {\n        char mv = allMoves[k];\n        if (!legalMove(br, bc, mv)) continue;\n        if (lastMove != '?' && mv == oppositeMove(lastMove)) continue;\n        cand[cnt++] = mv;\n    }\n\n    for (int i = 0; i < cnt; ++i) {\n        char mv = cand[i];\n        Board nb = B;\n        int nbr = br, nbc = bc;\n        applyMove(nb, nbr, nbc, mv);\n        long long sc = dfsScore(nb, nbr, nbc, mv, depth - 1);\n        if (sc > best) best = sc;\n    }\n    return best;\n}\n\n// ====== Main heuristic: multi-start greedy with lookahead ======\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    if (!(cin >> N >> T)) {\n        return 0;\n    }\n\n    Board initialBoard;\n    int initialBlankR = -1, initialBlankC = -1;\n\n    for (int i = 0; i < N; ++i) {\n        string row;\n        cin >> row;\n        for (int j = 0; j < N; ++j) {\n            char ch = row[j];\n            int val;\n            if ('0' <= ch && ch <= '9') val = ch - '0';\n            else val = ch - 'a' + 10;\n            initialBoard.a[i][j] = static_cast<unsigned char>(val);\n            if (val == 0) {\n                initialBlankR = i;\n                initialBlankC = j;\n            }\n        }\n    }\n\n    // Decide lookahead depth depending on N.\n    // Deeper for smaller boards, shallower for largest boards to keep time.\n    if (N <= 7) LOOKAHEAD_DEPTH = 4;\n    else LOOKAHEAD_DEPTH = 3;\n\n    // RNG for tie-breaking\n    mt19937_64 rng(\n        (uint64_t)chrono::high_resolution_clock::now().time_since_epoch().count()\n    );\n\n    auto startTime = Clock::now();\n    const double TIME_LIMIT = 2.8; // seconds, safety margin under 3.0\n\n    EvalRes initialEval = evaluate(initialBoard);\n    int totalTiles = N * N - 1;\n\n    // If initial board is already a full tree, output empty sequence.\n    if (initialEval.bestTree == totalTiles) {\n        cout << \"\\n\";\n        return 0;\n    }\n\n    EvalRes bestOverallEval = initialEval;\n    string bestOverallOps;\n    int bestOverallStep = 0;\n\n    static const char allMoves[4] = {'U', 'D', 'L', 'R'};\n    const int MAX_RUNS = 100; // upper bound; actual runs limited by TIME_LIMIT\n\n    for (int run = 0; run < MAX_RUNS && nowSec(startTime) < TIME_LIMIT; ++run) {\n        Board board = initialBoard;\n        int blankR = initialBlankR;\n        int blankC = initialBlankC;\n\n        string ops;\n        ops.reserve(T);\n\n        EvalRes bestRunEval = initialEval;\n        int bestRunStep = 0;\n        char lastMove = '?';\n\n        for (int step = 0; step < T; ++step) {\n            if (nowSec(startTime) >= TIME_LIMIT) break;\n\n            // Build candidate first moves, avoiding immediate reverse if possible.\n            char cand1[4];\n            int cand1cnt = 0;\n            for (int k = 0; k < 4; ++k) {\n                char mv = allMoves[k];\n                if (!legalMove(blankR, blankC, mv)) continue;\n                if (step > 0 && mv == oppositeMove(lastMove)) continue;\n                cand1[cand1cnt++] = mv;\n            }\n            if (cand1cnt == 0) {\n                // All legal moves are reverse of last; allow them.\n                for (int k = 0; k < 4; ++k) {\n                    char mv = allMoves[k];\n                    if (legalMove(blankR, blankC, mv)) {\n                        cand1[cand1cnt++] = mv;\n                    }\n                }\n                if (cand1cnt == 0) break; // no legal moves (shouldn't happen)\n            }\n\n            long long bestScoreStep = LLONG_MIN;\n            char chosenMove = cand1[0];\n            int tieCount = 0;\n\n            // For each candidate first move, perform depth-limited search.\n            for (int idx = 0; idx < cand1cnt; ++idx) {\n                char d1 = cand1[idx];\n\n                Board b1 = board;\n                int br1 = blankR, bc1 = blankC;\n                applyMove(b1, br1, bc1, d1);\n\n                // We already performed one move (d1); explore up to LOOKAHEAD_DEPTH-1 more.\n                long long sc = dfsScore(b1, br1, bc1, d1, LOOKAHEAD_DEPTH - 1);\n\n                if (sc > bestScoreStep) {\n                    bestScoreStep = sc;\n                    chosenMove = d1;\n                    tieCount = 1;\n                } else if (sc == bestScoreStep) {\n                    ++tieCount;\n                    if (rng() % tieCount == 0) {\n                        chosenMove = d1;\n                    }\n                }\n            }\n\n            // Commit chosen move\n            applyMove(board, blankR, blankC, chosenMove);\n            ops.push_back(chosenMove);\n            lastMove = chosenMove;\n\n            // Evaluate current board and update run-best prefix\n            EvalRes curEval = evaluate(board);\n            if (betterEval(curEval, bestRunEval)) {\n                bestRunEval = curEval;\n                bestRunStep = (int)ops.size();\n                if (bestRunEval.bestTree == totalTiles) {\n                    // Found a full tree; no need to continue this run.\n                    break;\n                }\n            }\n        }\n\n        // Update global best over all runs\n        if (betterEval(bestRunEval, bestOverallEval)) {\n            bestOverallEval = bestRunEval;\n            bestOverallStep = bestRunStep;\n            bestOverallOps = ops.substr(0, bestRunStep);\n            if (bestOverallEval.bestTree == totalTiles) {\n                // Reached optimal S; further improvements only affect K,\n                // but when S < N^2-1 score ignores K, so we can stop.\n                break;\n            }\n        }\n    }\n\n    if (bestOverallStep == 0) {\n        // best is initial board\n        cout << \"\\n\";\n    } else {\n        cout << bestOverallOps << \"\\n\";\n    }\n\n    return 0;\n}","ahc012":"#include <bits/stdc++.h>\nusing namespace std;\n\n// Constants\nstatic const int RADIUS = 10000;   // radius of the cake\nstatic const int BIG    = 100000;  // endpoints for axis-aligned lines\n\n// Pattern of regions: up to 128 bits (we only need <= 100)\nstruct Pattern {\n    uint64_t lo, hi;\n    bool operator==(const Pattern& o) const noexcept {\n        return lo == o.lo && hi == o.hi;\n    }\n};\nstruct PatternHash {\n    size_t operator()(const Pattern& p) const noexcept {\n        uint64_t x = p.lo * 0x9E3779B97F4A7C15ULL;\n        x ^= p.hi + 0x9E3779B97F4A7C15ULL + (x << 6) + (x >> 2);\n        return static_cast<size_t>(x);\n    }\n};\n\n// Line in Ax + By + C = 0 form, plus integer endpoints to output\nstruct Line {\n    long long A, B, C;\n    int px, py, qx, qy;\n};\n\n// Build quantile-based cut positions along one axis.\n//\n// Npoints: number of strawberries\n// Nc: desired number of cuts along this axis\n// sortedCoord: sorted coordinates (x or y) of all strawberries (size Npoints)\n// boundaryCoord: precomputed boundary coordinate for each boundary index 0..Npoints\n// boundaryValid: whether boundary 0..Npoints can be used without hitting any strawberry\n//\n// If we can't pick Nc valid boundaries, we fall back to uniform spacing.\nvector<int> build_quantile_cuts(\n    int Npoints,\n    int Nc,\n    const vector<int> &sortedCoord,\n    const vector<int> &boundaryCoord,\n    const vector<char> &boundaryValid\n) {\n    vector<int> cuts;\n    if (Nc <= 0) return cuts;\n\n    int validCount = 0;\n    for (int b = 0; b <= Npoints; ++b) {\n        if (boundaryValid[b]) ++validCount;\n    }\n\n    if (validCount <= Nc) {\n        // Fallback: uniform spacing in [-RADIUS, RADIUS]\n        cuts.reserve(Nc);\n        for (int i = 1; i <= Nc; ++i) {\n            long long num = 2LL * RADIUS * i;\n            int c = -RADIUS + (int)(num / (Nc + 1)); // floor\n            cuts.push_back(c);\n        }\n        return cuts;\n    }\n\n    cuts.reserve(Nc);\n    int prevB = -1;\n    bool success = true;\n    for (int i = 1; i <= Nc; ++i) {\n        long long target = 1LL * i * Npoints / (Nc + 1); // in [0, Npoints]\n        int bestB = -1;\n        long long bestDist = (1LL << 60);\n\n        // Choose next valid boundary index b > prevB minimizing |b - target|\n        for (int b = prevB + 1; b <= Npoints; ++b) {\n            if (!boundaryValid[b]) continue;\n            long long dist = llabs((long long)b - target);\n            if (dist < bestDist) {\n                bestDist = dist;\n                bestB = b;\n            }\n        }\n        if (bestB == -1) {\n            success = false;\n            break;\n        }\n        prevB = bestB;\n        cuts.push_back(boundaryCoord[bestB]);\n    }\n\n    if (!success || (int)cuts.size() != Nc) {\n        // Fallback: uniform spacing\n        cuts.clear();\n        cuts.reserve(Nc);\n        for (int i = 1; i <= Nc; ++i) {\n            long long num = 2LL * RADIUS * i;\n            int c = -RADIUS + (int)(num / (Nc + 1)); // floor\n            cuts.push_back(c);\n        }\n    }\n\n    return cuts;\n}\n\n// Compute current score (sum_d min(a_d, b_d)) for given patterns and lines.\nlong long compute_score_current(\n    const vector<uint64_t> &patLo,\n    const vector<uint64_t> &patHi,\n    int Lcur,\n    const vector<int> &a,\n    unordered_map<Pattern,int,PatternHash> &mp\n) {\n    int N = (int)patLo.size();\n    mp.clear();\n\n    if (Lcur == 0) {\n        int s = N;\n        int B[11];\n        memset(B, 0, sizeof(B));\n        if (1 <= s && s <= 10) B[s] = 1;\n        long long score = 0;\n        for (int d = 1; d <= 10; ++d) {\n            score += min((long long)a[d], (long long)B[d]);\n        }\n        return score;\n    }\n\n    mp.reserve(N * 2);\n    for (int i = 0; i < N; ++i) {\n        Pattern key{patLo[i], patHi[i]};\n        mp[key] += 1;\n    }\n\n    int B[11];\n    memset(B, 0, sizeof(B));\n    for (auto &kv : mp) {\n        int s = kv.second;\n        if (1 <= s && s <= 10) B[s] += 1;\n    }\n\n    long long score = 0;\n    for (int d = 1; d <= 10; ++d) {\n        score += min((long long)a[d], (long long)B[d]);\n    }\n    return score;\n}\n\n// Evaluate candidate line appended to current lines (patterns).\n// Returns score, or -1 if invalid (passes any strawberry center).\nlong long evaluate_candidate(\n    const Line &cand,\n    const vector<uint64_t> &patLo,\n    const vector<uint64_t> &patHi,\n    int Lcur,\n    const vector<pair<int,int>> &pts,\n    const vector<int> &a,\n    unordered_map<Pattern,int,PatternHash> &mp\n) {\n    int N = (int)pts.size();\n    mp.clear();\n    mp.reserve(N * 2);\n\n    bool invalid = false;\n\n    for (int i = 0; i < N; ++i) {\n        long long x = pts[i].first;\n        long long y = pts[i].second;\n        long long val = cand.A * x + cand.B * y + cand.C;\n        if (val == 0) {\n            invalid = true;\n            break;\n        }\n        Pattern key{patLo[i], patHi[i]};\n        if (val > 0) {\n            int bitpos = Lcur;\n            if (bitpos < 64) {\n                key.lo |= (1ULL << bitpos);\n            } else {\n                key.hi |= (1ULL << (bitpos - 64));\n            }\n        }\n        mp[key] += 1;\n    }\n\n    if (invalid) return -1;\n\n    int B[11];\n    memset(B, 0, sizeof(B));\n    for (auto &kv : mp) {\n        int s = kv.second;\n        if (1 <= s && s <= 10) B[s] += 1;\n    }\n\n    long long score = 0;\n    for (int d = 1; d <= 10; ++d) {\n        score += min((long long)a[d], (long long)B[d]);\n    }\n    return score;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, K;\n    if (!(cin >> N >> K)) return 0;\n    vector<int> a(11);\n    long long sumA = 0;\n    for (int d = 1; d <= 10; ++d) {\n        cin >> a[d];\n        sumA += a[d];\n    }\n    vector<pair<int,int>> pts(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> pts[i].first >> pts[i].second;\n    }\n\n    if (sumA == 0 || K == 0) {\n        cout << 0 << '\\n';\n        return 0;\n    }\n\n    // Average desired piece size\n    double avgD = (double)N / (double)sumA;\n\n    // Poisson fit on attendee-years distribution to tune lambda\n    vector<double> w(11, 0.0);\n    for (int d = 1; d <= 10; ++d) {\n        w[d] = (double)a[d] / (double)sumA;\n    }\n    double bestLambda = avgD;\n    double bestErr = 1e100;\n\n    for (double lambda = 1.0; lambda <= 8.0001; lambda += 0.1) {\n        double P[11];\n        P[0] = exp(-lambda);\n        double sum1to10 = 0.0;\n        for (int k = 1; k <= 10; ++k) {\n            P[k] = P[k-1] * lambda / k;\n            sum1to10 += P[k];\n        }\n        if (sum1to10 <= 0.0) continue;\n        double err = 0.0;\n        for (int d = 1; d <= 10; ++d) {\n            double q = P[d] / sum1to10;\n            double diff = q - w[d];\n            err += diff * diff;\n        }\n        if (err < bestErr) {\n            bestErr = err;\n            bestLambda = lambda;\n        }\n    }\n\n    double lambdaTarget = 0.5 * avgD + 0.5 * bestLambda;\n    lambdaTarget = max(2.0, min(8.0, lambdaTarget));\n\n    int cellsTarget = (int)llround((double)N / lambdaTarget);\n    if (cellsTarget < 1) cellsTarget = 1;\n\n    // Reserve some cuts for greedy improvement (reduce from 40 to 30 for better balance)\n    int Kextra = min(30, K / 2);   // up to 30 greedy cuts\n    if (Kextra < 0) Kextra = 0;\n    if (Kextra > K) Kextra = K;\n    int KgridLimit = max(0, K - Kextra);\n\n    // Determine grid sizes Nx, Ny with Nx + Ny <= KgridLimit\n    int bestNx = 0, bestNy = 0;\n    if (KgridLimit > 0) {\n        long long maxCellsPossible = 0;\n        for (int Nx = 0; Nx <= KgridLimit; ++Nx) {\n            int Ny = KgridLimit - Nx;\n            long long cells = 1LL * (Nx + 1) * (Ny + 1);\n            if (cells > maxCellsPossible) maxCellsPossible = cells;\n        }\n        if (cellsTarget > (int)maxCellsPossible) cellsTarget = (int)maxCellsPossible;\n\n        long long bestCellErr = (1LL << 60);\n        int bestSquarePenalty = (1 << 30);\n        for (int Nx = 0; Nx <= KgridLimit; ++Nx) {\n            for (int Ny = 0; Ny <= KgridLimit - Nx; ++Ny) {\n                long long cells = 1LL * (Nx + 1) * (Ny + 1);\n                long long err = llabs(cells - (long long)cellsTarget);\n                int squarePenalty = abs(Nx - Ny);\n                if (err < bestCellErr ||\n                    (err == bestCellErr && squarePenalty < bestSquarePenalty)) {\n                    bestCellErr = err;\n                    bestSquarePenalty = squarePenalty;\n                    bestNx = Nx;\n                    bestNy = Ny;\n                }\n            }\n        }\n    } else {\n        bestNx = bestNy = 0;\n    }\n\n    int Nx = bestNx;\n    int Ny = bestNy;\n\n    // Sorted coordinates for boundaries\n    vector<int> xs(N), ys(N);\n    for (int i = 0; i < N; ++i) {\n        xs[i] = pts[i].first;\n        ys[i] = pts[i].second;\n    }\n    sort(xs.begin(), xs.end());\n    sort(ys.begin(), ys.end());\n\n    // Build X boundaries\n    vector<int> xBoundaryCoord(N + 1);\n    vector<char> xBoundaryValid(N + 1, 0);\n    if (N > 0) {\n        int c0 = xs[0] - 1;\n        if (c0 < -RADIUS) c0 = -RADIUS;\n        xBoundaryCoord[0] = c0;\n        xBoundaryValid[0] = 1;\n\n        for (int b = 1; b <= N - 1; ++b) {\n            int left = xs[b-1];\n            int right = xs[b];\n            if (right - left >= 2) {\n                int c = (left + right) / 2;\n                xBoundaryCoord[b] = c;\n                xBoundaryValid[b] = 1;\n            } else {\n                xBoundaryValid[b] = 0;\n            }\n        }\n\n        int cN = xs[N-1] + 1;\n        if (cN > RADIUS) cN = RADIUS;\n        xBoundaryCoord[N] = cN;\n        xBoundaryValid[N] = 1;\n    }\n\n    // Build Y boundaries\n    vector<int> yBoundaryCoord(N + 1);\n    vector<char> yBoundaryValid(N + 1, 0);\n    if (N > 0) {\n        int c0 = ys[0] - 1;\n        if (c0 < -RADIUS) c0 = -RADIUS;\n        yBoundaryCoord[0] = c0;\n        yBoundaryValid[0] = 1;\n\n        for (int b = 1; b <= N - 1; ++b) {\n            int down = ys[b-1];\n            int up   = ys[b];\n            if (up - down >= 2) {\n                int c = (down + up) / 2;\n                yBoundaryCoord[b] = c;\n                yBoundaryValid[b] = 1;\n            } else {\n                yBoundaryValid[b] = 0;\n            }\n        }\n\n        int cN = ys[N-1] + 1;\n        if (cN > RADIUS) cN = RADIUS;\n        yBoundaryCoord[N] = cN;\n        yBoundaryValid[N] = 1;\n    }\n\n    // Quantile-based vertical and horizontal cuts\n    vector<int> xCuts = build_quantile_cuts(N, Nx, xs, xBoundaryCoord, xBoundaryValid);\n    vector<int> yCuts = build_quantile_cuts(N, Ny, ys, yBoundaryCoord, yBoundaryValid);\n\n    // Build initial line set (grid lines)\n    vector<Line> lines;\n    lines.reserve(K);\n    // vertical lines\n    for (int c : xCuts) {\n        Line L;\n        L.A = 1; L.B = 0; L.C = -c;\n        L.px = c; L.py = -BIG;\n        L.qx = c; L.qy =  BIG;\n        lines.push_back(L);\n    }\n    // horizontal lines\n    for (int c : yCuts) {\n        Line L;\n        L.A = 0; L.B = 1; L.C = -c;\n        L.px = -BIG; L.py = c;\n        L.qx =  BIG; L.qy = c;\n        lines.push_back(L);\n    }\n\n    int Lcur = (int)lines.size();\n\n    // Patterns for each strawberry\n    vector<uint64_t> patLo(N, 0), patHi(N, 0);\n    for (int i = 0; i < Lcur; ++i) {\n        const Line &L = lines[i];\n        for (int j = 0; j < N; ++j) {\n            long long x = pts[j].first;\n            long long y = pts[j].second;\n            long long val = L.A * x + L.B * y + L.C;\n            bool side = (val > 0);\n            if (side) {\n                int bitpos = i;\n                if (bitpos < 64) {\n                    patLo[j] |= (1ULL << bitpos);\n                } else {\n                    patHi[j] |= (1ULL << (bitpos - 64));\n                }\n            }\n        }\n    }\n\n    unordered_map<Pattern,int,PatternHash> mpCur, mpCand;\n    mpCur.reserve(N * 2);\n    mpCand.reserve(N * 2);\n\n    long long currentScore = compute_score_current(patLo, patHi, Lcur, a, mpCur);\n\n    // Random engine\n    uint64_t seed = 123456789ULL ^ (uint64_t)N;\n    if (N > 0) {\n        seed ^= (uint64_t)(pts[0].first * 1000003LL) ^ (uint64_t)(pts[0].second * 10007LL);\n    }\n    mt19937_64 rng(seed);\n    uniform_int_distribution<int> coordDist(-RADIUS, RADIUS);\n\n    const pair<int,int> offsets[8] = {\n        {1,0},{-1,0},{0,1},{0,-1},\n        {1,1},{-1,1},{1,-1},{-1,-1}\n    };\n\n    int usedExtra = 0;\n    const int CANDIDATES_PER_STEP = 35;  // evaluated per iteration\n    const int TRY_LIMIT_MULT = 4;        // tries up to CANDIDATES_PER_STEP * this\n\n    while (usedExtra < Kextra) {\n        // Recompute region partition for current lines\n        currentScore = compute_score_current(patLo, patHi, Lcur, a, mpCur);\n\n        // Collect large regions (patterns with many strawberries)\n        vector<pair<int,Pattern>> regions;\n        regions.reserve(mpCur.size());\n        for (auto &kv : mpCur) {\n            regions.emplace_back(kv.second, kv.first);\n        }\n        sort(regions.begin(), regions.end(),\n            [](const pair<int,Pattern> &x, const pair<int,Pattern> &y) {\n                return x.first > y.first;\n            });\n\n        const int MAX_BIG = 8;\n        const int MIN_BIG_SIZE = 10;\n        vector<Pattern> bigPatterns;\n        vector<vector<int>> bigIndices;\n        bigPatterns.reserve(MAX_BIG);\n        bigIndices.reserve(MAX_BIG);\n\n        for (int i = 0; i < (int)regions.size() && (int)bigPatterns.size() < MAX_BIG; ++i) {\n            int cnt = regions[i].first;\n            if (cnt < MIN_BIG_SIZE) break;\n            Pattern pat = regions[i].second;\n            bigPatterns.push_back(pat);\n        }\n\n        if (!bigPatterns.empty()) {\n            bigIndices.resize(bigPatterns.size());\n            for (int i = 0; i < N; ++i) {\n                Pattern p{patLo[i], patHi[i]};\n                for (int k = 0; k < (int)bigPatterns.size(); ++k) {\n                    if (p.lo == bigPatterns[k].lo && p.hi == bigPatterns[k].hi) {\n                        bigIndices[k].push_back(i);\n                        break;\n                    }\n                }\n            }\n        }\n\n        long long bestScoreIter = currentScore;\n        Line bestLine;\n        bool improved = false;\n\n        int validCandidates = 0;\n        int tries = 0;\n        int TRY_LIMIT = CANDIDATES_PER_STEP * TRY_LIMIT_MULT;\n\n        // Precompute cluster sizes for weighted choice\n        vector<int> clusterSizes;\n        int totalClusterSize = 0;\n        if (!bigIndices.empty()) {\n            clusterSizes.resize(bigIndices.size());\n            for (int k = 0; k < (int)bigIndices.size(); ++k) {\n                clusterSizes[k] = (int)bigIndices[k].size();\n                totalClusterSize += clusterSizes[k];\n            }\n        }\n\n        while (validCandidates < CANDIDATES_PER_STEP && tries < TRY_LIMIT) {\n            ++tries;\n            Line cand;\n            bool useCluster = (!bigIndices.empty() && (rng() % 4 != 0)); // ~3/4 cluster-based\n\n            if (useCluster) {\n                // Choose cluster weighted by size\n                if (totalClusterSize < 2) {\n                    useCluster = false;\n                } else {\n                    int r = (int)(rng() % totalClusterSize);\n                    int cid = 0;\n                    while (cid < (int)clusterSizes.size() && r >= clusterSizes[cid]) {\n                        r -= clusterSizes[cid];\n                        ++cid;\n                    }\n                    if (cid >= (int)bigIndices.size() || bigIndices[cid].size() < 2) {\n                        useCluster = false;\n                    } else {\n                        const vector<int> &idxs = bigIndices[cid];\n                        int sz = (int)idxs.size();\n                        int i1 = rng() % sz;\n                        int i2 = rng() % (sz - 1);\n                        if (i2 >= i1) ++i2;\n                        int pIdx = idxs[i1];\n                        int qIdx = idxs[i2];\n                        int x1 = pts[pIdx].first;\n                        int y1 = pts[pIdx].second;\n                        int x2 = pts[qIdx].first;\n                        int y2 = pts[qIdx].second;\n                        auto off = offsets[rng() & 7];\n                        int ox = off.first;\n                        int oy = off.second;\n                        cand.px = x1 + ox;\n                        cand.py = y1 + oy;\n                        cand.qx = x2 + ox;\n                        cand.qy = y2 + oy;\n                        if (cand.px == cand.qx && cand.py == cand.qy) {\n                            // degenerate, fall back to global\n                            useCluster = false;\n                        } else {\n                            long long X1 = cand.px, Y1 = cand.py;\n                            long long X2 = cand.qx, Y2 = cand.qy;\n                            cand.A = Y2 - Y1;\n                            cand.B = X1 - X2;\n                            cand.C = X2 * Y1 - X1 * Y2;\n                        }\n                    }\n                }\n            }\n\n            if (!useCluster) {\n                // Global random line\n                do {\n                    cand.px = coordDist(rng);\n                    cand.py = coordDist(rng);\n                    cand.qx = coordDist(rng);\n                    cand.qy = coordDist(rng);\n                } while (cand.px == cand.qx && cand.py == cand.qy);\n                long long x1 = cand.px, y1 = cand.py;\n                long long x2 = cand.qx, y2 = cand.qy;\n                cand.A = y2 - y1;\n                cand.B = x1 - x2;\n                cand.C = x2 * y1 - x1 * y2;\n                if (cand.A == 0 && cand.B == 0) continue;\n            }\n\n            long long candScore = evaluate_candidate(cand, patLo, patHi, Lcur, pts, a, mpCand);\n            if (candScore < 0) continue; // invalid (passes any strawberry)\n\n            ++validCandidates;\n            if (candScore > bestScoreIter) {\n                bestScoreIter = candScore;\n                bestLine = cand;\n                improved = true;\n            }\n        }\n\n        if (!improved) break;\n\n        // Commit best line\n        lines.push_back(bestLine);\n        int newIndex = Lcur;\n        ++Lcur;\n        ++usedExtra;\n\n        const Line &L = lines.back();\n        for (int j = 0; j < N; ++j) {\n            long long x = pts[j].first;\n            long long y = pts[j].second;\n            long long val = L.A * x + L.B * y + L.C;\n            // val == 0 should not happen (we avoided such lines in evaluate_candidate)\n            bool side = (val > 0);\n            if (side) {\n                if (newIndex < 64) {\n                    patLo[j] |= (1ULL << newIndex);\n                } else {\n                    patHi[j] |= (1ULL << (newIndex - 64));\n                }\n            }\n        }\n\n        currentScore = bestScoreIter;\n        if (Lcur >= K) break;\n    }\n\n    int totalCuts = (int)lines.size();\n    if (totalCuts > K) totalCuts = K;\n\n    cout << totalCuts << '\\n';\n    for (int i = 0; i < totalCuts; ++i) {\n        const Line &L = lines[i];\n        cout << L.px << ' ' << L.py << ' ' << L.qx << ' ' << L.qy << '\\n';\n    }\n\n    return 0;\n}","ahc014":"#include <bits/stdc++.h>\nusing namespace std;\n\n// =================== Constants & Globals ===================\n\nconst int MAXN = 65;  // N <= 61\n\nint N, M;\n\n// Board state\nstatic bool hasDot[MAXN][MAXN];      // [x][y]\nstatic bool horUsed[MAXN][MAXN];     // [y][x] edge from (x,y) to (x+1,y)\nstatic bool verUsed[MAXN][MAXN];     // [x][y] edge from (x,y) to (x,y+1)\nstatic bool diagUpUsed[MAXN][MAXN];  // [x][y] edge from (x,y) to (x+1,y+1)\nstatic bool diagDownUsed[MAXN][MAXN];// [x][y] edge from (x,y+1) to (x+1,y)\n\nstatic int rowPrefix[MAXN][MAXN+1];  // [y][i]: dots with x < i\nstatic int colPrefix[MAXN][MAXN+1];  // [x][i]: dots with y < i\nstatic int cellWeight[MAXN][MAXN];   // w(x,y)\n\n// Candidate type\nconstexpr uint8_t TYPE_AXIS = 0;\nconstexpr uint8_t TYPE_ROT  = 1;\n\n// Candidate rectangle\nstruct Candidate {\n    int weight;      // heuristic score for priority_queue\n    uint8_t type;    // 0: axis-aligned, 1: 45\u00b0 square\n    uint8_t px, py;  // new dot position\n    uint8_t pad;     // unused / padding\n    union {\n        struct { uint8_t xL, yB, xR, yT; } axis;\n        struct {\n            uint8_t vx[4];  // vertices in cyclic order\n            uint8_t vy[4];\n        } rot;\n    } u;\n};\n\nbool operator<(const Candidate &a, const Candidate &b) {\n    // max-heap by heuristic score\n    return a.weight < b.weight;\n}\n\n// Two queues: rotated first phase, then axis+rot together\npriority_queue<Candidate> pqAxis;\npriority_queue<Candidate> pqRot;\n\n// Move record\nstruct Move {\n    int x1, y1, x2, y2, x3, y3, x4, y4;\n};\n\nvector<Move> moves;\n\n// =================== Basic Operations ===================\n\ninline void addDot(int x, int y) {\n    if (hasDot[x][y]) return;\n    hasDot[x][y] = true;\n    for (int i = x + 1; i <= N; ++i) rowPrefix[y][i] += 1;\n    for (int i = y + 1; i <= N; ++i) colPrefix[x][i] += 1;\n}\n\n// =================== Axis-aligned Rectangles ===================\n\n// Generate all axis-aligned rectangles where the newly added dot is a vertex\n// and exactly three corners have dots (so the fourth is a candidate new dot).\ninline void updateAxisForNewDot(int x, int y) {\n    for (int x2 = 0; x2 < N; ++x2) {\n        if (x2 == x) continue;\n        int xL = (x2 < x) ? x2 : x;\n        int xR = (x2 < x) ? x : x2;\n        for (int y2 = 0; y2 < N; ++y2) {\n            if (y2 == y) continue;\n            int yB = (y2 < y) ? y2 : y;\n            int yT = (y2 < y) ? y : y2;\n\n            bool BL = hasDot[xL][yB];\n            bool BR = hasDot[xR][yB];\n            bool TR = hasDot[xR][yT];\n            bool TL = hasDot[xL][yT];\n            int cnt = BL + BR + TR + TL;\n            if (cnt != 3) continue;\n\n            int px, py;\n            if (!BL) { px = xL; py = yB; }\n            else if (!BR) { px = xR; py = yB; }\n            else if (!TR) { px = xR; py = yT; }\n            else { px = xL; py = yT; }\n\n            int w_new = cellWeight[px][py];\n\n            // sum weights of existing corners\n            int sumExisting = 0;\n            if (BL) sumExisting += cellWeight[xL][yB];\n            if (BR) sumExisting += cellWeight[xR][yB];\n            if (TR) sumExisting += cellWeight[xR][yT];\n            if (TL) sumExisting += cellWeight[xL][yT];\n\n            int width  = xR - xL;\n            int height = yT - yB;\n            int edges  = 2 * (width + height); // number of unit segments\n\n            // heuristic score\n            int score = w_new * 3000 + sumExisting * 5 - edges * 40;\n\n            Candidate c;\n            c.weight = score;\n            c.type   = TYPE_AXIS;\n            c.px = (uint8_t)px;\n            c.py = (uint8_t)py;\n            c.pad = 0;\n            c.u.axis.xL = (uint8_t)xL;\n            c.u.axis.yB = (uint8_t)yB;\n            c.u.axis.xR = (uint8_t)xR;\n            c.u.axis.yT = (uint8_t)yT;\n            pqAxis.push(c);\n        }\n    }\n}\n\ninline bool validateAxis(const Candidate &c) {\n    int px = c.px, py = c.py;\n    if (hasDot[px][py]) return false;\n\n    const auto &ax = c.u.axis;\n    int xL = ax.xL, xR = ax.xR;\n    int yB = ax.yB, yT = ax.yT;\n\n    // New point must be a corner\n    bool isCorner =\n        (px == xL && py == yB) ||\n        (px == xR && py == yB) ||\n        (px == xR && py == yT) ||\n        (px == xL && py == yT);\n    if (!isCorner) return false;\n\n    // Other three corners must have dots\n    if (!(px == xL && py == yB) && !hasDot[xL][yB]) return false;\n    if (!(px == xR && py == yB) && !hasDot[xR][yB]) return false;\n    if (!(px == xR && py == yT) && !hasDot[xR][yT]) return false;\n    if (!(px == xL && py == yT) && !hasDot[xL][yT]) return false;\n\n    // No extra dots on perimeter interior\n    if (xR - xL > 1) {\n        int sumBottom = rowPrefix[yB][xR] - rowPrefix[yB][xL + 1];\n        if (sumBottom > 0) return false;\n        int sumTop = rowPrefix[yT][xR] - rowPrefix[yT][xL + 1];\n        if (sumTop > 0) return false;\n    }\n    if (yT - yB > 1) {\n        int sumLeft  = colPrefix[xL][yT] - colPrefix[xL][yB + 1];\n        if (sumLeft > 0) return false;\n        int sumRight = colPrefix[xR][yT] - colPrefix[xR][yB + 1];\n        if (sumRight > 0) return false;\n    }\n\n    // No edges already used\n    for (int x = xL; x < xR; ++x) {\n        if (horUsed[yB][x]) return false;\n        if (horUsed[yT][x]) return false;\n    }\n    for (int y = yB; y < yT; ++y) {\n        if (verUsed[xL][y]) return false;\n        if (verUsed[xR][y]) return false;\n    }\n\n    return true;\n}\n\ninline void markEdgesAxis(const Candidate &c) {\n    const auto &ax = c.u.axis;\n    int xL = ax.xL, xR = ax.xR;\n    int yB = ax.yB, yT = ax.yT;\n    for (int x = xL; x < xR; ++x) {\n        horUsed[yB][x] = true;\n        horUsed[yT][x] = true;\n    }\n    for (int y = yB; y < yT; ++y) {\n        verUsed[xL][y] = true;\n        verUsed[xR][y] = true;\n    }\n}\n\n// =================== 45\u00b0 Rotated Squares (Diamonds) ===================\n\n// Generate 45\u00b0 squares where the newly added dot is one of the four vertices\n// and exactly three corners have dots (the fourth is a candidate new dot).\ninline void updateRotatedForNewDot(int x, int y) {\n    // Orientation 0: new dot is Up\n    {\n        for (int k = 1;; ++k) {\n            int rx = x + k;\n            int ry = y - k;\n            int dx = x;\n            int dy = y - 2 * k;\n            int lx = x - k;\n            int ly = y - k;\n            if (rx >= N || lx < 0 || dy < 0) break;\n\n            int vx[4] = {x,  rx, dx, lx};\n            int vy[4] = {y,  ry, dy, ly};\n            bool s[4];\n            s[0] = true;              // Up (new dot)\n            s[1] = hasDot[rx][ry];    // Right\n            s[2] = hasDot[dx][dy];    // Down\n            s[3] = hasDot[lx][ly];    // Left\n\n            int cnt = s[0] + s[1] + s[2] + s[3];\n            if (cnt != 3) continue;\n\n            int miss = -1;\n            for (int i = 0; i < 4; ++i) if (!s[i]) { miss = i; break; }\n            int px = vx[miss], py = vy[miss];\n            int w_new = cellWeight[px][py];\n\n            int sumExisting = 0;\n            for (int i = 0; i < 4; ++i)\n                if (s[i]) sumExisting += cellWeight[vx[i]][vy[i]];\n\n            int side = abs(vx[1] - vx[0]); // k\n            int edges = 4 * side;\n\n            int typeBonus = 2000;\n            int score = w_new * 3000 + sumExisting * 5 + typeBonus - edges * 40;\n\n            Candidate c;\n            c.weight = score;\n            c.type   = TYPE_ROT;\n            c.px = (uint8_t)px;\n            c.py = (uint8_t)py;\n            c.pad = 0;\n            for (int i = 0; i < 4; ++i) {\n                c.u.rot.vx[i] = (uint8_t)vx[i];\n                c.u.rot.vy[i] = (uint8_t)vy[i];\n            }\n            pqRot.push(c);\n        }\n    }\n\n    // Orientation 1: new dot is Right\n    {\n        for (int k = 1;; ++k) {\n            int ux = x - k;\n            int uy = y + k;\n            int dx = x - k;\n            int dy = y - k;\n            int lx = x - 2 * k;\n            int ly = y;\n            if (lx < 0 || ux < 0 || uy >= N || dy < 0) break;\n\n            int vx[4] = {ux, x,  dx, lx};\n            int vy[4] = {uy, y,  dy, ly};\n            bool s[4];\n            s[1] = true;              // Right (new dot)\n            s[0] = hasDot[ux][uy];    // Up\n            s[2] = hasDot[dx][dy];    // Down\n            s[3] = hasDot[lx][ly];    // Left\n\n            int cnt = s[0] + s[1] + s[2] + s[3];\n            if (cnt != 3) continue;\n\n            int miss = -1;\n            for (int i = 0; i < 4; ++i) if (!s[i]) { miss = i; break; }\n            int px = vx[miss], py = vy[miss];\n            int w_new = cellWeight[px][py];\n\n            int sumExisting = 0;\n            for (int i = 0; i < 4; ++i)\n                if (s[i]) sumExisting += cellWeight[vx[i]][vy[i]];\n\n            int side = abs(vx[1] - vx[0]); // k\n            int edges = 4 * side;\n\n            int typeBonus = 2000;\n            int score = w_new * 3000 + sumExisting * 5 + typeBonus - edges * 40;\n\n            Candidate c;\n            c.weight = score;\n            c.type   = TYPE_ROT;\n            c.px = (uint8_t)px;\n            c.py = (uint8_t)py;\n            c.pad = 0;\n            for (int i = 0; i < 4; ++i) {\n                c.u.rot.vx[i] = (uint8_t)vx[i];\n                c.u.rot.vy[i] = (uint8_t)vy[i];\n            }\n            pqRot.push(c);\n        }\n    }\n\n    // Orientation 2: new dot is Down\n    {\n        for (int k = 1;; ++k) {\n            int ux = x;\n            int uy = y + 2 * k;\n            int rx = x + k;\n            int ry = y + k;\n            int lx = x - k;\n            int ly = y + k;\n            if (uy >= N || rx >= N || lx < 0) break;\n\n            int vx[4] = {ux, rx, x,  lx};\n            int vy[4] = {uy, ry, y,  ly};\n            bool s[4];\n            s[2] = true;              // Down (new dot)\n            s[0] = hasDot[ux][uy];    // Up\n            s[1] = hasDot[rx][ry];    // Right\n            s[3] = hasDot[lx][ly];    // Left\n\n            int cnt = s[0] + s[1] + s[2] + s[3];\n            if (cnt != 3) continue;\n\n            int miss = -1;\n            for (int i = 0; i < 4; ++i) if (!s[i]) { miss = i; break; }\n            int px = vx[miss], py = vy[miss];\n            int w_new = cellWeight[px][py];\n\n            int sumExisting = 0;\n            for (int i = 0; i < 4; ++i)\n                if (s[i]) sumExisting += cellWeight[vx[i]][vy[i]];\n\n            int side = abs(vx[1] - vx[0]); // k\n            int edges = 4 * side;\n\n            int typeBonus = 2000;\n            int score = w_new * 3000 + sumExisting * 5 + typeBonus - edges * 40;\n\n            Candidate c;\n            c.weight = score;\n            c.type   = TYPE_ROT;\n            c.px = (uint8_t)px;\n            c.py = (uint8_t)py;\n            c.pad = 0;\n            for (int i = 0; i < 4; ++i) {\n                c.u.rot.vx[i] = (uint8_t)vx[i];\n                c.u.rot.vy[i] = (uint8_t)vy[i];\n            }\n            pqRot.push(c);\n        }\n    }\n\n    // Orientation 3: new dot is Left\n    {\n        for (int k = 1;; ++k) {\n            int ux = x + k;\n            int uy = y + k;\n            int rx = x + 2 * k;\n            int ry = y;\n            int dx = x + k;\n            int dy = y - k;\n            if (rx >= N || uy >= N || dy < 0) break;\n\n            int vx[4] = {ux, rx, dx, x};\n            int vy[4] = {uy, ry, dy, y};\n            bool s[4];\n            s[3] = true;              // Left (new dot)\n            s[0] = hasDot[ux][uy];    // Up\n            s[1] = hasDot[rx][ry];    // Right\n            s[2] = hasDot[dx][dy];    // Down\n\n            int cnt = s[0] + s[1] + s[2] + s[3];\n            if (cnt != 3) continue;\n\n            int miss = -1;\n            for (int i = 0; i < 4; ++i) if (!s[i]) { miss = i; break; }\n            int px = vx[miss], py = vy[miss];\n            int w_new = cellWeight[px][py];\n\n            int sumExisting = 0;\n            for (int i = 0; i < 4; ++i)\n                if (s[i]) sumExisting += cellWeight[vx[i]][vy[i]];\n\n            int side = abs(vx[1] - vx[0]); // k\n            int edges = 4 * side;\n\n            int typeBonus = 2000;\n            int score = w_new * 3000 + sumExisting * 5 + typeBonus - edges * 40;\n\n            Candidate c;\n            c.weight = score;\n            c.type   = TYPE_ROT;\n            c.px = (uint8_t)px;\n            c.py = (uint8_t)py;\n            c.pad = 0;\n            for (int i = 0; i < 4; ++i) {\n                c.u.rot.vx[i] = (uint8_t)vx[i];\n                c.u.rot.vy[i] = (uint8_t)vy[i];\n            }\n            pqRot.push(c);\n        }\n    }\n}\n\ninline bool validateRot(const Candidate &c) {\n    int px = c.px, py = c.py;\n    if (hasDot[px][py]) return false;\n\n    const auto &rt = c.u.rot;\n\n    // New point must be one of the vertices\n    int idx = -1;\n    for (int i = 0; i < 4; ++i) {\n        if (rt.vx[i] == px && rt.vy[i] == py) {\n            idx = i;\n            break;\n        }\n    }\n    if (idx == -1) return false;\n\n    // Other three vertices must have dots\n    for (int i = 0; i < 4; ++i) {\n        if (i == idx) continue;\n        int vx = rt.vx[i], vy = rt.vy[i];\n        if (!hasDot[vx][vy]) return false;\n    }\n\n    // Check edges: no extra dots on interior points and no reused diagonal segments\n    for (int e = 0; e < 4; ++e) {\n        int x1 = rt.vx[e];\n        int y1 = rt.vy[e];\n        int x2 = rt.vx[(e + 1) & 3];\n        int y2 = rt.vy[(e + 1) & 3];\n\n        int dx = x2 - x1;\n        int dy = y2 - y1;\n        int steps = abs(dx);\n        if (steps == 0) return false; // degenerate, shouldn't happen\n\n        int sxStep = (dx > 0) ? 1 : -1;\n        int syStep = (dy > 0) ? 1 : -1;\n\n        // Interior dots\n        for (int i = 1; i < steps; ++i) {\n            int qx = x1 + sxStep * i;\n            int qy = y1 + syStep * i;\n            if (hasDot[qx][qy]) return false;\n        }\n\n        bool slopeUp = ((long long)dx * dy > 0); // slope +1\n        if (slopeUp) {\n            int sx = min(x1, x2);\n            int sy = min(y1, y2);\n            for (int i = 0; i < steps; ++i) {\n                if (diagUpUsed[sx + i][sy + i]) return false;\n            }\n        } else {\n            int sx = min(x1, x2);\n            int sy = max(y1, y2);\n            for (int i = 0; i < steps; ++i) {\n                int bx = sx + i;\n                int by = sy - 1 - i; // segment from (bx,by+1) to (bx+1,by)\n                if (diagDownUsed[bx][by]) return false;\n            }\n        }\n    }\n\n    return true;\n}\n\ninline void markEdgesRot(const Candidate &c) {\n    const auto &rt = c.u.rot;\n\n    for (int e = 0; e < 4; ++e) {\n        int x1 = rt.vx[e];\n        int y1 = rt.vy[e];\n        int x2 = rt.vx[(e + 1) & 3];\n        int y2 = rt.vy[(e + 1) & 3];\n\n        int dx = x2 - x1;\n        int dy = y2 - y1;\n        int steps = abs(dx);\n        bool slopeUp = ((long long)dx * dy > 0);\n\n        if (slopeUp) {\n            int sx = min(x1, x2);\n            int sy = min(y1, y2);\n            for (int i = 0; i < steps; ++i) {\n                diagUpUsed[sx + i][sy + i] = true;\n            }\n        } else {\n            int sx = min(x1, x2);\n            int sy = max(y1, y2);\n            for (int i = 0; i < steps; ++i) {\n                int bx = sx + i;\n                int by = sy - 1 - i;\n                diagDownUsed[bx][by] = true;\n            }\n        }\n    }\n}\n\n// =================== Main ===================\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> M;\n    vector<pair<int,int>> initial(M);\n    for (int i = 0; i < M; ++i) {\n        int x, y;\n        cin >> x >> y;\n        initial[i] = {x, y};\n    }\n\n    // Precompute weights\n    int c = (N - 1) / 2;\n    for (int x = 0; x < N; ++x) {\n        for (int y = 0; y < N; ++y) {\n            int dx = x - c;\n            int dy = y - c;\n            cellWeight[x][y] = dx * dx + dy * dy + 1;\n        }\n    }\n\n    // Add initial dots and generate initial candidates\n    for (int i = 0; i < M; ++i) {\n        int x = initial[i].first;\n        int y = initial[i].second;\n        addDot(x, y);\n        updateAxisForNewDot(x, y);\n        updateRotatedForNewDot(x, y);\n    }\n\n    auto start_time = chrono::steady_clock::now();\n    const double TOTAL_TIME_LIMIT = 4.8;  // safety margin\n    const double ROT_PHASE_RATIO  = 0.5;  // first half time for rotated-only\n    const double ROT_PHASE_LIMIT  = TOTAL_TIME_LIMIT * ROT_PHASE_RATIO;\n\n    int iter = 0;\n\n    // Phase 1: use only rotated candidates\n    while (!pqRot.empty()) {\n        if ((iter & 0xFF) == 0) {\n            double elapsed = chrono::duration<double>(\n                                 chrono::steady_clock::now() - start_time\n                             ).count();\n            if (elapsed > ROT_PHASE_LIMIT) break;\n        }\n        ++iter;\n\n        Candidate cand = pqRot.top();\n        pqRot.pop();\n\n        if (!validateRot(cand)) continue;\n\n        // Commit rotated rectangle\n        markEdgesRot(cand);\n        int px = cand.px;\n        int py = cand.py;\n        addDot(px, py);\n        updateAxisForNewDot(px, py);\n        updateRotatedForNewDot(px, py);\n\n        const auto &rt = cand.u.rot;\n        int idx = 0;\n        for (; idx < 4; ++idx) {\n            if (rt.vx[idx] == px && rt.vy[idx] == py) break;\n        }\n        if (idx == 4) idx = 0; // fallback (should not happen)\n\n        int x1 = rt.vx[idx],           y1 = rt.vy[idx];\n        int x2 = rt.vx[(idx + 1) & 3], y2 = rt.vy[(idx + 1) & 3];\n        int x3 = rt.vx[(idx + 2) & 3], y3 = rt.vy[(idx + 2) & 3];\n        int x4 = rt.vx[(idx + 3) & 3], y4 = rt.vy[(idx + 3) & 3];\n        moves.push_back({x1, y1, x2, y2, x3, y3, x4, y4});\n    }\n\n    // Phase 2: both rotated and axis candidates, choose best by score\n    while (!pqRot.empty() || !pqAxis.empty()) {\n        if ((iter & 0xFF) == 0) {\n            double elapsed = chrono::duration<double>(\n                                 chrono::steady_clock::now() - start_time\n                             ).count();\n            if (elapsed > TOTAL_TIME_LIMIT) break;\n        }\n        ++iter;\n\n        bool chooseRot;\n        if (pqRot.empty()) chooseRot = false;\n        else if (pqAxis.empty()) chooseRot = true;\n        else chooseRot = (pqRot.top().weight >= pqAxis.top().weight);\n\n        Candidate cand = chooseRot ? pqRot.top() : pqAxis.top();\n        if (chooseRot) pqRot.pop(); else pqAxis.pop();\n\n        if (cand.type == TYPE_AXIS) {\n            if (!validateAxis(cand)) continue;\n\n            // Commit axis-aligned rectangle\n            markEdgesAxis(cand);\n            int px = cand.px;\n            int py = cand.py;\n            addDot(px, py);\n            updateAxisForNewDot(px, py);\n            updateRotatedForNewDot(px, py);\n\n            const auto &ax = cand.u.axis;\n            int xL = ax.xL, xR = ax.xR;\n            int yB = ax.yB, yT = ax.yT;\n\n            int ax0 = xL, ay0 = yB;\n            int bx0 = xR, by0 = yB;\n            int cx0 = xR, cy0 = yT;\n            int dx0 = xL, dy0 = yT;\n\n            Move m;\n            if (px == ax0 && py == ay0) {\n                m = {ax0, ay0, bx0, by0, cx0, cy0, dx0, dy0};\n            } else if (px == bx0 && py == by0) {\n                m = {bx0, by0, cx0, cy0, dx0, dy0, ax0, ay0};\n            } else if (px == cx0 && py == cy0) {\n                m = {cx0, cy0, dx0, dy0, ax0, ay0, bx0, by0};\n            } else {\n                m = {dx0, dy0, ax0, ay0, bx0, by0, cx0, cy0};\n            }\n            moves.push_back(m);\n\n        } else { // TYPE_ROT\n            if (!validateRot(cand)) continue;\n\n            // Commit rotated rectangle\n            markEdgesRot(cand);\n            int px = cand.px;\n            int py = cand.py;\n            addDot(px, py);\n            updateAxisForNewDot(px, py);\n            updateRotatedForNewDot(px, py);\n\n            const auto &rt = cand.u.rot;\n            int idx = 0;\n            for (; idx < 4; ++idx) {\n                if (rt.vx[idx] == px && rt.vy[idx] == py) break;\n            }\n            if (idx == 4) idx = 0; // fallback (should not happen)\n\n            int x1 = rt.vx[idx],           y1 = rt.vy[idx];\n            int x2 = rt.vx[(idx + 1) & 3], y2 = rt.vy[(idx + 1) & 3];\n            int x3 = rt.vx[(idx + 2) & 3], y3 = rt.vy[(idx + 2) & 3];\n            int x4 = rt.vx[(idx + 3) & 3], y4 = rt.vy[(idx + 3) & 3];\n            moves.push_back({x1, y1, x2, y2, x3, y3, x4, y4});\n        }\n    }\n\n    // Output\n    cout << moves.size() << '\\n';\n    for (const auto &m : moves) {\n        cout << m.x1 << ' ' << m.y1 << ' '\n             << m.x2 << ' ' << m.y2 << ' '\n             << m.x3 << ' ' << m.y3 << ' '\n             << m.x4 << ' ' << m.y4 << '\\n';\n    }\n\n    return 0;\n}","ahc015":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const int N = 10;\n\n// Monte Carlo samples\nstatic const int K0 = 2; // samples for 3-step lookahead (very early game)\nstatic const int K1 = 3; // samples for 2-step lookahead (early/mid game)\nstatic const int K2 = 5; // samples for 1-step lookahead (late game)\n\nstruct Board {\n    uint8_t a[N][N];\n    Board() { memset(a, 0, sizeof(a)); }\n};\n\n// Tilt directions: 0 = F, 1 = B, 2 = L, 3 = R\nvoid tilt(Board &b, int dir) {\n    if (dir == 0) { // F: move toward row 0\n        for (int c = 0; c < N; c++) {\n            int pos = 0;\n            for (int r = 0; r < N; r++) {\n                uint8_t v = b.a[r][c];\n                if (v) {\n                    if (pos != r) b.a[pos][c] = v;\n                    pos++;\n                }\n            }\n            for (int r = pos; r < N; r++) b.a[r][c] = 0;\n        }\n    } else if (dir == 1) { // B: move toward row 9\n        for (int c = 0; c < N; c++) {\n            int pos = N - 1;\n            for (int r = N - 1; r >= 0; r--) {\n                uint8_t v = b.a[r][c];\n                if (v) {\n                    if (pos != r) b.a[pos][c] = v;\n                    pos--;\n                }\n            }\n            for (int r = pos; r >= 0; r--) b.a[r][c] = 0;\n        }\n    } else if (dir == 2) { // L: move toward col 0\n        for (int r = 0; r < N; r++) {\n            int pos = 0;\n            for (int c = 0; c < N; c++) {\n                uint8_t v = b.a[r][c];\n                if (v) {\n                    if (pos != c) b.a[r][pos] = v;\n                    pos++;\n                }\n            }\n            for (int c = pos; c < N; c++) b.a[r][c] = 0;\n        }\n    } else { // R: move toward col 9\n        for (int r = 0; r < N; r++) {\n            int pos = N - 1;\n            for (int c = N - 1; c >= 0; c--) {\n                uint8_t v = b.a[r][c];\n                if (v) {\n                    if (pos != c) b.a[r][pos] = v;\n                    pos--;\n                }\n            }\n            for (int c = pos; c >= 0; c--) b.a[r][c] = 0;\n        }\n    }\n}\n\n// Sum of squared sizes of same-color connected components (4-neighbor)\nlong long evaluate(const Board &b) {\n    static uint32_t vis[N][N];\n    static uint32_t curMark = 1;\n    curMark++;\n\n    static const int dr[4] = {1, -1, 0, 0};\n    static const int dc[4] = {0, 0, 1, -1};\n    int qx[100], qy[100];\n    long long score = 0;\n\n    for (int r = 0; r < N; r++) {\n        for (int c = 0; c < N; c++) {\n            uint8_t color = b.a[r][c];\n            if (color != 0 && vis[r][c] != curMark) {\n                int head = 0, tail = 0;\n                qx[tail] = r;\n                qy[tail] = c;\n                tail++;\n                vis[r][c] = curMark;\n                int cnt = 0;\n\n                while (head < tail) {\n                    int x = qx[head];\n                    int y = qy[head];\n                    head++;\n                    cnt++;\n\n                    for (int k = 0; k < 4; k++) {\n                        int nx = x + dr[k];\n                        int ny = y + dc[k];\n                        if (0 <= nx && nx < N && 0 <= ny && ny < N) {\n                            if (b.a[nx][ny] == color && vis[nx][ny] != curMark) {\n                                vis[nx][ny] = curMark;\n                                qx[tail] = nx;\n                                qy[tail] = ny;\n                                tail++;\n                            }\n                        }\n                    }\n                }\n                score += 1LL * cnt * cnt;\n            }\n        }\n    }\n    return score;\n}\n\n// Simple spatial bias: distance of each color to its target corner\n// color 1 -> (0,0), color 2 -> (0,9), color 3 -> (9,0)\nint corner_distance(const Board &b) {\n    static const int tr[4] = {0, 0, 0, 9};\n    static const int tc[4] = {0, 0, 9, 0};\n    int dist = 0;\n    for (int r = 0; r < N; r++) {\n        for (int c = 0; c < N; c++) {\n            uint8_t col = b.a[r][c];\n            if (col >= 1 && col <= 3) {\n                dist += abs(r - tr[col]) + abs(c - tc[col]);\n            }\n        }\n    }\n    return dist;\n}\n\n// Find p-th empty cell (1-based) in front-to-back, left-to-right order\npair<int,int> findPos(const Board &b, int p) {\n    int cnt = 0;\n    for (int r = 0; r < N; r++) {\n        for (int c = 0; c < N; c++) {\n            if (b.a[r][c] == 0) {\n                cnt++;\n                if (cnt == p) return {r, c};\n            }\n        }\n    }\n    return {-1, -1}; // should not happen\n}\n\n// Choose a random empty cell uniformly from current board\npair<int,int> randomEmptyCell(const Board &b, mt19937_64 &rng) {\n    int empties = 0;\n    for (int r = 0; r < N; r++) {\n        for (int c = 0; c < N; c++) {\n            if (b.a[r][c] == 0) empties++;\n        }\n    }\n    // Should never be called with empties == 0\n    uint64_t x = rng();\n    int k = (int)(x % empties); // 0..empties-1\n    int cnt = 0;\n    for (int r = 0; r < N; r++) {\n        for (int c = 0; c < N; c++) {\n            if (b.a[r][c] == 0) {\n                if (cnt == k) return {r, c};\n                cnt++;\n            }\n        }\n    }\n    return {0, 0}; // fallback, should not occur\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // Read flavor sequence\n    vector<int> f(100);\n    for (int i = 0; i < 100; i++) {\n        if (!(cin >> f[i])) return 0;\n    }\n\n    Board cur;\n    const char DIR_CH[4] = {'F', 'B', 'L', 'R'};\n    mt19937_64 rng(712367821ull); // fixed seed for deterministic behavior\n\n    for (int t = 0; t < 100; t++) {\n        int p;\n        if (!(cin >> p)) return 0;\n\n        // Place current candy\n        auto [r, c] = findPos(cur, p);\n        if (r == -1) return 0; // safety\n        cur.a[r][c] = (uint8_t)f[t];\n\n        long long bestScore = LLONG_MIN;\n        long long bestS0 = -1;\n        int bestDist = INT_MAX;\n        int bestDir = 0;\n        Board bestBoard;\n\n        int remain = 99 - t; // number of future candies after this step\n\n        if (remain >= 3 && t <= 25) {\n            // Very early game: 3-step lookahead with K0 samples\n            for (int dir0 = 0; dir0 < 4; dir0++) {\n                Board b1 = cur;\n                tilt(b1, dir0);\n                long long S0 = evaluate(b1);\n                int dist0 = corner_distance(b1);\n                long long sum1 = 0, sum2 = 0, sum3 = 0;\n\n                for (int s = 0; s < K0; s++) {\n                    // Step t+1 simulation\n                    Board sim1 = b1;\n                    auto [r1, c1] = randomEmptyCell(sim1, rng);\n                    sim1.a[r1][c1] = (uint8_t)f[t + 1];\n\n                    long long best1 = LLONG_MIN;\n                    Board b2best;\n                    for (int dir1 = 0; dir1 < 4; dir1++) {\n                        Board b2 = sim1;\n                        tilt(b2, dir1);\n                        long long sc1 = evaluate(b2);\n                        if (sc1 > best1) {\n                            best1 = sc1;\n                            b2best = b2;\n                        }\n                    }\n                    sum1 += best1;\n\n                    // Step t+2 simulation\n                    Board sim2 = b2best;\n                    auto [r2, c2] = randomEmptyCell(sim2, rng);\n                    sim2.a[r2][c2] = (uint8_t)f[t + 2];\n\n                    long long best2 = LLONG_MIN;\n                    Board b3best;\n                    for (int dir2 = 0; dir2 < 4; dir2++) {\n                        Board b3 = sim2;\n                        tilt(b3, dir2);\n                        long long sc2 = evaluate(b3);\n                        if (sc2 > best2) {\n                            best2 = sc2;\n                            b3best = b3;\n                        }\n                    }\n                    sum2 += best2;\n\n                    // Step t+3 simulation\n                    Board sim3 = b3best;\n                    auto [r3, c3] = randomEmptyCell(sim3, rng);\n                    sim3.a[r3][c3] = (uint8_t)f[t + 3];\n\n                    long long best3 = LLONG_MIN;\n                    for (int dir3 = 0; dir3 < 4; dir3++) {\n                        Board b4 = sim3;\n                        tilt(b4, dir3);\n                        long long sc3 = evaluate(b4);\n                        if (sc3 > best3) {\n                            best3 = sc3;\n                        }\n                    }\n                    sum3 += best3;\n                }\n\n                // Approximate S0 + E[S1] + E[S2] + E[S3]\n                long long scoreValue = S0 * K0 + sum1 + sum2 + sum3;\n\n                if (scoreValue > bestScore ||\n                    (scoreValue == bestScore && (S0 > bestS0 ||\n                    (S0 == bestS0 && dist0 < bestDist)))) {\n                    bestScore = scoreValue;\n                    bestS0 = S0;\n                    bestDist = dist0;\n                    bestDir = dir0;\n                    bestBoard = b1;\n                }\n            }\n        } else if (remain >= 2 && t <= 60) {\n            // Early/mid game: 2-step lookahead with K1 samples\n            for (int dir0 = 0; dir0 < 4; dir0++) {\n                Board b1 = cur;\n                tilt(b1, dir0);\n                long long S0 = evaluate(b1);\n                int dist0 = corner_distance(b1);\n                long long sum1 = 0, sum2 = 0;\n\n                for (int s = 0; s < K1; s++) {\n                    // Step t+1 simulation\n                    Board sim1 = b1;\n                    auto [r1, c1] = randomEmptyCell(sim1, rng);\n                    sim1.a[r1][c1] = (uint8_t)f[t + 1];\n\n                    long long best1 = LLONG_MIN;\n                    Board b2best;\n                    for (int dir1 = 0; dir1 < 4; dir1++) {\n                        Board b2 = sim1;\n                        tilt(b2, dir1);\n                        long long sc1 = evaluate(b2);\n                        if (sc1 > best1) {\n                            best1 = sc1;\n                            b2best = b2;\n                        }\n                    }\n                    sum1 += best1;\n\n                    // Step t+2 simulation\n                    Board sim2 = b2best;\n                    auto [r2, c2] = randomEmptyCell(sim2, rng);\n                    sim2.a[r2][c2] = (uint8_t)f[t + 2];\n\n                    long long best2 = LLONG_MIN;\n                    for (int dir2 = 0; dir2 < 4; dir2++) {\n                        Board b3 = sim2;\n                        tilt(b3, dir2);\n                        long long sc2 = evaluate(b3);\n                        if (sc2 > best2) {\n                            best2 = sc2;\n                        }\n                    }\n                    sum2 += best2;\n                }\n\n                // Approximate S0 + E[S1] + E[S2]\n                long long scoreValue = S0 * K1 + sum1 + sum2;\n\n                if (scoreValue > bestScore ||\n                    (scoreValue == bestScore && (S0 > bestS0 ||\n                    (S0 == bestS0 && dist0 < bestDist)))) {\n                    bestScore = scoreValue;\n                    bestS0 = S0;\n                    bestDist = dist0;\n                    bestDir = dir0;\n                    bestBoard = b1;\n                }\n            }\n        } else if (remain >= 1) {\n            // Late game: 1-step lookahead with K2 samples\n            for (int dir0 = 0; dir0 < 4; dir0++) {\n                Board b1 = cur;\n                tilt(b1, dir0);\n                long long S0 = evaluate(b1);\n                int dist0 = corner_distance(b1);\n                long long sum1 = 0;\n\n                for (int s = 0; s < K2; s++) {\n                    Board sim1 = b1;\n                    auto [r1, c1] = randomEmptyCell(sim1, rng);\n                    sim1.a[r1][c1] = (uint8_t)f[t + 1];\n\n                    long long best1 = LLONG_MIN;\n                    for (int dir1 = 0; dir1 < 4; dir1++) {\n                        Board b2 = sim1;\n                        tilt(b2, dir1);\n                        long long sc1 = evaluate(b2);\n                        if (sc1 > best1) {\n                            best1 = sc1;\n                        }\n                    }\n                    sum1 += best1;\n                }\n\n                // Approximate S0 + E[S1]\n                long long scoreValue = S0 * K2 + sum1;\n\n                if (scoreValue > bestScore ||\n                    (scoreValue == bestScore && (S0 > bestS0 ||\n                    (S0 == bestS0 && dist0 < bestDist)))) {\n                    bestScore = scoreValue;\n                    bestS0 = S0;\n                    bestDist = dist0;\n                    bestDir = dir0;\n                    bestBoard = b1;\n                }\n            }\n        } else {\n            // Last step: no future candies; only immediate score matters\n            for (int dir0 = 0; dir0 < 4; dir0++) {\n                Board b1 = cur;\n                tilt(b1, dir0);\n                long long S0 = evaluate(b1);\n                int dist0 = corner_distance(b1);\n                long long scoreValue = S0;\n\n                if (scoreValue > bestScore ||\n                    (scoreValue == bestScore && (S0 > bestS0 ||\n                    (S0 == bestS0 && dist0 < bestDist)))) {\n                    bestScore = scoreValue;\n                    bestS0 = S0;\n                    bestDist = dist0;\n                    bestDir = dir0;\n                    bestBoard = b1;\n                }\n            }\n        }\n\n        cur = bestBoard;\n        cout << DIR_CH[bestDir] << '\\n' << flush;\n    }\n\n    return 0;\n}","ahc016":"#include <bits/stdc++.h>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int M;\n    double eps;\n    if (!(cin >> M >> eps)) return 0;\n\n    bool noNoise = (eps < 0.0005);  // eps is multiple of 0.01, so this is eps == 0\n\n    int N = 4;\n    int L = 0;\n\n    if (noNoise) {\n        // eps = 0: choose minimum N such that L >= M\n        while (N < 100) {\n            L = N * (N - 1) / 2;\n            if (L >= M) break;\n            ++N;\n        }\n        L = N * (N - 1) / 2;\n    } else {\n        // eps > 0: choose N using linear + SNR-based constraints\n        const double baseC0 = 6.0;\n        const double baseC1 = 60.0;\n        double L1 = (baseC0 + baseC1 * eps) * M;\n\n        // SNR-based constraint: require separation r0 in units of sigma\n        const double r0 = 4.0;\n        double den = 1.0 - 2.0 * eps;\n        den *= den;\n        double L2;\n        if (den < 1e-12) {\n            // For eps extremely close to 0.5 (not in given constraints), just force max L\n            L2 = 1e18;\n        } else {\n            double alpha2 = (r0 * r0 * eps * (1.0 - eps)) / den;\n            L2 = alpha2 * (M + 1.0) * (M + 1.0);\n        }\n\n        double targetL = max(L1, L2);\n        // Need at least M+1 distinct total edge counts\n        if (targetL < M + 1.0) targetL = M + 1.0;\n        // Cap by maximum possible L (N <= 100)\n        if (targetL > 4950.0) targetL = 4950.0;\n\n        N = 4;\n        while (N < 100) {\n            L = N * (N - 1) / 2;\n            if ((double)L >= targetL) break;\n            ++N;\n        }\n        L = N * (N - 1) / 2;\n    }\n\n    // Decide edge counts m_k\n    vector<int> mEdges(M);\n\n    if (noNoise) {\n        // eps = 0: simply use m_k = k (0..M-1), since L >= M\n        for (int k = 0; k < M; ++k) {\n            mEdges[k] = k;\n        }\n    } else {\n        // eps > 0: spread m_k approximately evenly across 1..L-1\n        for (int k = 0; k < M; ++k) {\n            long long num = 1LL * (k + 1) * L;\n            int mk = (int)(num / (M + 1));  // floor\n            if (mk <= 0) mk = 1;\n            if (mk >= L) mk = L - 1;\n            mEdges[k] = mk;\n        }\n        // Ensure strictly increasing in [1, L-1]\n        if (mEdges[0] <= 0) mEdges[0] = 1;\n        for (int k = 1; k < M; ++k) {\n            if (mEdges[k] <= mEdges[k - 1]) {\n                mEdges[k] = mEdges[k - 1] + 1;\n                if (mEdges[k] >= L) mEdges[k] = L - 1;\n            }\n        }\n    }\n\n    // Precompute mapping from edge index (0..L-1) to (u,v)\n    vector<int> edgeU(L), edgeV(L);\n    {\n        int pos = 0;\n        for (int i = 0; i < N; ++i) {\n            for (int j = i + 1; j < N; ++j) {\n                edgeU[pos] = i;\n                edgeV[pos] = j;\n                ++pos;\n            }\n        }\n    }\n\n    // Precompute expected noisy edge counts for eps > 0\n    vector<double> muEdges;\n    double a = 1.0 - 2.0 * eps;\n    double b = eps * L;\n    if (!noNoise) {\n        muEdges.resize(M);\n        for (int k = 0; k < M; ++k) {\n            muEdges[k] = a * (double)mEdges[k] + b;\n        }\n    }\n\n    // For eps > 0, also precompute expected sorted degree sequences for each G_k\n    vector<vector<double>> muDegSorted;  // size M x N\n    if (!noNoise) {\n        muDegSorted.assign(M, vector<double>(N));\n        vector<int> deg(N);\n        vector<int> idx(N);\n        double shiftDeg = eps * (N - 1);\n        for (int k = 0; k < M; ++k) {\n            // Build degree sequence for graph G_k with \"first mEdges[k] bits = 1\"\n            fill(deg.begin(), deg.end(), 0);\n            int mk = mEdges[k];\n            for (int pos = 0; pos < mk; ++pos) {\n                int u = edgeU[pos];\n                int v = edgeV[pos];\n                ++deg[u];\n                ++deg[v];\n            }\n            // Sort vertices by degree\n            iota(idx.begin(), idx.end(), 0);\n            sort(idx.begin(), idx.end(), [&](int u, int v) {\n                if (deg[u] != deg[v]) return deg[u] < deg[v];\n                return u < v;\n            });\n            // Store expected degrees after noise in sorted order\n            for (int r = 0; r < N; ++r) {\n                int v = idx[r];\n                muDegSorted[k][r] = a * (double)deg[v] + shiftDeg;\n            }\n        }\n    }\n\n    // Output N and graphs as bitstrings of length L\n    cout << N << '\\n';\n    for (int k = 0; k < M; ++k) {\n        int mk = mEdges[k];\n        string s(L, '0');\n        for (int i = 0; i < mk; ++i) s[i] = '1';\n        cout << s << '\\n';\n    }\n    cout.flush();\n\n    // If eps = 0, build direct map from edge count to index and answer queries via edges only\n    if (noNoise) {\n        vector<int> edgeToIndex(L + 1, -1);\n        for (int k = 0; k < M; ++k) {\n            int mk = mEdges[k];\n            if (0 <= mk && mk <= L) edgeToIndex[mk] = k;\n        }\n\n        for (int q = 0; q < 100; ++q) {\n            string H;\n            if (!(cin >> H)) return 0;\n\n            int mPrime = 0;\n            for (char c : H) if (c == '1') ++mPrime;\n\n            int bestK = 0;\n            if (mPrime >= 0 && mPrime <= L && edgeToIndex[mPrime] != -1) {\n                bestK = edgeToIndex[mPrime];\n            } else {\n                // Very unlikely fallback: choose nearest in mEdges\n                int bestDiff = INT_MAX;\n                for (int k = 0; k < M; ++k) {\n                    int diff = abs(mPrime - mEdges[k]);\n                    if (diff < bestDiff) {\n                        bestDiff = diff;\n                        bestK = k;\n                    }\n                }\n            }\n\n            cout << bestK << '\\n';\n            cout.flush();\n        }\n        return 0;\n    }\n\n    // eps > 0: prepare degree-related constants\n    double var_m = (double)L * eps * (1.0 - eps);\n    double sigma_m = sqrt(max(var_m, 1e-9));\n    double var_deg = (double)(N - 1) * eps * (1.0 - eps);\n    double sigma_deg = sqrt(max(var_deg, 1e-9));\n\n    // Small weight for degree term (edges stay main signal)\n    const double lambda_deg = 0.05;\n\n    // Buffers for queries\n    vector<int> degH(N), idxH(N), degSortedH(N);\n\n    // Process 100 queries\n    for (int q = 0; q < 100; ++q) {\n        string H;\n        if (!(cin >> H)) return 0;\n\n        int mPrime = 0;\n        fill(degH.begin(), degH.end(), 0);\n\n        // Count edges and compute degrees in H\n        for (int pos = 0; pos < L; ++pos) {\n            if (H[pos] == '1') {\n                ++mPrime;\n                int u = edgeU[pos];\n                int v = edgeV[pos];\n                ++degH[u];\n                ++degH[v];\n            }\n        }\n\n        // Sorted degrees in H\n        iota(idxH.begin(), idxH.end(), 0);\n        sort(idxH.begin(), idxH.end(), [&](int u, int v) {\n            if (degH[u] != degH[v]) return degH[u] < degH[v];\n            return u < v;\n        });\n        for (int r = 0; r < N; ++r) {\n            degSortedH[r] = degH[idxH[r]];\n        }\n\n        int bestK = 0;\n        double bestCost = 1e300;\n\n        for (int k = 0; k < M; ++k) {\n            // Edge-count contribution (Gaussian z-score squared)\n            double deltaE = ((double)mPrime - muEdges[k]) / sigma_m;\n            double cost = deltaE * deltaE;\n\n            // Degree distribution contribution\n            const vector<double> &muDeg = muDegSorted[k];\n            double sumZ2 = 0.0;\n            for (int r = 0; r < N; ++r) {\n                double z = ((double)degSortedH[r] - muDeg[r]) / sigma_deg;\n                sumZ2 += z * z;\n            }\n            cost += lambda_deg * (sumZ2 / (double)N);\n\n            if (cost < bestCost) {\n                bestCost = cost;\n                bestK = k;\n            }\n        }\n\n        cout << bestK << '\\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 id;\n    int w;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, D, K;\n    if (!(cin >> N >> M >> D >> K)) return 0;\n\n    vector<int> U(M), V(M), W(M);\n    for (int i = 0; i < M; i++) {\n        cin >> U[i] >> V[i] >> W[i];\n        --U[i];\n        --V[i];\n    }\n    // Coordinates are unused by the algorithm\n    for (int i = 0; i < N; i++) {\n        int x, y;\n        cin >> x >> y;\n    }\n\n    // Build adjacency list\n    vector<vector<AdjEdge>> g(N);\n    for (int i = 0; i < M; i++) {\n        int u = U[i], v = V[i], w = W[i];\n        g[u].push_back({v, i, w});\n        g[v].push_back({u, i, w});\n    }\n\n    mt19937_64 rng(123456789);\n\n    // ---------------------- Step 1: Betweenness-like centrality -------------------------\n    int S_c = min(N, 60); // sampled sources for centrality\n    vector<int> perm(N);\n    iota(perm.begin(), perm.end(), 0);\n    shuffle(perm.begin(), perm.end(), rng);\n    vector<int> sources_c(S_c);\n    for (int i = 0; i < S_c; i++) sources_c[i] = perm[i];\n\n    vector<double> central(M, 0.0);\n\n    const long long INFLL = (1LL << 60);\n    vector<long long> distLL(N);\n    vector<int> parent_v(N), parent_e(N);\n    vector<int> order;\n    order.reserve(N);\n\n    using PQItem = pair<long long, int>;\n\n    for (int s : sources_c) {\n        fill(distLL.begin(), distLL.end(), INFLL);\n        fill(parent_v.begin(), parent_v.end(), -1);\n        fill(parent_e.begin(), parent_e.end(), -1);\n        order.clear();\n\n        priority_queue<PQItem, vector<PQItem>, greater<PQItem>> pq;\n        distLL[s] = 0;\n        pq.emplace(0, s);\n\n        while (!pq.empty()) {\n            auto [d, v] = pq.top();\n            pq.pop();\n            if (d != distLL[v]) continue;\n            order.push_back(v);\n            for (const auto &e : g[v]) {\n                int to = e.to;\n                long long nd = d + e.w;\n                if (nd < distLL[to]) {\n                    distLL[to] = nd;\n                    parent_v[to] = v;\n                    parent_e[to] = e.id;\n                    pq.emplace(nd, to);\n                }\n            }\n        }\n\n        // Tree DP to accumulate centrality\n        vector<int> sz(N, 1);\n        for (int i = (int)order.size() - 1; i >= 0; --i) {\n            int v = order[i];\n            int pv = parent_v[v];\n            if (pv == -1) continue;\n            int eid = parent_e[v];\n            central[eid] += sz[v];\n            sz[pv] += sz[v];\n        }\n    }\n\n    // ---------------------- Step 2: Alternative-path detour per edge ---------------------\n    vector<long long> altDiff(M, 1); // altDist - W[e], at least 1\n    const long long INF_COST = 1000000000LL;\n\n    for (int eid = 0; eid < M; eid++) {\n        int src = U[eid];\n        int tgt = V[eid];\n\n        fill(distLL.begin(), distLL.end(), INF_COST);\n        priority_queue<PQItem, vector<PQItem>, greater<PQItem>> pq;\n        distLL[src] = 0;\n        pq.emplace(0, src);\n\n        while (!pq.empty()) {\n            auto [d, v] = pq.top();\n            pq.pop();\n            if (d != distLL[v]) continue;\n            if (v == tgt) break; // reached target with minimal distance\n            for (const auto &ed : g[v]) {\n                if (ed.id == eid) continue; // skip this edge in both directions\n                int to = ed.to;\n                long long nd = d + ed.w;\n                if (nd < distLL[to]) {\n                    distLL[to] = nd;\n                    pq.emplace(nd, to);\n                }\n            }\n        }\n\n        long long alt = distLL[tgt];\n        if (alt >= INF_COST) alt = INF_COST; // should not happen due to 2-edge-connectivity\n        long long delta = alt - (long long)W[eid];\n        if (delta < 1) delta = 1;\n        altDiff[eid] = delta;\n    }\n\n    // ---------------------- Step 3: Edge importance modes & normalization ---------------\n    const int MODES = 3;\n    vector<vector<double>> rawImp(MODES, vector<double>(M));\n    vector<double> maxImp(MODES, 0.0);\n\n    for (int i = 0; i < M; i++) {\n        double cen = central[i] + 1.0;\n        double wlen = (double)W[i];\n        double ad = (double)altDiff[i];\n\n        // Mode 0: central * edge length\n        rawImp[0][i] = cen * wlen;\n        // Mode 1: central * alternative detour\n        rawImp[1][i] = cen * ad;\n        // Mode 2: hybrid: central * (0.5*wlen + 0.5*min(ad, 5*wlen))\n        double ad_lim = min(ad, wlen * 5.0);\n        rawImp[2][i] = cen * (0.5 * wlen + 0.5 * ad_lim);\n\n        for (int m = 0; m < MODES; m++) {\n            if (rawImp[m][i] > maxImp[m]) maxImp[m] = rawImp[m][i];\n        }\n    }\n\n    vector<vector<double>> weightModes(MODES, vector<double>(M));\n    for (int m = 0; m < MODES; m++) {\n        double scale = (maxImp[m] > 0.0 ? maxImp[m] / 1000.0 : 1.0);\n        if (scale == 0.0) scale = 1.0;\n        for (int i = 0; i < M; i++) {\n            weightModes[m][i] = rawImp[m][i] / scale;\n        }\n    }\n\n    // ---------------------- Step 4: Capacities per day ----------------------------------\n    vector<int> cap(D);\n    int base = M / D;\n    int rem = M % D;\n    for (int d = 0; d < D; d++) {\n        cap[d] = base + (d < rem ? 1 : 0);\n        // cap[d] <= ceil(M/D) <= K guaranteed\n    }\n\n    // ---------------------- Step 5: Schedule builder (greedy + local search) -----------\n    auto buildSchedule = [&](const vector<double> &weight) -> vector<int> {\n        vector<int> day_cnt(D, 0);\n        vector<double> day_sum(D, 0.0);\n        // vds[v][d] = sum of weights of edges incident to vertex v on day d\n        vector<vector<double>> vds(N, vector<double>(D, 0.0));\n        vector<int> r(M, -1);\n\n        // Initial greedy assignment\n        vector<int> ids(M);\n        iota(ids.begin(), ids.end(), 0);\n        sort(ids.begin(), ids.end(), [&](int a, int b) {\n            return weight[a] > weight[b];\n        });\n\n        const double INIT_ALPHA = 10.0; // local vertex concurrency weight\n        const double INIT_BETA  = 1.0;  // per-day balance weight\n\n        for (int idx = 0; idx < M; idx++) {\n            int e = ids[idx];\n            int u = U[e], v = V[e];\n\n            int bestD = -1;\n            double bestScore = 1e300;\n\n            for (int d = 0; d < D; d++) {\n                if (day_cnt[d] >= cap[d]) continue;\n                double localConcur = vds[u][d] + vds[v][d];\n                double score = INIT_ALPHA * localConcur + INIT_BETA * day_sum[d];\n                if (score < bestScore) {\n                    bestScore = score;\n                    bestD = d;\n                }\n            }\n\n            if (bestD == -1) {\n                // Fallback (should not happen): allocate to any day with free capacity\n                for (int d = 0; d < D; d++) {\n                    if (day_cnt[d] < cap[d]) {\n                        bestD = d;\n                        break;\n                    }\n                }\n            }\n\n            r[e] = bestD;\n            day_cnt[bestD]++;\n            day_sum[bestD] += weight[e];\n            vds[u][bestD] += weight[e];\n            vds[v][bestD] += weight[e];\n        }\n\n        // Local search: minimize ALPHA2*sum_{v,d} vds^2 + BETA2*sum_d day_sum^2\n        const double ALPHA2 = 1.0;\n        const double BETA2  = 0.10;  // stronger day-balance weight\n\n        int ITER = min(1500000, 500 * M);\n        uniform_int_distribution<int> distEdge(0, M - 1);\n\n        for (int it = 0; it < ITER; ++it) {\n            int e1 = distEdge(rng);\n            int e2 = distEdge(rng);\n            if (e1 == e2) continue;\n            int d1 = r[e1], d2 = r[e2];\n            if (d1 == d2) continue;\n\n            int u1 = U[e1], v1 = V[e1];\n            int u2 = U[e2], v2 = V[e2];\n            double w1 = weight[e1], w2 = weight[e2];\n\n            // Day-sum component\n            double S1 = day_sum[d1], S2 = day_sum[d2];\n            double nS1 = S1 - w1 + w2;\n            double nS2 = S2 - w2 + w1;\n            double deltaDay = BETA2 * ((nS1 * nS1 + nS2 * nS2) - (S1 * S1 + S2 * S2));\n\n            // Vertex-day component\n            int vs[8];\n            int ds[8];\n            double dW[8];\n            int cnt = 0;\n\n            auto addChange = [&](int v, int d, double delta) {\n                for (int i = 0; i < cnt; i++) {\n                    if (vs[i] == v && ds[i] == d) {\n                        dW[i] += delta;\n                        return;\n                    }\n                }\n                vs[cnt] = v;\n                ds[cnt] = d;\n                dW[cnt] = delta;\n                cnt++;\n            };\n\n            // e1: d1 -> d2\n            addChange(u1, d1, -w1);\n            addChange(u1, d2, +w1);\n            addChange(v1, d1, -w1);\n            addChange(v1, d2, +w1);\n            // e2: d2 -> d1\n            addChange(u2, d2, -w2);\n            addChange(u2, d1, +w2);\n            addChange(v2, d2, -w2);\n            addChange(v2, d1, +w2);\n\n            double deltaVertex = 0.0;\n            double newVals[8];\n            for (int i = 0; i < cnt; i++) {\n                int v = vs[i];\n                int d = ds[i];\n                double oldS = vds[v][d];\n                double newS = oldS + dW[i];\n                newVals[i] = newS;\n                deltaVertex += ALPHA2 * (newS * newS - oldS * oldS);\n            }\n\n            double deltaScore = deltaVertex + deltaDay;\n\n            if (deltaScore < -1e-9) {\n                // Accept swap\n                day_sum[d1] = nS1;\n                day_sum[d2] = nS2;\n                for (int i = 0; i < cnt; i++) {\n                    vds[vs[i]][ds[i]] = newVals[i];\n                }\n                swap(r[e1], r[e2]);\n            }\n        }\n\n        return r;\n    };\n\n    // ---------------------- Step 6: Build schedules for all modes -----------------------\n    vector<vector<int>> schedules(MODES);\n    for (int m = 0; m < MODES; m++) {\n        schedules[m] = buildSchedule(weightModes[m]);\n    }\n\n    // ---------------------- Step 7: Approximate evaluation of schedules ----------------\n    int S_eval = min(N, 24);\n    vector<int> evalSources(S_eval);\n    for (int i = 0; i < S_eval; i++) evalSources[i] = perm[i];\n\n    const int INF = 1000000000;\n    vector<vector<int>> baseDist(S_eval, vector<int>(N, INF));\n    for (int si = 0; si < S_eval; si++) {\n        int s = evalSources[si];\n        fill(distLL.begin(), distLL.end(), INFLL);\n        priority_queue<PQItem, vector<PQItem>, greater<PQItem>> pq;\n        distLL[s] = 0;\n        pq.emplace(0, s);\n\n        while (!pq.empty()) {\n            auto [d, v] = pq.top();\n            pq.pop();\n            if (d != distLL[v]) continue;\n            for (const auto &e : g[v]) {\n                int to = e.to;\n                long long nd = d + e.w;\n                if (nd < distLL[to]) {\n                    distLL[to] = nd;\n                    pq.emplace(nd, to);\n                }\n            }\n        }\n        for (int v = 0; v < N; v++) {\n            long long dv = distLL[v];\n            if (dv >= INF_COST) dv = INF_COST;\n            baseDist[si][v] = (int)dv;\n        }\n    }\n\n    auto evaluateSchedule = [&](const vector<int> &r) -> double {\n        vector<long long> distEval(N);\n        double totalDelta = 0.0;\n\n        for (int si = 0; si < S_eval; si++) {\n            int s = evalSources[si];\n            const vector<int> &orig = baseDist[si];\n\n            for (int dday = 0; dday < D; dday++) {\n                fill(distEval.begin(), distEval.end(), (long long)INF);\n                priority_queue<PQItem, vector<PQItem>, greater<PQItem>> pq;\n                distEval[s] = 0;\n                pq.emplace(0, s);\n\n                while (!pq.empty()) {\n                    auto [cd, v] = pq.top();\n                    pq.pop();\n                    if (cd != distEval[v]) continue;\n                    for (const auto &e : g[v]) {\n                        if (r[e.id] == dday) continue; // edge under repair this day\n                        int to = e.to;\n                        long long nd = cd + e.w;\n                        if (nd < distEval[to] && nd < INF) {\n                            distEval[to] = nd;\n                            pq.emplace(nd, to);\n                        }\n                    }\n                }\n\n                for (int v = 0; v < N; v++) {\n                    if (v == s) continue;\n                    int o = orig[v];\n                    long long cur = distEval[v];\n                    int nd = (cur >= INF ? INF : (int)cur);\n                    long long delta = (long long)nd - o;\n                    if (delta < 0) delta = 0; // safety\n                    totalDelta += (double)delta;\n                }\n            }\n        }\n        return totalDelta; // denominator is common across schedules, so omitted\n    };\n\n    int bestIdx = 0;\n    double bestScore = evaluateSchedule(schedules[0]);\n    for (int m = 1; m < MODES; m++) {\n        double sc = evaluateSchedule(schedules[m]);\n        if (sc < bestScore) {\n            bestScore = sc;\n            bestIdx = m;\n        }\n    }\n\n    // ---------------------- Output best schedule ----------------------------------------\n    const vector<int> &best = schedules[bestIdx];\n    for (int i = 0; i < M; i++) {\n        cout << (best[i] + 1);\n        if (i + 1 != M) cout << ' ';\n    }\n    cout << '\\n';\n\n    return 0;\n}","ahc019":"#include <bits/stdc++.h>\nusing namespace std;\n\n// ----------------------------\n// Basic structures\n// ----------------------------\nstruct Coord {\n    int x, y, z;\n};\n\nstruct Rot {\n    int p[3]; // permutation of axes: 0=x,1=y,2=z\n    int s[3]; // sign for each axis: +1 or -1\n};\n\nconst int MAXS = 250; // upper bound for number of shared cubes (safe for D<=14)\nstatic bool adjSmall[MAXS][MAXS]; // adjacency in small puzzle\n\n// ----------------------------\n// Generate all 24 proper rotations (determinant +1) of the cube\n// ----------------------------\nvector<Rot> generate_rotations() {\n    vector<Rot> rots;\n    vector<int> perm = {0, 1, 2};\n    auto parity = [](const vector<int>& p) -> int {\n        int inv = 0;\n        for (int i = 0; i < 3; i++) {\n            for (int j = i + 1; j < 3; j++) {\n                if (p[i] > p[j]) inv++;\n            }\n        }\n        return (inv % 2 == 0) ? 1 : -1;\n    };\n\n    do {\n        int ps = parity(perm); // +1 for even, -1 for odd\n        for (int mask = 0; mask < 8; mask++) {\n            int s0 = (mask & 1) ? -1 : 1;\n            int s1 = (mask & 2) ? -1 : 1;\n            int s2 = (mask & 4) ? -1 : 1;\n            int det = ps * s0 * s1 * s2;\n            if (det == 1) { // proper rotation\n                Rot r;\n                r.p[0] = perm[0]; r.p[1] = perm[1]; r.p[2] = perm[2];\n                r.s[0] = s0;      r.s[1] = s1;      r.s[2] = s2;\n                rots.push_back(r);\n            }\n        }\n    } while (next_permutation(perm.begin(), perm.end()));\n    return rots; // should have size 24\n}\n\n// ----------------------------\n// Canonical shape representation from cell IDs\n// coords are given as cell IDs in [0, D^3)\n// preRot[r][id] = rotated (x,y,z) for rotation r\n// ----------------------------\nvector<array<int,3>> canonical_from_ids(\n    const vector<int>& ids,\n    const vector<vector<array<int,3>>>& preRot\n) {\n    vector<array<int,3>> best;\n    bool first = true;\n    int R = (int)preRot.size();\n    for (int r = 0; r < R; r++) {\n        const auto& tab = preRot[r];\n        vector<array<int,3>> coords;\n        coords.reserve(ids.size());\n        int minx = INT_MAX, miny = INT_MAX, minz = INT_MAX;\n        for (int id : ids) {\n            const auto& q = tab[id];\n            coords.push_back(q);\n            minx = min(minx, q[0]);\n            miny = min(miny, q[1]);\n            minz = min(minz, q[2]);\n        }\n        for (auto &q : coords) {\n            q[0] -= minx;\n            q[1] -= miny;\n            q[2] -= minz;\n        }\n        sort(coords.begin(), coords.end());\n        if (first || coords < best) {\n            best = coords;\n            first = false;\n        }\n    }\n    return best;\n}\n\n// ----------------------------\n// Main\n// ----------------------------\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int D;\n    if (!(cin >> D)) return 0;\n\n    // Read silhouettes: f[t][z][x], r[t][z][y]\n    vector<string> f[2], r[2];\n    for (int t = 0; t < 2; t++) {\n        f[t].resize(D);\n        r[t].resize(D);\n        for (int z = 0; z < D; z++) cin >> f[t][z];\n        for (int z = 0; z < D; z++) cin >> r[t][z];\n    }\n\n    // Build minimal-volume occupancy for each puzzle\n    vector<Coord> cells[2]; // occupied cells per puzzle\n\n    for (int t = 0; t < 2; t++) {\n        for (int z = 0; z < D; z++) {\n            vector<int> rows, cols;\n            for (int x = 0; x < D; x++) if (f[t][z][x] == '1') rows.push_back(x);\n            for (int y = 0; y < D; y++) if (r[t][z][y] == '1') cols.push_back(y);\n            int Rcnt = (int)rows.size();\n            int Ccnt = (int)cols.size();\n            if (Rcnt == 0 || Ccnt == 0) continue; // shouldn't happen by constraints\n\n            if (Rcnt <= Ccnt) {\n                // Use Ccnt cubes, one per column\n                for (int j = 0; j < Ccnt; j++) {\n                    int x = rows[j % Rcnt];\n                    int y = cols[j];\n                    cells[t].push_back({x, y, z});\n                }\n            } else {\n                // Use Rcnt cubes, one per row\n                for (int i = 0; i < Rcnt; i++) {\n                    int x = rows[i];\n                    int y = cols[i % Ccnt];\n                    cells[t].push_back({x, y, z});\n                }\n            }\n        }\n    }\n\n    int V0 = (int)cells[0].size();\n    int V1 = (int)cells[1].size();\n\n    // Decide which puzzle is \"small\" and which is \"big\" by volume\n    int small = 0, big = 1;\n    if (V0 > V1) {\n        small = 1;\n        big = 0;\n        swap(V0, V1);\n    }\n    int S = (int)cells[small].size(); // all cubes in small puzzle\n    int T = (int)cells[big].size();\n\n    // Positions and cell IDs\n    vector<Coord> posSmall(S), posBigAll(T);\n    for (int i = 0; i < S; i++) posSmall[i] = cells[small][i];\n    for (int i = 0; i < T; i++) posBigAll[i] = cells[big][i];\n\n    auto encode = [D](int x, int y, int z) {\n        return x * D * D + y * D + z;\n    };\n    int D3 = D * D * D;\n\n    vector<int> cellIdSmall(S), cellIdBigAll(T);\n    for (int i = 0; i < S; i++) {\n        cellIdSmall[i] = encode(posSmall[i].x, posSmall[i].y, posSmall[i].z);\n    }\n    for (int i = 0; i < T; i++) {\n        cellIdBigAll[i] = encode(posBigAll[i].x, posBigAll[i].y, posBigAll[i].z);\n    }\n\n    // Build adjacency in the small puzzle\n    vector<int> idxSmall(D3, -1);\n    for (int i = 0; i < S; i++) {\n        idxSmall[cellIdSmall[i]] = i;\n    }\n\n    for (int i = 0; i < S; i++)\n        for (int j = 0; j < S; j++)\n            adjSmall[i][j] = false;\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 k = 0; k < S; k++) {\n        int x = posSmall[k].x;\n        int y = posSmall[k].y;\n        int z = posSmall[k].z;\n        for (int d = 0; d < 6; d++) {\n            int nx = x + dx[d];\n            int ny = y + dy[d];\n            int nz = z + dz[d];\n            if (nx < 0 || nx >= D || ny < 0 || ny >= D || nz < 0 || nz >= D) continue;\n            int nid = encode(nx, ny, nz);\n            int j = idxSmall[nid];\n            if (j >= 0) {\n                adjSmall[k][j] = adjSmall[j][k] = true;\n            }\n        }\n    }\n\n    // Convert adjacency to neighbor lists\n    vector<vector<int>> neighbors(S);\n    for (int i = 0; i < S; i++) {\n        for (int j = i + 1; j < S; j++) {\n            if (adjSmall[i][j]) {\n                neighbors[i].push_back(j);\n                neighbors[j].push_back(i);\n            }\n        }\n    }\n\n    // Also build adjacency in the big puzzle (for degree-based mapping)\n    vector<vector<int>> neighborsBig(T);\n    vector<int> idxBig(D3, -1);\n    for (int i = 0; i < T; i++) idxBig[cellIdBigAll[i]] = i;\n    for (int k = 0; k < T; k++) {\n        int x = posBigAll[k].x;\n        int y = posBigAll[k].y;\n        int z = posBigAll[k].z;\n        for (int d = 0; d < 6; d++) {\n            int nx = x + dx[d];\n            int ny = y + dy[d];\n            int nz = z + dz[d];\n            if (nx < 0 || nx >= D || ny < 0 || ny >= D || nz < 0 || nz >= D) continue;\n            int nid = encode(nx, ny, nz);\n            int j = idxBig[nid];\n            if (j >= 0) {\n                neighborsBig[k].push_back(j);\n            }\n        }\n    }\n\n    // Precompute all rotations and rotated coordinates for each cell ID\n    vector<Rot> rots = generate_rotations();\n    int R = (int)rots.size(); // should be 24\n    vector<vector<array<int,3>>> preRot(R, vector<array<int,3>>(D3));\n\n    for (int id = 0; id < D3; id++) {\n        int x = id / (D * D);\n        int rem = id % (D * D);\n        int y = rem / D;\n        int z = rem % D;\n        int src[3] = {x, y, z};\n        for (int rIdx = 0; rIdx < R; rIdx++) {\n            const Rot &rt = rots[rIdx];\n            array<int,3> q;\n            q[0] = rt.s[0] * src[ rt.p[0] ];\n            q[1] = rt.s[1] * src[ rt.p[1] ];\n            q[2] = rt.s[2] * src[ rt.p[2] ];\n            preRot[rIdx][id] = q;\n        }\n    }\n\n    // Initialize RNG with deterministic seed based on input (for reproducibility)\n    uint64_t seed = 1234567u ^ (uint64_t)D;\n    for (int t = 0; t < 2; t++) {\n        for (int z = 0; z < D; z++) {\n            for (int x = 0; x < D; x++) {\n                if (f[t][z][x] == '1') {\n                    seed ^= ((uint64_t)(t+1) << 48) ^ ((uint64_t)(z+1) << 32) ^ ((uint64_t)(x+1) << 16);\n                }\n                if (r[t][z][x] == '1') {\n                    seed ^= ((uint64_t)(t+3) << 40) ^ ((uint64_t)(z+5) << 24) ^ ((uint64_t)(x+7) << 8);\n                }\n            }\n        }\n    }\n    mt19937_64 rng(seed);\n\n    // Helper: shapesMatch for given node set and mapped big IDs\n    auto shapesMatch = [&](const vector<int>& nodes,\n                           const vector<int>& cellIdBigMapped) -> bool {\n        vector<int> idsSmall, idsBig;\n        idsSmall.reserve(nodes.size());\n        idsBig.reserve(nodes.size());\n        for (int idx : nodes) {\n            idsSmall.push_back(cellIdSmall[idx]);\n            idsBig.push_back(cellIdBigMapped[idx]);\n        }\n        auto repSmall = canonical_from_ids(idsSmall, preRot);\n        auto repBig   = canonical_from_ids(idsBig, preRot);\n        return repSmall == repBig;\n    };\n\n    // Deterministic clustering for a given mapping small->big (match[i] = index in big)\n    auto clusterDet = [&](const vector<int>& match)\n        -> pair<double, vector<vector<int>>> {\n        vector<int> cellIdBigMapped(S);\n        for (int i = 0; i < S; i++) {\n            cellIdBigMapped[i] = cellIdBigAll[ match[i] ];\n        }\n\n        vector<char> visited(S, false);\n        vector<vector<int>> clusters;\n        clusters.reserve(S);\n\n        for (int i = 0; i < S; i++) {\n            if (visited[i]) continue;\n\n            vector<int> cluster;\n            cluster.push_back(i);\n            visited[i] = true;\n\n            while (true) {\n                vector<int> cand;\n                for (int u : cluster) {\n                    for (int v : neighbors[u]) {\n                        if (!visited[v]) cand.push_back(v);\n                    }\n                }\n                sort(cand.begin(), cand.end());\n                cand.erase(unique(cand.begin(), cand.end()), cand.end());\n                bool added = false;\n                for (int v : cand) {\n                    vector<int> candidate = cluster;\n                    candidate.push_back(v);\n                    if (shapesMatch(candidate, cellIdBigMapped)) {\n                        cluster.push_back(v);\n                        visited[v] = true;\n                        added = true;\n                    }\n                }\n                if (!added) break;\n            }\n\n            clusters.push_back(cluster);\n        }\n\n        double sumInv = 0.0;\n        for (auto &cl : clusters) {\n            sumInv += 1.0 / (double)cl.size();\n        }\n        return {sumInv, clusters};\n    };\n\n    // Randomized clustering for the same mapping (used as refinement)\n    auto clusterRand = [&](const vector<int>& match)\n        -> pair<double, vector<vector<int>>> {\n        vector<int> cellIdBigMapped(S);\n        for (int i = 0; i < S; i++) {\n            cellIdBigMapped[i] = cellIdBigAll[ match[i] ];\n        }\n\n        vector<char> visited(S, false);\n        vector<vector<int>> clusters;\n        clusters.reserve(S);\n\n        vector<int> order(S);\n        iota(order.begin(), order.end(), 0);\n        shuffle(order.begin(), order.end(), rng);\n\n        for (int idx0 = 0; idx0 < S; idx0++) {\n            int i = order[idx0];\n            if (visited[i]) continue;\n\n            vector<int> cluster;\n            cluster.push_back(i);\n            visited[i] = true;\n\n            while (true) {\n                vector<int> cand;\n                for (int u : cluster) {\n                    for (int v : neighbors[u]) {\n                        if (!visited[v]) cand.push_back(v);\n                    }\n                }\n                sort(cand.begin(), cand.end());\n                cand.erase(unique(cand.begin(), cand.end()), cand.end());\n                if (cand.empty()) break;\n                shuffle(cand.begin(), cand.end(), rng);\n                bool added = false;\n                for (int v : cand) {\n                    vector<int> candidate = cluster;\n                    candidate.push_back(v);\n                    if (shapesMatch(candidate, cellIdBigMapped)) {\n                        cluster.push_back(v);\n                        visited[v] = true;\n                        added = true;\n                    }\n                }\n                if (!added) break;\n            }\n\n            clusters.push_back(cluster);\n        }\n\n        double sumInv = 0.0;\n        for (auto &cl : clusters) {\n            sumInv += 1.0 / (double)cl.size();\n        }\n        return {sumInv, clusters};\n    };\n\n    double bestScore = 1e100;\n    vector<vector<int>> bestClusters;\n    vector<int> bestMatch;\n\n    // ---------- Attempt 1: nearest-neighbor mapping (original space) ----------\n    {\n        vector<int> match(S, -1);\n        vector<char> used(T, false);\n        for (int i = 0; i < S; i++) {\n            const Coord &cs = posSmall[i];\n            int bestJ = -1;\n            int bestDist = INT_MAX;\n            for (int j = 0; j < T; j++) {\n                if (used[j]) continue;\n                const Coord &cb = posBigAll[j];\n                int dist = abs(cs.x - cb.x) + abs(cs.y - cb.y) + abs(cs.z - cb.z);\n                if (dist < bestDist) {\n                    bestDist = dist;\n                    bestJ = j;\n                }\n            }\n            if (bestJ == -1) {\n                bestJ = 0;\n                while (used[bestJ]) bestJ++;\n            }\n            match[i] = bestJ;\n            used[bestJ] = true;\n        }\n        auto res = clusterDet(match);\n        if (res.first < bestScore) {\n            bestScore = res.first;\n            bestClusters = move(res.second);\n            bestMatch = match;\n        }\n    }\n\n    // ---------- Attempt 2: lexicographic mapping by (x,y,z) ----------\n    {\n        vector<int> idxS(S), idxB(T);\n        iota(idxS.begin(), idxS.end(), 0);\n        iota(idxB.begin(), idxB.end(), 0);\n        sort(idxS.begin(), idxS.end(), [&](int a, int b) {\n            const Coord &A = posSmall[a], &B = posSmall[b];\n            if (A.x != B.x) return A.x < B.x;\n            if (A.y != B.y) return A.y < B.y;\n            return A.z < B.z;\n        });\n        sort(idxB.begin(), idxB.end(), [&](int a, int b) {\n            const Coord &A = posBigAll[a], &B = posBigAll[b];\n            if (A.x != B.x) return A.x < B.x;\n            if (A.y != B.y) return A.y < B.y;\n            return A.z < B.z;\n        });\n        vector<int> match(S, -1);\n        for (int k = 0; k < S; k++) {\n            match[idxS[k]] = idxB[k];\n        }\n        auto res = clusterDet(match);\n        if (res.first < bestScore) {\n            bestScore = res.first;\n            bestClusters = move(res.second);\n            bestMatch = match;\n        }\n    }\n\n    // ---------- Attempt 3: lexicographic mapping by (z,x,y) ----------\n    {\n        vector<int> idxS(S), idxB(T);\n        iota(idxS.begin(), idxS.end(), 0);\n        iota(idxB.begin(), idxB.end(), 0);\n        sort(idxS.begin(), idxS.end(), [&](int a, int b) {\n            const Coord &A = posSmall[a], &B = posSmall[b];\n            if (A.z != B.z) return A.z < B.z;\n            if (A.x != B.x) return A.x < B.x;\n            return A.y < B.y;\n        });\n        sort(idxB.begin(), idxB.end(), [&](int a, int b) {\n            const Coord &A = posBigAll[a], &B = posBigAll[b];\n            if (A.z != B.z) return A.z < B.z;\n            if (A.x != B.x) return A.x < B.x;\n            return A.y < B.y;\n        });\n        vector<int> match(S, -1);\n        for (int k = 0; k < S; k++) {\n            match[idxS[k]] = idxB[k];\n        }\n        auto res = clusterDet(match);\n        if (res.first < bestScore) {\n            bestScore = res.first;\n            bestClusters = move(res.second);\n            bestMatch = match;\n        }\n    }\n\n    // ---------- Attempt 4: degree-based greedy mapping ----------\n    {\n        vector<int> degSmall(S), degBig(T);\n        for (int i = 0; i < S; i++) degSmall[i] = (int)neighbors[i].size();\n        for (int j = 0; j < T; j++) degBig[j] = (int)neighborsBig[j].size();\n\n        vector<int> idxS(S), idxB(T);\n        iota(idxS.begin(), idxS.end(), 0);\n        iota(idxB.begin(), idxB.end(), 0);\n        sort(idxS.begin(), idxS.end(), [&](int a, int b) {\n            if (degSmall[a] != degSmall[b]) return degSmall[a] > degSmall[b]; // high degree first\n            const Coord &A = posSmall[a], &B = posSmall[b];\n            if (A.x != B.x) return A.x < B.x;\n            if (A.y != B.y) return A.y < B.y;\n            return A.z < B.z;\n        });\n        sort(idxB.begin(), idxB.end(), [&](int a, int b) {\n            if (degBig[a] != degBig[b]) return degBig[a] > degBig[b];\n            const Coord &A = posBigAll[a], &B = posBigAll[b];\n            if (A.x != B.x) return A.x < B.x;\n            if (A.y != B.y) return A.y < B.y;\n            return A.z < B.z;\n        });\n\n        vector<int> match(S, -1);\n        for (int k = 0; k < S; k++) {\n            match[idxS[k]] = idxB[k];\n        }\n\n        auto res = clusterDet(match);\n        if (res.first < bestScore) {\n            bestScore = res.first;\n            bestClusters = move(res.second);\n            bestMatch = match;\n        }\n    }\n\n    // ---------- Precompute big centroid for rotation-based mappings ----------\n    double sumBx = 0.0, sumBy = 0.0, sumBz = 0.0;\n    for (int j = 0; j < T; j++) {\n        sumBx += posBigAll[j].x;\n        sumBy += posBigAll[j].y;\n        sumBz += posBigAll[j].z;\n    }\n    double cenBx = sumBx / (double)T;\n    double cenBy = sumBy / (double)T;\n    double cenBz = sumBz / (double)T;\n\n    // ---------- Attempts 5+: rotation-based nearest-neighbor mappings ----------\n    for (int rIdx = 0; rIdx < R; rIdx++) {\n        vector<array<double,3>> rotPos(S);\n        double sumSx = 0.0, sumSy = 0.0, sumSz = 0.0;\n        for (int i = 0; i < S; i++) {\n            auto q = preRot[rIdx][ cellIdSmall[i] ];\n            rotPos[i] = { (double)q[0], (double)q[1], (double)q[2] };\n            sumSx += rotPos[i][0];\n            sumSy += rotPos[i][1];\n            sumSz += rotPos[i][2];\n        }\n        double cenSx = sumSx / (double)S;\n        double cenSy = sumSy / (double)S;\n        double cenSz = sumSz / (double)S;\n        double dx0 = cenBx - cenSx;\n        double dy0 = cenBy - cenSy;\n        double dz0 = cenBz - cenSz;\n\n        vector<int> match(S, -1);\n        vector<char> used(T, false);\n\n        for (int i = 0; i < S; i++) {\n            double tx = rotPos[i][0] + dx0;\n            double ty = rotPos[i][1] + dy0;\n            double tz = rotPos[i][2] + dz0;\n            int bestJ = -1;\n            double bestDist = 1e100;\n            for (int j = 0; j < T; j++) {\n                if (used[j]) continue;\n                const Coord &cb = posBigAll[j];\n                double ddx = cb.x - tx;\n                double ddy = cb.y - ty;\n                double ddz = cb.z - tz;\n                double dist2 = ddx*ddx + ddy*ddy + ddz*ddz;\n                if (dist2 < bestDist) {\n                    bestDist = dist2;\n                    bestJ = j;\n                }\n            }\n            if (bestJ == -1) {\n                bestJ = 0;\n                while (used[bestJ]) bestJ++;\n            }\n            match[i] = bestJ;\n            used[bestJ] = true;\n        }\n\n        auto res = clusterDet(match);\n        if (res.first < bestScore) {\n            bestScore = res.first;\n            bestClusters = move(res.second);\n            bestMatch = match;\n        }\n    }\n\n    // ---------- Random mappings ----------\n    const int RANDOM_ATTEMPTS = 8;\n    for (int att = 0; att < RANDOM_ATTEMPTS; att++) {\n        vector<int> smallOrder(S), bigPerm(T);\n        iota(smallOrder.begin(), smallOrder.end(), 0);\n        iota(bigPerm.begin(),  bigPerm.end(),  0);\n        shuffle(smallOrder.begin(), smallOrder.end(), rng);\n        shuffle(bigPerm.begin(),  bigPerm.end(),  rng);\n\n        vector<int> match(S, -1);\n        for (int k = 0; k < S; k++) {\n            int si = smallOrder[k];\n            int bi = bigPerm[k];\n            match[si] = bi;\n        }\n\n        auto res = clusterDet(match);\n        if (res.first < bestScore) {\n            bestScore = res.first;\n            bestClusters = move(res.second);\n            bestMatch = match;\n        }\n    }\n\n    // ---------- Randomized re-clustering for the best mapping ----------\n    {\n        double bestScoreRefine = bestScore;\n        vector<vector<int>> bestClustersRefine = bestClusters;\n\n        const int CLUSTER_RANDOM_RETRY = 16;\n        for (int it = 0; it < CLUSTER_RANDOM_RETRY; it++) {\n            auto res = clusterRand(bestMatch);\n            if (res.first < bestScoreRefine) {\n                bestScoreRefine = res.first;\n                bestClustersRefine = move(res.second);\n            }\n        }\n\n        bestScore = bestScoreRefine;\n        bestClusters = move(bestClustersRefine);\n    }\n\n    // ---------- Post-process: merge neighboring clusters for the best mapping ----------\n    {\n        vector<int> cellIdBigMapped(S);\n        for (int i = 0; i < S; i++) {\n            cellIdBigMapped[i] = cellIdBigAll[ bestMatch[i] ];\n        }\n\n        vector<vector<int>> &clusters = bestClusters;\n        vector<int> nodeCluster(S, -1);\n        for (int cid = 0; cid < (int)clusters.size(); cid++) {\n            for (int u : clusters[cid]) nodeCluster[u] = cid;\n        }\n\n        bool changed = true;\n        while (changed) {\n            changed = false;\n            int C = (int)clusters.size();\n            if (C <= 1) break;\n\n            // Build cluster adjacency from node adjacency\n            vector<vector<int>> clNei(C);\n            for (int u = 0; u < S; u++) {\n                int cu = nodeCluster[u];\n                for (int v : neighbors[u]) {\n                    int cv = nodeCluster[v];\n                    if (cu == cv) continue;\n                    if (cu < cv) clNei[cu].push_back(cv);\n                    else clNei[cv].push_back(cu);\n                }\n            }\n            for (int c = 0; c < C; c++) {\n                auto &lst = clNei[c];\n                sort(lst.begin(), lst.end());\n                lst.erase(unique(lst.begin(), lst.end()), lst.end());\n            }\n\n            bool merged = false;\n            for (int cu = 0; cu < C && !merged; cu++) {\n                auto lst = clNei[cu];\n                sort(lst.begin(), lst.end(), [&](int a, int b) {\n                    return clusters[cu].size() + clusters[a].size()\n                         > clusters[cu].size() + clusters[b].size();\n                });\n                for (int cv : lst) {\n                    if (cv <= cu) continue;\n                    vector<int> unionNodes;\n                    unionNodes.reserve(clusters[cu].size() + clusters[cv].size());\n                    unionNodes.insert(unionNodes.end(),\n                                      clusters[cu].begin(), clusters[cu].end());\n                    unionNodes.insert(unionNodes.end(),\n                                      clusters[cv].begin(), clusters[cv].end());\n                    if (!shapesMatch(unionNodes, cellIdBigMapped)) continue;\n\n                    // Merge cv into cu\n                    clusters[cu] = move(unionNodes);\n                    for (int u : clusters[cu]) nodeCluster[u] = cu;\n                    clusters.erase(clusters.begin() + cv);\n                    // Update cluster indices in nodeCluster\n                    for (int u = 0; u < S; u++) {\n                        int cid = nodeCluster[u];\n                        if (cid > cv) nodeCluster[u] = cid - 1;\n                    }\n                    merged = true;\n                    changed = true;\n                    break;\n                }\n            }\n        }\n    }\n\n    // Build final block assignments using bestMatch and bestClusters\n    vector<int> b0(D3, 0), b1(D3, 0);\n    int blockCount = 0;\n\n    auto setCell = [&](int puzzle, const Coord& c, int id) {\n        int idx = encode(c.x, c.y, c.z);\n        if (puzzle == 0) b0[idx] = id;\n        else b1[idx] = id;\n    };\n\n    // Shared blocks from clusters\n    for (const auto& cluster : bestClusters) {\n        ++blockCount;\n        for (int idx : cluster) {\n            const Coord &cs = posSmall[idx];\n            const Coord &cb = posBigAll[ bestMatch[idx] ];\n            setCell(small, cs, blockCount);\n            setCell(big,   cb, blockCount);\n        }\n    }\n\n    // Big-only blocks for cubes in big puzzle that are not shared\n    vector<char> usedBig(T, false);\n    for (int i = 0; i < S; i++) {\n        usedBig[ bestMatch[i] ] = true;\n    }\n    for (int j = 0; j < T; j++) {\n        if (usedBig[j]) continue;\n        ++blockCount;\n        const Coord &cb = posBigAll[j];\n        setCell(big, cb, blockCount);\n    }\n\n    // Output\n    cout << blockCount << '\\n';\n\n    auto output_grid = [&](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 idx = x * D * D + y * D + z;\n                    if (!first) cout << ' ';\n                    first = false;\n                    cout << b[idx];\n                }\n            }\n        }\n        cout << '\\n';\n    };\n\n    // Puzzle 0 grid then puzzle 1 grid\n    output_grid(b0);\n    output_grid(b1);\n\n    return 0;\n}","ahc020":"#include <bits/stdc++.h>\nusing namespace std;\nusing ll = long long;\n\nconst int MAXN = 105;   // N <= 100\nconst int MAXM = 305;   // M <= 300\nconst int MAXK = 5005;  // K <= 5000\nconst ll INFLL = (1LL << 60);\n\n// ----- Graph and data -----\nstruct Edge {\n    int u, v;\n    ll w;\n};\n\nint N, M, K;\nll vx[MAXN], vy[MAXN];\nll ax_arr[MAXK], ay_arr[MAXK];\nEdge edges[MAXM];\nvector<pair<int,int>> adj[MAXN];  // (to, edgeIndex)\n\n// All-pairs shortest paths (Dijkstra from each node)\nll distAll[MAXN][MAXN];    // distAll[s][v]\nint parEdge[MAXN][MAXN];   // parent edge index from s to v\n\n// Residents' candidate stations sorted by squared distance (within radius 5000)\nvector<pair<ll,int>> residentCand[MAXK];\n\n// For greedy coverage: residents each station can cover\nvector<int> stationRes[MAXN];  // stationRes[v] = list of residents k covered by v\n\n// For cost-aware greedy cover: max squared distance to any resident this station can cover\nll stationMaxR2[MAXN];\n\n// ----- Steiner tree / evaluation buffers -----\nll maxd2_arr[MAXN];\nbool used_arr[MAXN];\nbool isReq[MAXN];\nbool usedEdgeUnion[MAXM];\nbool aliveEdge[MAXM];\n\nll keyArr[MAXN];\nint prArr[MAXN];\nbool inArr[MAXN];\nint reqNodesArr[MAXN];\nint metricU[MAXN], metricV[MAXN];\n\n// DSU for MST\nint dsu_p[MAXN], dsu_rnk[MAXN];\nvector<int> ordEdges;  // edges sorted by weight\n\ninline void dsu_reset(int n) {\n    for (int i = 1; i <= n; ++i) {\n        dsu_p[i] = i;\n        dsu_rnk[i] = 0;\n    }\n}\nint dsu_find(int x) {\n    return dsu_p[x] == x ? x : (dsu_p[x] = dsu_find(dsu_p[x]));\n}\nbool dsu_unite(int a, int b) {\n    a = dsu_find(a);\n    b = dsu_find(b);\n    if (a == b) return false;\n    if (dsu_rnk[a] < dsu_rnk[b]) swap(a, b);\n    dsu_p[b] = a;\n    if (dsu_rnk[a] == dsu_rnk[b]) ++dsu_rnk[a];\n    return true;\n}\n\n// Global best solution\nll bestCostGlobal = (1LL << 62);\nint P_best[MAXN];\nchar B_best[MAXM];\n\n// Temporary buffers for evaluation\nint P_tmp[MAXN];\nchar B_tmp[MAXM];\n\n// Evaluate solution for given open[1..N].\n// openFlag[v] = 1 if station v can be used as broadcast center.\n// Returns true if all residents can be covered (each within radius <=5000).\n// On success, fills P_out[1..N], B_out[0..M-1], and cost_out.\nbool evaluate_solution(const char openFlag[], ll &cost_out, int P_out[], char B_out[]) {\n    const ll R2max = 5000LL * 5000LL;\n\n    // Residents -> nearest open station within radius 5000\n    for (int i = 1; i <= N; ++i) {\n        maxd2_arr[i] = 0;\n        used_arr[i] = false;\n    }\n\n    for (int k = 0; k < K; ++k) {\n        bool assigned = false;\n        const auto &cand = residentCand[k];\n        for (size_t idx = 0; idx < cand.size(); ++idx) {\n            ll d2 = cand[idx].first;\n            if (d2 > R2max) break;\n            int v = cand[idx].second;\n            if (openFlag[v]) {\n                assigned = true;\n                used_arr[v] = true;\n                if (maxd2_arr[v] < d2) maxd2_arr[v] = d2;\n                break;\n            }\n        }\n        if (!assigned) {\n            // Some resident cannot be covered\n            return false;\n        }\n    }\n\n    // Compute P_i and broadcasting cost\n    ll broadcastCost = 0;\n    for (int i = 1; i <= N; ++i) {\n        if (maxd2_arr[i] > 0) {\n            long double sr = sqrtl((long double)maxd2_arr[i]);\n            ll r = (ll)sr;\n            if (r * r < maxd2_arr[i]) ++r;\n            if (r > 5000) r = 5000;\n            P_out[i] = (int)r;\n            broadcastCost += r * r;\n        } else {\n            P_out[i] = 0;\n        }\n    }\n\n    // Build required node set: station 1 + all stations with assigned residents\n    for (int i = 1; i <= N; ++i) isReq[i] = false;\n    int R = 0;\n    isReq[1] = true;\n    reqNodesArr[R++] = 1;\n    for (int i = 2; i <= N; ++i) {\n        if (used_arr[i]) {\n            isReq[i] = true;\n            reqNodesArr[R++] = i;\n        }\n    }\n\n    // No edges needed if only root is required\n    for (int j = 0; j < M; ++j) B_out[j] = 0;\n    if (R <= 1) {\n        cost_out = broadcastCost;\n        return true;\n    }\n\n    // Metric MST on required nodes (Prim) using distAll\n    for (int i = 0; i < R; ++i) {\n        keyArr[i] = INFLL;\n        prArr[i] = -1;\n        inArr[i] = false;\n    }\n    keyArr[0] = 0;\n    int metricCnt = 0;\n    for (int it = 0; it < R; ++it) {\n        int u = -1;\n        ll best = INFLL;\n        for (int i = 0; i < R; ++i) if (!inArr[i] && keyArr[i] < best) {\n            best = keyArr[i];\n            u = i;\n        }\n        if (u == -1) break;  // should not happen\n        inArr[u] = true;\n        if (prArr[u] != -1) {\n            metricU[metricCnt] = u;\n            metricV[metricCnt] = prArr[u];\n            ++metricCnt;\n        }\n        int vu = reqNodesArr[u];\n        for (int i = 0; i < R; ++i) if (!inArr[i]) {\n            int vv = reqNodesArr[i];\n            ll w = distAll[vu][vv];\n            if (w < keyArr[i]) {\n                keyArr[i] = w;\n                prArr[i] = u;\n            }\n        }\n    }\n\n    // Union of shortest paths for metric MST edges\n    for (int j = 0; j < M; ++j) usedEdgeUnion[j] = false;\n    for (int idx = 0; idx < metricCnt; ++idx) {\n        int a = reqNodesArr[metricU[idx]];\n        int b = reqNodesArr[metricV[idx]];\n        int cur = b;\n        while (cur != a) {\n            int eid = parEdge[a][cur];\n            if (eid < 0) break;  // safety\n            usedEdgeUnion[eid] = true;\n            const Edge &E = edges[eid];\n            cur = E.u ^ E.v ^ cur;\n        }\n    }\n\n    // MST over union edges (Steiner tree approximation)\n    dsu_reset(N);\n    for (int j = 0; j < M; ++j) aliveEdge[j] = false;\n    ll edgeCost = 0;\n    for (int idx = 0; idx < (int)ordEdges.size(); ++idx) {\n        int e = ordEdges[idx];\n        if (!usedEdgeUnion[e]) continue;\n        int u = edges[e].u;\n        int v = edges[e].v;\n        if (dsu_unite(u, v)) {\n            aliveEdge[e] = true;\n            edgeCost += edges[e].w;\n        }\n    }\n\n    for (int j = 0; j < M; ++j) {\n        B_out[j] = aliveEdge[j] ? 1 : 0;\n    }\n\n    cost_out = broadcastCost + edgeCost;\n    return true;\n}\n\n// Greedy removal: try to close stations in 'order'.\n// open[] is modified in place, curCost is updated if closures accepted.\n// covCount[k] is number of open stations covering resident k (consistent with open[]).\nvoid greedy_removal(char open[], ll &curCost, const vector<int> &order, int covCount[]) {\n    for (int idx = 0; idx < (int)order.size(); ++idx) {\n        int v = order[idx];\n        if (!open[v]) continue;\n\n        // Quick coverage check: if some resident is only covered by v, can't close v\n        bool fail = false;\n        const auto &resList = stationRes[v];\n        for (int i = 0; i < (int)resList.size(); ++i) {\n            int k = resList[i];\n            if (covCount[k] == 1) {\n                fail = true;\n                break;\n            }\n        }\n        if (fail) continue;\n\n        // Tentatively close v\n        open[v] = 0;\n        for (int i = 0; i < (int)resList.size(); ++i) {\n            int k = resList[i];\n            --covCount[k];\n        }\n\n        ll cost2;\n        if (!evaluate_solution(open, cost2, P_tmp, B_tmp)) {\n            // Should not happen, but revert safely\n            open[v] = 1;\n            for (int i = 0; i < (int)resList.size(); ++i) {\n                int k = resList[i];\n                ++covCount[k];\n            }\n            continue;\n        }\n\n        // Update global best\n        if (cost2 < bestCostGlobal) {\n            bestCostGlobal = cost2;\n            for (int i = 1; i <= N; ++i) P_best[i] = P_tmp[i];\n            for (int j = 0; j < M; ++j) B_best[j] = B_tmp[j];\n        }\n\n        if (cost2 <= curCost) {\n            curCost = cost2;  // keep v closed\n        } else {\n            // Revert closure\n            open[v] = 1;\n            for (int i = 0; i < (int)resList.size(); ++i) {\n                int k = resList[i];\n                ++covCount[k];\n            }\n        }\n    }\n}\n\n// Greedy cover: choose a small set of stations covering all residents (ignoring edge cost).\n// openCov[v] = 1 for chosen stations.\nvoid build_greedy_cover(char openCov[]) {\n    vector<char> covered(K, 0);\n    int uncovered = K;\n    for (int i = 1; i <= N; ++i) openCov[i] = 0;\n\n    while (uncovered > 0) {\n        int bestStation = -1;\n        int bestGain = -1;\n        for (int v = 1; v <= N; ++v) if (!openCov[v]) {\n            int gain = 0;\n            const auto &lis = stationRes[v];\n            for (int idx = 0; idx < (int)lis.size(); ++idx) {\n                int k = lis[idx];\n                if (!covered[k]) ++gain;\n            }\n            if (gain > bestGain) {\n                bestGain = gain;\n                bestStation = v;\n            }\n        }\n        if (bestStation == -1) break;  // safety; should not happen\n        openCov[bestStation] = 1;\n        const auto &lis = stationRes[bestStation];\n        for (int idx = 0; idx < (int)lis.size(); ++idx) {\n            int k = lis[idx];\n            if (!covered[k]) {\n                covered[k] = 1;\n                --uncovered;\n            }\n        }\n    }\n}\n\n// Cost-aware greedy cover: choose stations considering approximate edge + broadcast cost.\nvoid build_cost_greedy_cover(char openCov[], const ll distFrom1[]) {\n    vector<char> covered(K, 0);\n    int uncovered = K;\n    for (int i = 1; i <= N; ++i) openCov[i] = 0;\n\n    while (uncovered > 0) {\n        int bestStation = -1;\n        double bestScore = 1e100;\n\n        for (int v = 1; v <= N; ++v) if (!openCov[v]) {\n            int gain = 0;\n            const auto &lis = stationRes[v];\n            for (int idx = 0; idx < (int)lis.size(); ++idx) {\n                int k = lis[idx];\n                if (!covered[k]) ++gain;\n            }\n            if (gain <= 0) continue;\n\n            // Approximate cost = shortest-path distance from root + typical broadcast radius^2\n            double approxCost = (double)distFrom1[v] + (double)stationMaxR2[v];\n            double score = approxCost / gain;\n            if (score < bestScore) {\n                bestScore = score;\n                bestStation = v;\n            }\n        }\n        if (bestStation == -1) break;  // safety; should not happen\n        openCov[bestStation] = 1;\n        const auto &lis = stationRes[bestStation];\n        for (int idx = 0; idx < (int)lis.size(); ++idx) {\n            int k = lis[idx];\n            if (!covered[k]) {\n                covered[k] = 1;\n                --uncovered;\n            }\n        }\n    }\n}\n\n// Simulated annealing on open[] and covCount[] starting from curCost.\n// Updates global best solution via evaluate_solution.\nvoid simulated_annealing(char open[], int covCount[], ll &curCost, int steps, mt19937_64 &rng) {\n    uniform_int_distribution<int> distV(1, N);\n    uniform_real_distribution<double> distReal(0.0, 1.0);\n\n    const double T0 = 1e7;\n    const double T1 = 1e4;\n\n    for (int step = 0; step < steps; ++step) {\n        int v = distV(rng);\n        const auto &resList = stationRes[v];\n\n        bool closing = (open[v] != 0);\n        if (closing) {\n            // Quick coverage check: cannot close if some resident is only covered by v\n            bool fail = false;\n            for (int i = 0; i < (int)resList.size(); ++i) {\n                int k = resList[i];\n                if (covCount[k] == 1) {  // only v covers k\n                    fail = true;\n                    break;\n                }\n            }\n            if (fail) continue;\n\n            // Apply closure\n            open[v] = 0;\n            for (int i = 0; i < (int)resList.size(); ++i) {\n                int k = resList[i];\n                --covCount[k];\n            }\n\n            ll newCost;\n            if (!evaluate_solution(open, newCost, P_tmp, B_tmp)) {\n                // Safety revert\n                open[v] = 1;\n                for (int i = 0; i < (int)resList.size(); ++i) {\n                    int k = resList[i];\n                    ++covCount[k];\n                }\n                continue;\n            }\n\n            if (newCost < bestCostGlobal) {\n                bestCostGlobal = newCost;\n                for (int i = 1; i <= N; ++i) P_best[i] = P_tmp[i];\n                for (int j = 0; j < M; ++j) B_best[j] = B_tmp[j];\n            }\n\n            ll delta = newCost - curCost;\n            double t = (double)step / (double)steps;\n            double T = T0 * pow(T1 / T0, t);\n            if (delta <= 0) {\n                curCost = newCost;\n            } else {\n                double prob = exp(- (double)delta / T);\n                double r = distReal(rng);\n                if (r < prob) {\n                    curCost = newCost;\n                } else {\n                    // Reject move: revert\n                    open[v] = 1;\n                    for (int i = 0; i < (int)resList.size(); ++i) {\n                        int k = resList[i];\n                        ++covCount[k];\n                    }\n                }\n            }\n        } else {\n            // Opening v\n            open[v] = 1;\n            for (int i = 0; i < (int)resList.size(); ++i) {\n                int k = resList[i];\n                ++covCount[k];\n            }\n\n            ll newCost;\n            if (!evaluate_solution(open, newCost, P_tmp, B_tmp)) {\n                // Safety revert\n                open[v] = 0;\n                for (int i = 0; i < (int)resList.size(); ++i) {\n                    int k = resList[i];\n                    --covCount[k];\n                }\n                continue;\n            }\n\n            if (newCost < bestCostGlobal) {\n                bestCostGlobal = newCost;\n                for (int i = 1; i <= N; ++i) P_best[i] = P_tmp[i];\n                for (int j = 0; j < M; ++j) B_best[j] = B_tmp[j];\n            }\n\n            ll delta = newCost - curCost;\n            double t = (double)step / (double)steps;\n            double T = T0 * pow(T1 / T0, t);\n            if (delta <= 0) {\n                curCost = newCost;\n            } else {\n                double prob = exp(- (double)delta / T);\n                double r = distReal(rng);\n                if (r < prob) {\n                    curCost = newCost;\n                } else {\n                    // Reject move: revert\n                    open[v] = 0;\n                    for (int i = 0; i < (int)resList.size(); ++i) {\n                        int k = resList[i];\n                        --covCount[k];\n                    }\n                }\n            }\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> M >> K;\n    for (int i = 1; i <= N; ++i) {\n        cin >> vx[i] >> vy[i];\n    }\n    for (int j = 0; j < M; ++j) {\n        int u, v;\n        ll w;\n        cin >> u >> v >> w;\n        edges[j] = {u, v, w};\n    }\n    for (int k = 0; k < K; ++k) {\n        cin >> ax_arr[k] >> ay_arr[k];\n    }\n\n    // Build adjacency\n    for (int i = 1; i <= N; ++i) adj[i].clear();\n    for (int j = 0; j < M; ++j) {\n        int u = edges[j].u;\n        int v = edges[j].v;\n        adj[u].push_back({v, j});\n        adj[v].push_back({u, j});\n    }\n\n    // All-pairs shortest paths (Dijkstra from each source)\n    for (int s = 1; s <= N; ++s) {\n        for (int i = 1; i <= N; ++i) {\n            distAll[s][i] = INFLL;\n            parEdge[s][i] = -1;\n        }\n        distAll[s][s] = 0;\n        priority_queue<pair<ll,int>, vector<pair<ll,int>>, greater<pair<ll,int>>> pq;\n        pq.push({0, s});\n        while (!pq.empty()) {\n            auto [d, v] = pq.top();\n            pq.pop();\n            if (d != distAll[s][v]) continue;\n            for (auto &pr : adj[v]) {\n                int to = pr.first;\n                int eidx = pr.second;\n                ll nd = d + edges[eidx].w;\n                if (nd < distAll[s][to]) {\n                    distAll[s][to] = nd;\n                    parEdge[s][to] = eidx;\n                    pq.push({nd, to});\n                }\n            }\n        }\n    }\n\n    // Distance from 1 in the original graph\n    ll distFrom1[MAXN];\n    for (int i = 1; i <= N; ++i) {\n        distFrom1[i] = distAll[1][i];\n    }\n\n    // Precompute resident candidate lists (within radius 5000)\n    const ll R2max = 5000LL * 5000LL;\n    for (int k = 0; k < K; ++k) {\n        auto &cand = residentCand[k];\n        cand.clear();\n        cand.reserve(N);\n        for (int v = 1; v <= N; ++v) {\n            ll dx = vx[v] - ax_arr[k];\n            ll dy = vy[v] - ay_arr[k];\n            ll d2 = dx * dx + dy * dy;\n            if (d2 <= R2max) {\n                cand.emplace_back(d2, v);\n            }\n        }\n        sort(cand.begin(), cand.end(),\n             [](const pair<ll,int> &a, const pair<ll,int> &b){ return a.first < b.first; });\n    }\n\n    // Build stationRes (residents each station can cover)\n    for (int v = 1; v <= N; ++v) stationRes[v].clear();\n    for (int k = 0; k < K; ++k) {\n        const auto &cand = residentCand[k];\n        for (size_t idx = 0; idx < cand.size(); ++idx) {\n            int v = cand[idx].second;\n            stationRes[v].push_back(k);\n        }\n    }\n\n    // Precompute stationMaxR2\n    for (int v = 1; v <= N; ++v) stationMaxR2[v] = 0;\n    for (int k = 0; k < K; ++k) {\n        const auto &cand = residentCand[k];\n        for (size_t idx = 0; idx < cand.size(); ++idx) {\n            ll d2 = cand[idx].first;\n            int v = cand[idx].second;\n            if (stationMaxR2[v] < d2) stationMaxR2[v] = d2;\n        }\n    }\n\n    // Precompute global edge order by weight\n    ordEdges.resize(M);\n    iota(ordEdges.begin(), ordEdges.end(), 0);\n    sort(ordEdges.begin(), ordEdges.end(),\n         [&](int a, int b){ return edges[a].w < edges[b].w; });\n\n    // Precompute removal order: vertices sorted by decreasing distFrom1\n    vector<int> order;\n    order.reserve(N);\n    for (int i = 1; i <= N; ++i) order.push_back(i);\n    sort(order.begin(), order.end(),\n         [&](int a, int b){ return distFrom1[a] > distFrom1[b]; });\n\n    mt19937_64 rng((uint64_t)chrono::steady_clock::now().time_since_epoch().count());\n\n    // Coverage counters per scenario\n    static int covCount1[MAXK], covCount2[MAXK], covCount3[MAXK];\n\n    // ----- Scenario 1: all stations open + greedy removal -----\n    static char open1[MAXN];\n    for (int i = 1; i <= N; ++i) open1[i] = 1;\n    for (int k = 0; k < K; ++k) {\n        covCount1[k] = (int)residentCand[k].size();  // all candidates open\n    }\n\n    ll cost1;\n    bool ok1 = evaluate_solution(open1, cost1, P_tmp, B_tmp);\n    if (!ok1) {\n        // Fallback: trivial legal solution (extremely unlikely needed)\n        for (int i = 1; i <= N; ++i) P_best[i] = 5000;\n        for (int j = 0; j < M; ++j) B_best[j] = 1;\n        bestCostGlobal = 0;\n        cout << P_best[1];\n        for (int i = 2; i <= N; ++i) cout << ' ' << P_best[i];\n        cout << '\\n';\n        if (M > 0) {\n            cout << (int)B_best[0];\n            for (int j = 1; j < M; ++j) cout << ' ' << (int)B_best[j];\n        }\n        cout << '\\n';\n        return 0;\n    }\n    bestCostGlobal = cost1;\n    for (int i = 1; i <= N; ++i) P_best[i] = P_tmp[i];\n    for (int j = 0; j < M; ++j) B_best[j] = B_tmp[j];\n\n    greedy_removal(open1, cost1, order, covCount1);\n\n    // ----- Scenario 2: greedy coverage + greedy removal -----\n    static char open2[MAXN];\n    build_greedy_cover(open2);\n\n    for (int k = 0; k < K; ++k) {\n        int cnt = 0;\n        const auto &cand = residentCand[k];\n        for (size_t idx = 0; idx < cand.size(); ++idx) {\n            int v = cand[idx].second;\n            if (open2[v]) ++cnt;\n        }\n        covCount2[k] = cnt;\n    }\n\n    ll cost2;\n    bool ok2 = evaluate_solution(open2, cost2, P_tmp, B_tmp);\n    if (ok2) {\n        if (cost2 < bestCostGlobal) {\n            bestCostGlobal = cost2;\n            for (int i = 1; i <= N; ++i) P_best[i] = P_tmp[i];\n            for (int j = 0; j < M; ++j) B_best[j] = B_tmp[j];\n        }\n        greedy_removal(open2, cost2, order, covCount2);\n    } else {\n        // Fallback to scenario 1 if something odd happens\n        for (int i = 1; i <= N; ++i) open2[i] = open1[i];\n        for (int k = 0; k < K; ++k) covCount2[k] = covCount1[k];\n        cost2 = cost1;\n    }\n\n    // ----- Scenario 3: cost-aware greedy coverage + greedy removal -----\n    static char open3[MAXN];\n    build_cost_greedy_cover(open3, distFrom1);\n\n    for (int k = 0; k < K; ++k) {\n        int cnt = 0;\n        const auto &cand = residentCand[k];\n        for (size_t idx = 0; idx < cand.size(); ++idx) {\n            int v = cand[idx].second;\n            if (open3[v]) ++cnt;\n        }\n        covCount3[k] = cnt;\n    }\n\n    ll cost3;\n    bool ok3 = evaluate_solution(open3, cost3, P_tmp, B_tmp);\n    if (ok3) {\n        if (cost3 < bestCostGlobal) {\n            bestCostGlobal = cost3;\n            for (int i = 1; i <= N; ++i) P_best[i] = P_tmp[i];\n            for (int j = 0; j < M; ++j) B_best[j] = B_tmp[j];\n        }\n        greedy_removal(open3, cost3, order, covCount3);\n    } else {\n        // Fallback to scenario 1\n        for (int i = 1; i <= N; ++i) open3[i] = open1[i];\n        for (int k = 0; k < K; ++k) covCount3[k] = covCount1[k];\n        cost3 = cost1;\n    }\n\n    // ----- Simulated annealing: three runs from different starts -----\n    const int SA_STEPS_PER_RUN = 1800;  // total ~5400 evaluations\n\n    simulated_annealing(open1, covCount1, cost1, SA_STEPS_PER_RUN, rng);\n    simulated_annealing(open2, covCount2, cost2, SA_STEPS_PER_RUN, rng);\n    simulated_annealing(open3, covCount3, cost3, SA_STEPS_PER_RUN, rng);\n\n    // ----- Output best solution -----\n    cout << P_best[1];\n    for (int i = 2; i <= N; ++i) {\n        cout << ' ' << P_best[i];\n    }\n    cout << '\\n';\n\n    if (M > 0) {\n        cout << (int)B_best[0];\n        for (int j = 1; j < M; ++j) {\n            cout << ' ' << (int)B_best[j];\n        }\n    }\n    cout << '\\n';\n\n    return 0;\n}","ahc021":"#include <bits/stdc++.h>\nusing namespace std;\n\n// ---------------- Structures ----------------\n\nstruct Edge {\n    int u, v; // indices of nodes\n};\n\nstruct Op {\n    short x1, y1, x2, y2; // coordinates of swapped cells\n};\n\n// ---------------- Simple RNG (xorshift) ----------------\n\nstruct XorShift {\n    uint64_t x;\n    XorShift(uint64_t seed = 123456789) : x(seed) {}\n    uint64_t operator()() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return x;\n    }\n    int next_int(int n) { // 0..n-1\n        return (int)(operator()() % (uint64_t)n);\n    }\n};\n\n// ---------------- Violation computation ----------------\n\n// Compute total number of violations E\nint computeE(const vector<int> &a, const vector<Edge> &dEdges) {\n    int E = 0;\n    for (const auto &e : dEdges) {\n        if (a[e.u] > a[e.v]) ++E;\n    }\n    return E;\n}\n\n// Delta E for swapping two neighboring nodes u, v\nint deltaE_for_swap(const vector<int> &a, int u, int v,\n                    const vector<Edge> &dEdges,\n                    const vector<vector<int>> &nodeEdgeIds) {\n    int valU = a[u];\n    int valV = a[v];\n\n    int edges[16];\n    int cnt = 0;\n\n    // collect incident edges of u\n    for (int id : nodeEdgeIds[u]) {\n        edges[cnt++] = id;\n    }\n    // add incident edges of v, avoiding duplicates\n    for (int id : nodeEdgeIds[v]) {\n        bool dup = false;\n        for (int i = 0; i < cnt; ++i) {\n            if (edges[i] == id) {\n                dup = true;\n                break;\n            }\n        }\n        if (!dup) edges[cnt++] = id;\n    }\n\n    int delta = 0;\n    for (int i = 0; i < cnt; ++i) {\n        const Edge &e = dEdges[edges[i]];\n        int aIdx = e.u;\n        int bIdx = e.v;\n\n        int beforeA = a[aIdx];\n        int beforeB = a[bIdx];\n        bool before = (beforeA > beforeB);\n\n        int afterA = (aIdx == u ? valV : (aIdx == v ? valU : beforeA));\n        int afterB = (bIdx == u ? valV : (bIdx == v ? valU : beforeB));\n        bool after = (afterA > afterB);\n\n        delta += (int)after - (int)before;\n    }\n    return delta;\n}\n\n// ---------------- One heuristic run ----------------\n\n// Performs one run (starting from \"initial\"); returns operations and final E.\nvoid run_single(const vector<int> &initial,\n                const vector<Edge> &dEdges,\n                const vector<Edge> &adjEdges,\n                const vector<vector<int>> &nodeEdgeIds,\n                const vector<int> &posX,\n                const vector<int> &posY,\n                XorShift &rng,\n                vector<Op> &opsOut,\n                int &EOut) {\n    const int maxK = 10000;\n    vector<int> a = initial;\n\n    vector<Op> ops;\n    ops.reserve(maxK);\n\n    int K = 0;\n    int E = computeE(a, dEdges);\n\n    // ---------- Stage 1: bubble along parent-child edges (heapify-like) ----------\n    // Swap whenever parent > child, regardless of global E.\n    const int limitStage1       = maxK * 8 / 10; // up to 8000 swaps\n    const int E_threshold       = 30;            // stop Stage1 early if already low\n    const int recalc_interval_1 = 128;           // more frequent checks than before\n\n    if (E > 0) {\n        int dM = (int)dEdges.size();\n        bool done = false;\n        while (K < limitStage1 && !done) {\n            bool swappedPass = false;\n            int start = rng.next_int(dM); // random starting position\n\n            for (int t = 0; t < dM && K < limitStage1; ++t) {\n                const Edge &ed = dEdges[(start + t) % dM];\n                int u = ed.u;\n                int v = ed.v;\n                if (a[u] > a[v]) {\n                    swap(a[u], a[v]);\n                    ops.push_back(Op{(short)posX[u], (short)posY[u],\n                                     (short)posX[v], (short)posY[v]});\n                    ++K;\n                    swappedPass = true;\n\n                    if ((K % recalc_interval_1 == 0) || K >= limitStage1) {\n                        E = computeE(a, dEdges);\n                        if (E == 0 || E <= E_threshold || K >= limitStage1) {\n                            done = true;\n                            break;\n                        }\n                    }\n                }\n            }\n            if (!swappedPass) {\n                // No violating parent-child edge => E = 0\n                E = 0;\n                done = true;\n                break;\n            }\n        }\n    }\n\n    // ---------- Stage 2: greedy best-improvement + random kicks ----------\n    if (E != 0 && K < maxK) {\n        E = computeE(a, dEdges); // ensure E is up-to-date\n        int M = (int)adjEdges.size();\n\n        const int maxKickMoves   = 25; // maximum number of uphill moves\n        const int maxKickDelta   = 4;  // allow \u0394E up to +4 in kicks\n        const int maxKickTrials  = 80; // trials to find a candidate edge per kick\n        const int recalc_interval_2 = 256; // periodically recompute E for safety\n\n        int kicksUsed = 0;\n\n        while (K < maxK && E > 0) {\n            bool improved = false;\n\n            // ----- Best-improvement step: scan all edges and choose best \u0394E < 0 -----\n            int bestDelta = 0;\n            int bestIdx   = -1;\n            int start = rng.next_int(M);\n\n            for (int t = 0; t < M; ++t) {\n                int idx = (start + t) % M;\n                const Edge &edge = adjEdges[idx];\n                int u = edge.u;\n                int v = edge.v;\n\n                int delta = deltaE_for_swap(a, u, v, dEdges, nodeEdgeIds);\n                if (delta < bestDelta) {\n                    bestDelta = delta;\n                    bestIdx   = idx;\n                }\n            }\n\n            if (bestIdx != -1 && K < maxK) {\n                const Edge &edge = adjEdges[bestIdx];\n                int u = edge.u;\n                int v = edge.v;\n                swap(a[u], a[v]);\n                ops.push_back(Op{(short)posX[u], (short)posY[u],\n                                 (short)posX[v], (short)posY[v]});\n                ++K;\n                E += bestDelta;\n                improved = true;\n\n                if (K % recalc_interval_2 == 0) {\n                    E = computeE(a, dEdges);\n                }\n            }\n\n            if (improved) continue;\n\n            // ----- No improving swap: use random kicks to escape local minima -----\n            if (kicksUsed >= maxKickMoves) break;\n\n            bool kicked = false;\n            for (int trials = 0; trials < maxKickTrials && K < maxK; ++trials) {\n                int idx = rng.next_int(M);\n                const Edge &edge = adjEdges[idx];\n                int u = edge.u;\n                int v = edge.v;\n\n                int delta = deltaE_for_swap(a, u, v, dEdges, nodeEdgeIds);\n\n                // Allow small uphill/neutral moves to escape local minima\n                if (delta <= maxKickDelta) {\n                    swap(a[u], a[v]);\n                    ops.push_back(Op{(short)posX[u], (short)posY[u],\n                                     (short)posX[v], (short)posY[v]});\n                    ++K;\n                    E += delta;\n                    if (delta > 0) ++kicksUsed;\n                    kicked = true;\n\n                    if (K % recalc_interval_2 == 0) {\n                        E = computeE(a, dEdges);\n                    }\n                    break;\n                }\n            }\n\n            if (!kicked) break; // couldn't find a reasonable kick move\n        }\n    }\n\n    // Final accurate E\n    EOut = computeE(a, dEdges);\n    opsOut.swap(ops);\n}\n\n// ---------------- Main ----------------\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    const int N = 30;\n    const int numNodes = N * (N + 1) / 2;\n\n    // Read input and build id / coordinate mapping\n    vector<int> a0(numNodes);\n    vector<int> posX(numNodes), posY(numNodes);\n    vector<vector<int>> id(N);\n    int cur = 0;\n    for (int x = 0; x < N; ++x) {\n        id[x].resize(x + 1);\n        for (int y = 0; y <= x; ++y) {\n            id[x][y] = cur;\n            posX[cur] = x;\n            posY[cur] = y;\n            int v;\n            cin >> v;\n            a0[cur] = v;\n            ++cur;\n        }\n    }\n\n    // Build DAG edges (parent -> child)\n    vector<Edge> dEdges;\n    dEdges.reserve(2 * (N - 1) * N / 2);\n    for (int x = 0; x < N - 1; ++x) {\n        for (int y = 0; y <= x; ++y) {\n            int p = id[x][y];\n            int c1 = id[x + 1][y];\n            int c2 = id[x + 1][y + 1];\n            dEdges.push_back(Edge{p, c1});\n            dEdges.push_back(Edge{p, c2});\n        }\n    }\n\n    // For each node, list incident DAG edges (indices into dEdges)\n    vector<vector<int>> nodeEdgeIds(numNodes);\n    for (int ei = 0; ei < (int)dEdges.size(); ++ei) {\n        int u = dEdges[ei].u;\n        int v = dEdges[ei].v;\n        nodeEdgeIds[u].push_back(ei);\n        nodeEdgeIds[v].push_back(ei);\n    }\n\n    // Build adjacency edges of triangular grid (undirected)\n    const int dx[6] = {-1, -1, 0, 0, 1, 1};\n    const int dy[6] = {-1, 0, -1, 1, 0, 1};\n    vector<Edge> adjEdges;\n    adjEdges.reserve(3 * numNodes); // rough upper bound\n\n    for (int x = 0; x < N; ++x) {\n        for (int y = 0; y <= x; ++y) {\n            int u = id[x][y];\n            for (int dir = 0; dir < 6; ++dir) {\n                int nx = x + dx[dir];\n                int ny = y + dy[dir];\n                if (nx < 0 || nx >= N) continue;\n                if (ny < 0 || ny > nx) continue;\n                int v = id[nx][ny];\n                if (v > u) { // avoid duplicates (treat undirected)\n                    adjEdges.push_back(Edge{u, v});\n                }\n            }\n        }\n    }\n\n    // Seed RNG with time-based seed\n    uint64_t seed = chrono::high_resolution_clock::now().time_since_epoch().count();\n    XorShift rng(seed);\n\n    // Multiple restarts; keep the best result\n    const int MAX_RESTARTS = 40;  // increased for better best-of performance\n    vector<Op> bestOps;\n    int bestE = INT_MAX;\n    int bestK = INT_MAX;\n\n    for (int iter = 0; iter < MAX_RESTARTS; ++iter) {\n        vector<Op> curOps;\n        int curE;\n        run_single(a0, dEdges, adjEdges, nodeEdgeIds, posX, posY,\n                   rng, curOps, curE);\n        int curK = (int)curOps.size();\n\n        if (curE < bestE || (curE == bestE && curK < bestK)) {\n            bestE = curE;\n            bestK = curK;\n            bestOps = std::move(curOps);\n        }\n    }\n\n    // Output\n    cout << bestOps.size() << '\\n';\n    for (const auto &op : bestOps) {\n        cout << op.x1 << ' ' << op.y1 << ' '\n             << op.x2 << ' ' << op.y2 << '\\n';\n    }\n\n    return 0;\n}","toyota2023summer-final":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Cell {\n    int r, c, dist;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int D, N;\n    if (!(cin >> D >> N)) return 0;\n\n    const int er = 0;\n    const int ec = (D - 1) / 2;\n\n    vector<vector<bool>> isObstacle(D, vector<bool>(D, false));\n    for (int k = 0; k < N; ++k) {\n        int r, c;\n        cin >> r >> c;\n        isObstacle[r][c] = true;\n    }\n\n    // 1. Static BFS distances from entrance (considering only obstacles).\n    vector<vector<int>> dist(D, vector<int>(D, -1));\n    {\n        queue<pair<int,int>> q;\n        dist[er][ec] = 0;\n        q.push({er, ec});\n        const int dr[4] = {1, -1, 0, 0};\n        const int dc[4] = {0, 0, 1, -1};\n        while (!q.empty()) {\n            auto [r, c] = q.front();\n            q.pop();\n            for (int d = 0; d < 4; ++d) {\n                int nr = r + dr[d];\n                int nc = c + dc[d];\n                if (nr < 0 || nr >= D || nc < 0 || nc >= D) continue;\n                if (isObstacle[nr][nc]) continue;\n                if (dist[nr][nc] != -1) continue;\n                dist[nr][nc] = dist[r][c] + 1;\n                q.push({nr, nc});\n            }\n        }\n    }\n\n    // 2. Collect storeable cells (non-entrance, non-obstacle) with distances.\n    vector<Cell> cells;\n    cells.reserve(D * D);\n    for (int r = 0; r < D; ++r) {\n        for (int c = 0; c < D; ++c) {\n            if (r == er && c == ec) continue;\n            if (isObstacle[r][c]) continue;\n            cells.push_back({r, c, dist[r][c]});\n        }\n    }\n    int M = (int)cells.size(); // D^2 - 1 - N\n\n    // 3. Sort cells by distance from entrance, then row, then column.\n    sort(cells.begin(), cells.end(), [](const Cell &a, const Cell &b) {\n        if (a.dist != b.dist) return a.dist < b.dist;\n        if (a.r != b.r) return a.r < b.r;\n        return a.c < b.c;\n    });\n\n    // Occupancy and labels.\n    vector<vector<bool>> hasContainer(D, vector<bool>(D, false));\n    vector<vector<int>>  labelGrid(D, vector<int>(D, -1));\n    vector<bool> usedIndex(M, false);          // whether cells[i] already has a container\n    vector<int> assignedIdxOfLabel(M, -1);     // index of cell for each label (if assigned)\n\n    // BFS to count reachable empty cells (excluding entrance) from entrance,\n    // with current hasContainer + isObstacle.\n    auto bfs_count_reachable_empty = [&]() -> int {\n        vector<vector<char>> vis(D, vector<char>(D, 0));\n        queue<pair<int,int>> q;\n        vis[er][ec] = 1;\n        q.push({er, ec});\n        const int dr[4] = {1, -1, 0, 0};\n        const int dc[4] = {0, 0, 1, -1};\n\n        while (!q.empty()) {\n            auto [r, c] = q.front();\n            q.pop();\n            for (int d = 0; d < 4; ++d) {\n                int nr = r + dr[d];\n                int nc = c + dc[d];\n                if (nr < 0 || nr >= D || nc < 0 || nc >= D) continue;\n                if (vis[nr][nc]) continue;\n                if (isObstacle[nr][nc]) continue;\n                if (hasContainer[nr][nc]) continue;\n                vis[nr][nc] = 1;\n                q.push({nr, nc});\n            }\n        }\n\n        int cnt = 0;\n        for (int r = 0; r < D; ++r) {\n            for (int c = 0; c < D; ++c) {\n                if (r == er && c == ec) continue;\n                if (isObstacle[r][c]) continue;\n                if (hasContainer[r][c]) continue;\n                if (vis[r][c]) ++cnt;\n            }\n        }\n        return cnt;\n    };\n\n    auto is_safe_index = [&](int idx, int placed) -> bool {\n        const Cell &cell = cells[idx];\n        int r = cell.r, c = cell.c;\n        hasContainer[r][c] = true;\n        int reachableEmpty = bfs_count_reachable_empty();\n        hasContainer[r][c] = false;\n        int emptiesAfter = M - (placed + 1);\n        return reachableEmpty == emptiesAfter;\n    };\n\n    // 4. Storage phase: choose safe index minimizing weighted crossings with assigned labels.\n    //    We weight \"smaller labels placed deeper\" more heavily.\n    for (int step = 0; step < M; ++step) {\n        int t;\n        cin >> t;\n\n        int bestIdx   = -1;\n        int bestInv   = INT_MAX;\n        int bestDelta = INT_MAX;\n\n        for (int i = 0; i < M; ++i) {\n            if (usedIndex[i]) continue;\n            if (!is_safe_index(i, step)) continue;\n\n            int cross_small_right = 0;\n            int cross_large_left  = 0;\n\n            // Smaller labels placed deeper than i.\n            for (int l = 0; l < t; ++l) {\n                int idxL = assignedIdxOfLabel[l];\n                if (idxL != -1 && idxL > i) ++cross_small_right;\n            }\n            // Larger labels placed shallower than i.\n            for (int l = t + 1; l < M; ++l) {\n                int idxL = assignedIdxOfLabel[l];\n                if (idxL != -1 && idxL < i) ++cross_large_left;\n            }\n\n            // Weight smaller-label-deeper crossings more heavily.\n            int inv   = 2 * cross_small_right + cross_large_left;\n            int delta = abs(i - t);\n\n            if (inv < bestInv ||\n                (inv == bestInv && delta < bestDelta)) {\n                bestInv   = inv;\n                bestDelta = delta;\n                bestIdx   = i;\n            }\n        }\n\n        // Fallback: if somehow no safe index is found (should be extremely rare),\n        // pick any free index.\n        if (bestIdx == -1) {\n            for (int i = 0; i < M; ++i) {\n                if (!usedIndex[i]) {\n                    bestIdx = i;\n                    break;\n                }\n            }\n        }\n\n        usedIndex[bestIdx] = true;\n        assignedIdxOfLabel[t] = bestIdx;\n\n        int r = cells[bestIdx].r;\n        int c = cells[bestIdx].c;\n        hasContainer[r][c] = true;\n        labelGrid[r][c] = t;\n\n        cout << r << ' ' << c << '\\n' << flush;\n    }\n\n    // 5. Retrieval phase: always remove the smallest label currently accessible.\n    auto bfs_reachable_empty = [&](vector<vector<char>> &vis) {\n        vis.assign(D, vector<char>(D, 0));\n        queue<pair<int,int>> q;\n        vis[er][ec] = 1;\n        q.push({er, ec});\n        const int dr[4] = {1, -1, 0, 0};\n        const int dc[4] = {0, 0, 1, -1};\n        while (!q.empty()) {\n            auto [r, c] = q.front();\n            q.pop();\n            for (int d = 0; d < 4; ++d) {\n                int nr = r + dr[d];\n                int nc = c + dc[d];\n                if (nr < 0 || nr >= D || nc < 0 || nc >= D) continue;\n                if (vis[nr][nc]) continue;\n                if (isObstacle[nr][nc]) continue;\n                if (hasContainer[nr][nc]) continue;\n                vis[nr][nc] = 1;\n                q.push({nr, nc});\n            }\n        }\n    };\n\n    const int dr4[4] = {1, -1, 0, 0};\n    const int dc4[4] = {0, 0, 1, -1};\n    vector<vector<char>> vis;\n\n    for (int step = 0; step < M; ++step) {\n        bfs_reachable_empty(vis);\n\n        int bestLabel = INT_MAX;\n        int bestR = -1, bestC = -1;\n\n        for (int r = 0; r < D; ++r) {\n            for (int c = 0; c < D; ++c) {\n                if (!hasContainer[r][c]) continue;\n                bool accessible = false;\n                for (int d = 0; d < 4; ++d) {\n                    int nr = r + dr4[d];\n                    int nc = c + dc4[d];\n                    if (nr < 0 || nr >= D || nc < 0 || nc >= D) continue;\n                    if (isObstacle[nr][nc]) continue;\n                    if (hasContainer[nr][nc]) continue; // neighbor must be empty\n                    if (vis[nr][nc]) {\n                        accessible = true;\n                        break;\n                    }\n                }\n                if (!accessible) continue;\n                int lbl = labelGrid[r][c];\n                if (lbl < bestLabel) {\n                    bestLabel = lbl;\n                    bestR = r;\n                    bestC = c;\n                }\n            }\n        }\n\n        // Fallback (should not happen if storage kept empties connected).\n        if (bestR == -1) {\n            for (int r = 0; r < D && bestR == -1; ++r)\n                for (int c = 0; c < D && bestR == -1; ++c)\n                    if (hasContainer[r][c]) {\n                        bestR = r;\n                        bestC = c;\n                    }\n        }\n\n        cout << bestR << ' ' << bestC << '\\n';\n        hasContainer[bestR][bestC] = false;\n        labelGrid[bestR][bestC] = -1;\n    }\n\n    cout.flush();\n    return 0;\n}","ahc024":"#include <bits/stdc++.h>\nusing namespace std;\n\n// Constants\nconst int MAXM = 100;\nconst int MAXN = 50;\n\nint n, m; // n = 50, m = 100\n\n// Original grid\nvector<vector<int>> orig_grid;\n\n// Original adjacency matrix: adj_orig[a][b] is true iff colors a and b are adjacent in the original map\nbool adj_orig[MAXM + 1][MAXM + 1];\n\n// Current adjacency as edge counts (for each unordered pair a<b): number of edges between colors a and b\nint edgeCount[MAXM + 1][MAXM + 1];\n\n// Number of outside-adjacency edges for each cell (i,j)\nint outsideAdjEdges[MAXN][MAXN];\n\n// Whether color c may touch 0 (i.e., had adjacency with 0 in original)\nbool allowedZeroAdj[MAXM + 1];\n\n// Directions for 4-neighborhood\nconst int DX[4] = {1, -1, 0, 0};\nconst int DY[4] = {0, 0, 1, -1};\n\n// Compute adjacency matrix for a given grid (used only for the original grid)\nvoid computeAdj(const vector<vector<int>> &g, bool adj[MAXM + 1][MAXM + 1]) {\n    for (int i = 0; i <= m; i++) {\n        for (int j = 0; j <= m; j++) {\n            adj[i][j] = false;\n        }\n    }\n\n    // Internal adjacency in the grid\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            int a = g[i][j];\n            if (i + 1 < n) {\n                int b = g[i + 1][j];\n                if (a != b) adj[a][b] = adj[b][a] = true;\n            }\n            if (j + 1 < n) {\n                int b = g[i][j + 1];\n                if (a != b) adj[a][b] = adj[b][a] = true;\n            }\n        }\n    }\n\n    // Adjacency with outside (color 0) via boundary cells\n    for (int i = 0; i < n; i++) {\n        int c1 = g[i][0];\n        if (c1 != 0) adj[0][c1] = adj[c1][0] = true;\n        int c2 = g[i][n - 1];\n        if (c2 != 0) adj[0][c2] = adj[c2][0] = true;\n    }\n    for (int j = 1; j < n - 1; j++) {\n        int c1 = g[0][j];\n        if (c1 != 0) adj[0][c1] = adj[c1][0] = true;\n        int c2 = g[n - 1][j];\n        if (c2 != 0) adj[0][c2] = adj[c2][0] = true;\n    }\n}\n\n// Initialize edgeCount[a][b] from a given grid\nvoid initAdjCounts(const vector<vector<int>> &g) {\n    for (int i = 0; i <= m; i++) {\n        for (int j = 0; j <= m; j++) {\n            edgeCount[i][j] = 0;\n        }\n    }\n\n    // Internal edges in the grid\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            int a = g[i][j];\n            if (i + 1 < n) {\n                int b = g[i + 1][j];\n                if (a != b) {\n                    int x = min(a, b), y = max(a, b);\n                    edgeCount[x][y]++;\n                }\n            }\n            if (j + 1 < n) {\n                int b = g[i][j + 1];\n                if (a != b) {\n                    int x = min(a, b), y = max(a, b);\n                    edgeCount[x][y]++;\n                }\n            }\n        }\n    }\n\n    // Outside adjacency (between color 0 and each boundary cell's color)\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            int c = g[i][j];\n            int outE = outsideAdjEdges[i][j];\n            if (outE > 0 && c != 0) {\n                int x = 0, y = c; // 0 < c\n                edgeCount[x][y] += outE;\n            }\n        }\n    }\n}\n\n// Check that after removing cell (x, y) from color 'col',\n// the remaining cells of 'col' stay connected.\n//\n// grid[x][y] must already be recolored to something != col before calling.\nbool checkColorConnectivityAfterRemoval(int x, int y, int col, const vector<vector<int>> &grid) {\n    // Collect same-color neighbors of (x, y)\n    pair<int,int> nbrs[4];\n    int k = 0;\n    for (int dir = 0; dir < 4; dir++) {\n        int nx = x + DX[dir];\n        int ny = y + DY[dir];\n        if (nx < 0 || nx >= n || ny < 0 || ny >= n) continue;\n        if (grid[nx][ny] == col) {\n            nbrs[k++] = {nx, ny};\n        }\n    }\n    if (k <= 1) {\n        // Vertex with degree <=1 in its color component cannot be articulation\n        return true;\n    }\n\n    // BFS from first neighbor, check if we can reach all other neighbors\n    static vector<char> vis;\n    int N = n * n;\n    if ((int)vis.size() != N) vis.assign(N, 0);\n    else fill(vis.begin(), vis.end(), 0);\n\n    auto idx_of = [&](int xx, int yy) { return xx * n + yy; };\n\n    queue<pair<int,int>> q;\n    q.push(nbrs[0]);\n    vis[idx_of(nbrs[0].first, nbrs[0].second)] = 1;\n\n    bool reached[4] = {false,false,false,false};\n    reached[0] = true;\n    int reachedCnt = 1;\n\n    while (!q.empty() && reachedCnt < k) {\n        auto [cx, cy] = q.front(); q.pop();\n        for (int dir = 0; dir < 4; dir++) {\n            int nx = cx + DX[dir];\n            int ny = cy + DY[dir];\n            if (nx < 0 || nx >= n || ny < 0 || ny >= n) continue;\n            if (grid[nx][ny] != col) continue;\n            int idx = idx_of(nx, ny);\n            if (vis[idx]) continue;\n            vis[idx] = 1;\n            q.emplace(nx, ny);\n\n            // Check if this is one of the neighbors of (x,y)\n            for (int t = 1; t < k; t++) {\n                if (!reached[t] && nbrs[t].first == nx && nbrs[t].second == ny) {\n                    reached[t] = true;\n                    reachedCnt++;\n                    break;\n                }\n            }\n        }\n    }\n    return (reachedCnt == k);\n}\n\n// Try to change cell (x, y) from its current color to 0.\nbool tryChangeToZero(int x, int y,\n                     vector<vector<int>> &grid,\n                     vector<int> &countColor,\n                     mt19937_64 &rng) {\n    int oldCol = grid[x][y];\n    if (oldCol == 0) return false;\n    if (countColor[oldCol] <= 1) return false; // don't delete last cell of a color\n\n    // Condition for 0 connectivity: new 0 must be on boundary or adjacent to an existing 0\n    bool boundary = (x == 0 || x == n - 1 || y == 0 || y == n - 1);\n    bool adjZero = false;\n    if (!boundary) {\n        for (int dir = 0; dir < 4; dir++) {\n            int nx = x + DX[dir];\n            int ny = y + DY[dir];\n            if (nx < 0 || nx >= n || ny < 0 || ny >= n) continue;\n            if (grid[nx][ny] == 0) {\n                adjZero = true;\n                break;\n            }\n        }\n    }\n    if (!boundary && !adjZero) return false;\n\n    // Quick filter: no new adjacency between 0 and colors that originally didn't touch 0\n    for (int dir = 0; dir < 4; dir++) {\n        int nx = x + DX[dir];\n        int ny = y + DY[dir];\n        if (nx < 0 || nx >= n || ny < 0 || ny >= n) continue;\n        int d = grid[nx][ny];\n        if (!allowedZeroAdj[d]) {\n            return false;\n        }\n    }\n\n    // Count same-color neighbors (for potential connectivity check)\n    pair<int,int> nbrs[4];\n    int k = 0;\n    for (int dir = 0; dir < 4; dir++) {\n        int nx = x + DX[dir];\n        int ny = y + DY[dir];\n        if (nx < 0 || nx >= n || ny < 0 || ny >= n) continue;\n        if (grid[nx][ny] == oldCol) {\n            nbrs[k++] = {nx, ny};\n        }\n    }\n\n    // Tentatively recolor to 0\n    grid[x][y] = 0;\n    countColor[oldCol]--;\n    countColor[0]++;\n\n    bool ok = true;\n\n    // If degree in color component >= 2, check connectivity via neighbor test\n    if (k >= 2) {\n        if (!checkColorConnectivityAfterRemoval(x, y, oldCol, grid)) {\n            ok = false;\n        }\n    }\n\n    if (!ok) {\n        grid[x][y] = oldCol;\n        countColor[oldCol]++;\n        countColor[0]--;\n        return false;\n    }\n\n    // Incremental adjacency update\n    struct Delta {\n        int a, b, d;\n    };\n    static vector<Delta> deltas;\n    deltas.clear();\n\n    auto addDelta = [&](int a, int b, int delta) {\n        if (a == b) return; // we don't track same-color adjacency\n        if (a > b) swap(a, b);\n        for (auto &dd : deltas) {\n            if (dd.a == a && dd.b == b) {\n                dd.d += delta;\n                return;\n            }\n        }\n        deltas.push_back({a, b, delta});\n    };\n\n    // Internal neighbors: adjust oldCol-d and 0-d\n    for (int dir = 0; dir < 4; dir++) {\n        int nx = x + DX[dir];\n        int ny = y + DY[dir];\n        if (nx < 0 || nx >= n || ny < 0 || ny >= n) continue;\n        int d = grid[nx][ny]; // after recolor: grid[x][y] = 0\n\n        // Remove old adjacency oldCol-d if existed\n        if (d != oldCol) {\n            int a = min(oldCol, d), b = max(oldCol, d);\n            addDelta(a, b, -1);\n        }\n        // Add new adjacency 0-d if d != 0\n        if (d != 0) {\n            int a = 0, b = d;\n            addDelta(a, b, +1);\n        }\n    }\n\n    // Outside adjacency edges: oldCol had 'outE' adjacency edges with 0, now 0-0\n    int outE = outsideAdjEdges[x][y];\n    if (outE > 0) {\n        int a = 0, b = oldCol;\n        addDelta(a, b, -outE);\n    }\n\n    // Apply deltas to edgeCount\n    for (auto &dd : deltas) {\n        edgeCount[dd.a][dd.b] += dd.d;\n    }\n\n    // Check adjacency for affected pairs only\n    for (auto &dd : deltas) {\n        int a = dd.a, b = dd.b;\n        bool curAdj = (edgeCount[a][b] > 0);\n        if (curAdj != adj_orig[a][b]) {\n            ok = false;\n            break;\n        }\n    }\n\n    if (!ok) {\n        // Revert edge counts\n        for (auto &dd : deltas) {\n            edgeCount[dd.a][dd.b] -= dd.d;\n        }\n        // Revert color\n        grid[x][y] = oldCol;\n        countColor[oldCol]++;\n        countColor[0]--;\n        return false;\n    }\n\n    // Successful recolor\n    return true;\n}\n\n// Try to recolor cell (x, y) from its current color to newCol (both >0).\n// Keeps adjacency matrix (via edgeCount) and connectivity of oldCol.\nbool tryRecolorToColor(int x, int y, int newCol,\n                       vector<vector<int>> &grid,\n                       vector<int> &countColor) {\n    int oldCol = grid[x][y];\n    if (oldCol == newCol) return false;\n    if (oldCol == 0 || newCol == 0) return false;\n    if (countColor[oldCol] <= 1) return false; // keep at least one cell per color\n\n    // Quick adjacency filter: we must not create adjacency newCol-e if adj_orig[newCol][e] is false\n    // (for any neighbor e where newCol != e).\n    for (int dir = 0; dir < 4; dir++) {\n        int nx = x + DX[dir];\n        int ny = y + DY[dir];\n        if (nx < 0 || nx >= n || ny < 0 || ny >= n) continue;\n        int e = grid[nx][ny];\n        if (e != newCol && !adj_orig[newCol][e]) return false;\n    }\n    // Also check adjacency with outside: if this cell has outside edges, then 0-newCol must be allowed\n    int outE = outsideAdjEdges[x][y];\n    if (outE > 0 && !adj_orig[0][newCol]) return false;\n\n    // Count same-color neighbors for connectivity test\n    pair<int,int> nbrs[4];\n    int k = 0;\n    for (int dir = 0; dir < 4; dir++) {\n        int nx = x + DX[dir];\n        int ny = y + DY[dir];\n        if (nx < 0 || nx >= n || ny < 0 || ny >= n) continue;\n        if (grid[nx][ny] == oldCol) {\n            nbrs[k++] = {nx, ny};\n        }\n    }\n\n    // Tentatively recolor\n    grid[x][y] = newCol;\n    countColor[oldCol]--;\n    countColor[newCol]++;\n\n    bool ok = true;\n\n    // If degree in oldCol component >= 2, check connectivity\n    if (k >= 2) {\n        if (!checkColorConnectivityAfterRemoval(x, y, oldCol, grid)) {\n            ok = false;\n        }\n    }\n\n    if (!ok) {\n        grid[x][y] = oldCol;\n        countColor[oldCol]++;\n        countColor[newCol]--;\n        return false;\n    }\n\n    // Incremental adjacency update for recolor oldCol -> newCol\n    struct Delta {\n        int a, b, d;\n    };\n    static vector<Delta> deltas;\n    deltas.clear();\n\n    auto addDelta = [&](int a, int b, int delta) {\n        if (a == b) return; // we don't track same-color adjacency\n        if (a > b) swap(a, b);\n        for (auto &dd : deltas) {\n            if (dd.a == a && dd.b == b) {\n                dd.d += delta;\n                return;\n            }\n        }\n        deltas.push_back({a, b, delta});\n    };\n\n    // Internal neighbors\n    for (int dir = 0; dir < 4; dir++) {\n        int nx = x + DX[dir];\n        int ny = y + DY[dir];\n        if (nx < 0 || nx >= n || ny < 0 || ny >= n) continue;\n        int e = grid[nx][ny]; // after recolor: grid[x][y] = newCol\n\n        // Remove old adjacency oldCol-e if existed\n        if (e != oldCol) {\n            int a = min(oldCol, e), b = max(oldCol, e);\n            addDelta(a, b, -1);\n        }\n        // Add new adjacency newCol-e if e != newCol\n        if (e != newCol) {\n            int a = min(newCol, e), b = max(newCol, e);\n            addDelta(a, b, +1);\n        }\n    }\n\n    // Outside adjacency: oldCol loses, newCol gains\n    if (outE > 0) {\n        int a1 = 0, b1 = oldCol;\n        addDelta(a1, b1, -outE);\n        int a2 = 0, b2 = newCol;\n        addDelta(a2, b2, +outE);\n    }\n\n    // Apply deltas\n    for (auto &dd : deltas) {\n        edgeCount[dd.a][dd.b] += dd.d;\n    }\n\n    // Check adjacency for affected pairs\n    for (auto &dd : deltas) {\n        int a = dd.a, b = dd.b;\n        bool curAdj = (edgeCount[a][b] > 0);\n        if (curAdj != adj_orig[a][b]) {\n            ok = false;\n            break;\n        }\n    }\n\n    if (!ok) {\n        // Revert edge counts\n        for (auto &dd : deltas) {\n            edgeCount[dd.a][dd.b] -= dd.d;\n        }\n        // Revert recolor\n        grid[x][y] = oldCol;\n        countColor[oldCol]++;\n        countColor[newCol]--;\n        return false;\n    }\n\n    return true;\n}\n\n// Run one greedy pass with a given RNG seed and time limit.\n// Returns the number of 0 cells in the resulting grid, and writes that grid into out_grid.\nint solve_one(uint64_t seed, double timeLimit, vector<vector<int>> &out_grid) {\n    // Initialize current grid and color counts\n    vector<vector<int>> cur_grid = orig_grid;\n    vector<int> countColor(m + 1, 0);\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            countColor[cur_grid[i][j]]++;\n        }\n    }\n\n    // Initialize edge counts\n    initAdjCounts(cur_grid);\n\n    // RNG for this run\n    mt19937_64 rng(seed);\n\n    auto start_time = chrono::steady_clock::now();\n    const double TIME_LIMIT = timeLimit;\n    const double RECOLOR_FRAC = 0.25; // 25% of run time for recolor phase\n\n    int Ncells = n * n;\n    vector<char> inQueue(Ncells, 0);\n\n    // ---- Phase 1: recolor \"interior\" colors into \"outer\" colors ----\n    {\n        double recLimit = TIME_LIMIT * RECOLOR_FRAC;\n        bool changed = true;\n\n        while (changed) {\n            auto now = chrono::steady_clock::now();\n            double elapsed = chrono::duration<double>(now - start_time).count();\n            if (elapsed > recLimit) break;\n\n            changed = false;\n\n            // Generate cell indices in random order\n            static vector<int> order;\n            order.resize(Ncells);\n            iota(order.begin(), order.end(), 0);\n            shuffle(order.begin(), order.end(), rng);\n\n            for (int idx : order) {\n                auto now2 = chrono::steady_clock::now();\n                double elapsed2 = chrono::duration<double>(now2 - start_time).count();\n                if (elapsed2 > recLimit) break;\n\n                int x = idx / n;\n                int y = idx % n;\n                int c = cur_grid[x][y];\n                if (c == 0) continue;\n                // Only recolor colors that are not allowed to touch 0 originally\n                if (allowedZeroAdj[c]) continue;\n\n                // Try recolor to one of neighboring colors that are allowedZeroAdj\n                int dirs[4] = {0,1,2,3};\n                // small shuffle to vary neighbor order\n                for (int i = 3; i > 0; --i) {\n                    int j = rng() % (i + 1);\n                    swap(dirs[i], dirs[j]);\n                }\n\n                bool done = false;\n                for (int t = 0; t < 4 && !done; t++) {\n                    int dir = dirs[t];\n                    int nx = x + DX[dir];\n                    int ny = y + DY[dir];\n                    if (nx < 0 || nx >= n || ny < 0 || ny >= n) continue;\n                    int d = cur_grid[nx][ny];\n                    if (d <= 0) continue;\n                    if (!allowedZeroAdj[d]) continue; // target must be \"outer\" color\n\n                    if (tryRecolorToColor(x, y, d, cur_grid, countColor)) {\n                        changed = true;\n                        done = true;\n                    }\n                }\n            }\n        }\n    }\n\n    // ---- Phase 2: greedy removal to 0 ----\n    {\n        bool improved = true;\n\n        struct Cand {\n            int idx;\n            uint8_t degSame;\n            uint64_t rnd;\n        };\n\n        while (improved) {\n            auto now = chrono::steady_clock::now();\n            double elapsed = chrono::duration<double>(now - start_time).count();\n            if (elapsed > TIME_LIMIT) break;\n\n            improved = false;\n            vector<Cand> cands;\n            cands.reserve(Ncells);\n\n            // Collect frontier cells: non-zero cells that are on boundary or adjacent to 0\n            for (int x = 0; x < n; x++) {\n                for (int y = 0; y < n; y++) {\n                    if (cur_grid[x][y] == 0) continue;\n                    bool boundary = (x == 0 || x == n - 1 || y == 0 || y == n - 1);\n                    bool adjZero = false;\n                    if (!boundary) {\n                        for (int dir = 0; dir < 4; dir++) {\n                            int nx = x + DX[dir];\n                            int ny = y + DY[dir];\n                            if (nx < 0 || nx >= n || ny < 0 || ny >= n) continue;\n                            if (cur_grid[nx][ny] == 0) {\n                                adjZero = true;\n                                break;\n                            }\n                        }\n                    }\n                    if (boundary || adjZero) {\n                        // compute same-color neighbor count (for heuristic ordering)\n                        int c = cur_grid[x][y];\n                        int degSame = 0;\n                        for (int dir = 0; dir < 4; dir++) {\n                            int nx = x + DX[dir];\n                            int ny = y + DY[dir];\n                            if (nx < 0 || nx >= n || ny < 0 || ny >= n) continue;\n                            if (cur_grid[nx][ny] == c) degSame++;\n                        }\n                        Cand cd;\n                        cd.idx = x * n + y;\n                        cd.degSame = (uint8_t)degSame;\n                        cd.rnd = rng();\n                        cands.push_back(cd);\n                    }\n                }\n            }\n\n            if (cands.empty()) break;\n\n            // Sort candidates by increasing same-color degree (peel \"thin\" parts first),\n            // tie-broken randomly.\n            sort(cands.begin(), cands.end(), [](const Cand &a, const Cand &b) {\n                if (a.degSame != b.degSame) return a.degSame < b.degSame;\n                return a.rnd < b.rnd;\n            });\n\n            fill(inQueue.begin(), inQueue.end(), 0);\n            deque<int> q;\n            for (auto &cd : cands) {\n                int idx = cd.idx;\n                if (!inQueue[idx]) {\n                    inQueue[idx] = 1;\n                    q.push_back(idx);\n                }\n            }\n\n            int iter = 0;\n            while (!q.empty()) {\n                if ((iter & 0xFF) == 0) { // time check every 256 steps\n                    auto now2 = chrono::steady_clock::now();\n                    double elapsed2 = chrono::duration<double>(now2 - start_time).count();\n                    if (elapsed2 > TIME_LIMIT) break;\n                }\n                iter++;\n\n                int idx = q.front();\n                q.pop_front();\n                inQueue[idx] = 0;\n                int x = idx / n;\n                int y = idx % n;\n                if (cur_grid[x][y] == 0) continue;\n\n                if (tryChangeToZero(x, y, cur_grid, countColor, rng)) {\n                    improved = true;\n                    // Neighbors may now become removable\n                    for (int dir = 0; dir < 4; dir++) {\n                        int nx = x + DX[dir];\n                        int ny = y + DY[dir];\n                        if (nx < 0 || nx >= n || ny < 0 || ny >= n) continue;\n                        if (cur_grid[nx][ny] == 0) continue;\n                        int idx2 = nx * n + ny;\n                        if (!inQueue[idx2]) {\n                            inQueue[idx2] = 1;\n                            if (rng() & 1) q.push_front(idx2);\n                            else q.push_back(idx2);\n                        }\n                    }\n                }\n            }\n        }\n    }\n\n    // Count zeros and return\n    int zeros = 0;\n    for (int i = 0; i < n; i++)\n        for (int j = 0; j < n; j++)\n            if (cur_grid[i][j] == 0) zeros++;\n\n    out_grid = move(cur_grid);\n    return zeros;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> n >> m;\n    orig_grid.assign(n, vector<int>(n));\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            cin >> orig_grid[i][j];\n        }\n    }\n\n    // Precompute outside adjacency edges for each cell\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            int cnt = 0;\n            if (i == 0) cnt++;\n            if (i == n - 1) cnt++;\n            if (j == 0) cnt++;\n            if (j == n - 1) cnt++;\n            outsideAdjEdges[i][j] = cnt;\n        }\n    }\n\n    // Compute original adjacency matrix\n    computeAdj(orig_grid, adj_orig);\n\n    // Colors that may touch 0\n    for (int c = 0; c <= m; c++) {\n        allowedZeroAdj[c] = adj_orig[0][c];\n    }\n    allowedZeroAdj[0] = true;\n\n    // Multi-start: run the greedy solver multiple times with different seeds, keep best\n    uint64_t base_seed = chrono::steady_clock::now().time_since_epoch().count();\n    auto global_start = chrono::steady_clock::now();\n\n    int bestZeros = -1;\n    vector<vector<int>> bestGrid;\n\n    const double GLOBAL_LIMIT = 1.9;  // safety margin under 2.0s\n    const int MAX_RUNS = 7;\n\n    for (int r = 0; r < MAX_RUNS; r++) {\n        auto now = chrono::steady_clock::now();\n        double globalElapsed = chrono::duration<double>(now - global_start).count();\n        double remaining = GLOBAL_LIMIT - globalElapsed;\n        if (remaining <= 0.12) break; // keep some margin\n\n        double runLimit = min(0.5, remaining - 0.02);\n        if (runLimit <= 0.0) break;\n\n        vector<vector<int>> candidateGrid;\n        uint64_t seed = base_seed + 1234567ULL * (r + 1);\n\n        int z = solve_one(seed, runLimit, candidateGrid);\n        if (z > bestZeros) {\n            bestZeros = z;\n            bestGrid = move(candidateGrid);\n        }\n    }\n\n    if (bestZeros < 0) bestGrid = orig_grid;\n\n    // Output best grid\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            if (j) cout << ' ';\n            cout << bestGrid[i][j];\n        }\n        cout << '\\n';\n    }\n\n    return 0;\n}","ahc025":"#include <bits/stdc++.h>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, D, Q;\n    if (!(cin >> N >> D >> Q)) return 0;\n\n    // Precompute expected order statistics (ascending) of Exp(lambda) for N items\n    const double lambda = 1e-5;\n    vector<double> wAsc(N);\n    double acc = 0.0;\n    for (int k = 1; k <= N; ++k) {\n        acc += 1.0 / (lambda * (N - k + 1));  // increment for kth smallest\n        wAsc[k - 1] = acc;\n    }\n    double wmax = 1e5 * (double) N / (double) D;\n    for (int i = 0; i < N; ++i) {\n        if (wAsc[i] > wmax) wAsc[i] = wmax;\n    }\n\n    // Decide if we can fully sort by comparisons (binary-search insertion sort)\n    int qSortNeeded = 0;\n    if (N >= 2) {\n        for (int i = 1; i < N; ++i) {\n            int len = i;  // current sorted size before inserting i\n            int steps = 0;\n            while ((1 << steps) < len + 1) steps++;  // ceil(log2(len+1))\n            qSortNeeded += steps;\n        }\n    }\n    bool useSort = (Q >= qSortNeeded);\n\n    vector<double> weight(N, 1.0);  // approximate weights to be filled\n\n    if (useSort && N >= 2) {\n        // ---- Mode 1: Full comparison sort using binary-search insertion ----\n        vector<int> sorted;\n        sorted.reserve(N);\n        sorted.push_back(0);  // start with item 0\n\n        int qUsed = 0;\n\n        for (int i = 1; i < N; ++i) {\n            int lo = 0, hi = (int)sorted.size();\n            while (lo < hi) {\n                int mid = (lo + hi) >> 1;\n                int j = sorted[mid];\n\n                // Compare item i vs j: 1 on each side\n                cout << 1 << ' ' << 1 << ' ' << i << ' ' << j << '\\n';\n                cout.flush();\n                string res;\n                if (!(cin >> res)) return 0;\n                ++qUsed;\n\n                // We want descending order in sorted\n                // If i is heavier, it should come before j => search left\n                if (res[0] == '>') {\n                    hi = mid;\n                } else { // '<' or '=' treated as not heavier than j\n                    lo = mid + 1;\n                }\n            }\n            sorted.insert(sorted.begin() + lo, i);\n        }\n\n        // Use remaining queries as dummy (does not affect our already-built order)\n        int remaining = Q - qUsed;\n        for (int t = 0; t < remaining; ++t) {\n            // Any valid pair; N >= 2\n            cout << 1 << ' ' << 1 << ' ' << 0 << ' ' << 1 << '\\n';\n            cout.flush();\n            string res;\n            if (!(cin >> res)) return 0;\n        }\n\n        // Map sorted order to approximate weights using wAsc\n        // sorted[0] (heaviest) -> wAsc[N-1], sorted[1] -> wAsc[N-2], ...\n        for (int pos = 0; pos < N; ++pos) {\n            int item = sorted[pos];\n            double w_est = wAsc[N - 1 - pos];\n            weight[item] = w_est;\n        }\n\n    } else {\n        // ---- Mode 2: Logistic rating with random pair queries (previous best) ----\n        vector<int> A(Q), B(Q);   // items in each query\n        vector<int> Y(Q);         // label: +1 if A[q] heavier, -1 if B[q] heavier, 0 if '='\n        vector<int> matchCount(N, 0);\n        static bool used[100][100];  // N <= 100, symmetric\n        mt19937 rng(712367821);\n\n        vector<int> order(N);\n        iota(order.begin(), order.end(), 0);\n\n        // Query phase\n        for (int q = 0; q < Q; ++q) {\n            // Choose a pair (a, b) that keeps match counts balanced and avoids repeats\n            sort(order.begin(), order.end(), [&](int i, int j) {\n                if (matchCount[i] != matchCount[j]) return matchCount[i] < matchCount[j];\n                return i < j;\n            });\n\n            int a = -1, b = -1;\n            bool found = false;\n            int K = min(N, 10);\n\n            // Try to find a new pair among the K least-used items\n            for (int attempt = 0; attempt < K * 5 && !found; ++attempt) {\n                int ui = rng() % K;\n                int vi = rng() % K;\n                if (ui == vi) continue;\n                int i = order[ui];\n                int j = order[vi];\n                if (i > j) swap(i, j);\n                if (!used[i][j]) {\n                    a = i;\n                    b = j;\n                    found = true;\n                }\n            }\n\n            // Fallback: random pairs avoiding used ones if possible\n            if (!found) {\n                for (int attempt = 0; attempt < N * N && !found; ++attempt) {\n                    int i = rng() % N;\n                    int j = rng() % N;\n                    if (i == j) continue;\n                    if (i > j) swap(i, j);\n                    if (!used[i][j]) {\n                        a = i;\n                        b = j;\n                        found = true;\n                    }\n                }\n            }\n\n            // If all pairs are used (very unlikely), just pick any pair\n            if (!found) {\n                do {\n                    a = rng() % N;\n                    b = rng() % N;\n                } while (a == b);\n                if (a > b) swap(a, b);\n            }\n\n            used[a][b] = used[b][a] = true;\n            matchCount[a]++;\n            matchCount[b]++;\n            A[q] = a;\n            B[q] = b;\n\n            // Output query\n            cout << 1 << ' ' << 1 << ' ' << a << ' ' << b << '\\n';\n            cout.flush();\n\n            // Read result\n            string res;\n            if (!(cin >> res)) return 0;\n            if (res[0] == '>') {\n                Y[q] = +1;  // A heavier than B\n            } else if (res[0] == '<') {\n                Y[q] = -1;  // B heavier than A\n            } else {\n                Y[q] = 0;   // '=' (very rare)\n            }\n        }\n\n        // Bradley\u2013Terry style logistic regression to compute ratings r[i]\n        vector<double> r(N, 0.0);\n        const int ITER = 80;\n        const double base_eta = 0.5;\n\n        bool hasInfo = false;\n        for (int q = 0; q < Q; ++q) if (Y[q] != 0) { hasInfo = true; break; }\n\n        if (hasInfo) {\n            for (int iter = 0; iter < ITER; ++iter) {\n                double eta = base_eta / (1.0 + 0.1 * iter);\n                for (int q = 0; q < Q; ++q) {\n                    int y = Y[q];\n                    if (y == 0) continue;  // skip ties\n                    int a = A[q], b = B[q];\n                    double s = r[a] - r[b];\n                    double z = (double) y * s;\n\n                    if (z > 40.0) continue; // saturation\n\n                    double g;\n                    if (z < -40.0) {\n                        g = (double) y;  // ~ y / (1 + 0) = y\n                    } else {\n                        g = (double) y / (1.0 + std::exp(z));\n                    }\n                    double step = eta * g;\n                    r[a] += step;\n                    r[b] -= step;\n                }\n            }\n        }\n\n        // Map ratings to approximate weights via wAsc\n        vector<int> idx(N);\n        iota(idx.begin(), idx.end(), 0);\n        sort(idx.begin(), idx.end(), [&](int i, int j) {\n            if (r[i] != r[j]) return r[i] > r[j];\n            return i < j;\n        });\n\n        if (hasInfo) {\n            for (int pos = 0; pos < N; ++pos) {\n                int item = idx[pos];\n                double w_est = wAsc[N - 1 - pos];\n                weight[item] = w_est;\n            }\n        } else {\n            for (int i = 0; i < N; ++i) weight[i] = 1.0;\n        }\n    }\n\n    // ---- Partitioning: greedy initialization (largest weight first) ----\n    vector<int> assign(N, -1);\n    vector<double> binSum(D, 0.0);\n\n    vector<int> ord(N);\n    iota(ord.begin(), ord.end(), 0);\n    sort(ord.begin(), ord.end(), [&](int i, int j) {\n        if (weight[i] != weight[j]) return weight[i] > weight[j];\n        return i < j;\n    });\n\n    for (int id : ord) {\n        int bestBin = 0;\n        double bestSum = binSum[0];\n        for (int k = 1; k < D; ++k) {\n            if (binSum[k] < bestSum) {\n                bestSum = binSum[k];\n                bestBin = k;\n            }\n        }\n        assign[id] = bestBin;\n        binSum[bestBin] += weight[id];\n    }\n\n    // ---- Local search (single moves + swaps, first improvement) ----\n    double totalW = 0.0;\n    for (double x : weight) totalW += x;\n    double target = totalW / D;\n    const double EPS = 1e-9;\n    const int MAX_ITERS_LS = 10000;\n\n    int guard = 0;\n    while (true) {\n        bool improved = false;\n\n        // Single-item moves\n        for (int i = 0; i < N && !improved; ++i) {\n            int ai = assign[i];\n            double wi = weight[i];\n            double sa = binSum[ai];\n            double oldA = (sa - target) * (sa - target);\n            for (int k = 0; k < D; ++k) {\n                if (k == ai) continue;\n                double sb = binSum[k];\n                double oldB = (sb - target) * (sb - target);\n                double newSa = sa - wi;\n                double newSb = sb + wi;\n                double newCost = (newSa - target) * (newSa - target)\n                               + (newSb - target) * (newSb - target);\n                double oldCost = oldA + oldB;\n                if (newCost + EPS < oldCost) {\n                    binSum[ai] -= wi;\n                    binSum[k] += wi;\n                    assign[i] = k;\n                    improved = true;\n                    break;\n                }\n            }\n        }\n\n        // Pair swaps\n        if (!improved) {\n            for (int i = 0; i < N && !improved; ++i) {\n                for (int j = i + 1; j < N; ++j) {\n                    int ai = assign[i];\n                    int aj = assign[j];\n                    if (ai == aj) continue;\n                    double wi = weight[i];\n                    double wj = weight[j];\n                    double sa = binSum[ai];\n                    double sb = binSum[aj];\n                    double oldCost = (sa - target) * (sa - target)\n                                   + (sb - target) * (sb - target);\n                    double newSa = sa - wi + wj;\n                    double newSb = sb - wj + wi;\n                    double newCost = (newSa - target) * (newSa - target)\n                                   + (newSb - target) * (newSb - target);\n                    if (newCost + EPS < oldCost) {\n                        binSum[ai] = newSa;\n                        binSum[aj] = newSb;\n                        swap(assign[i], assign[j]);\n                        improved = true;\n                        break;\n                    }\n                }\n            }\n        }\n\n        if (!improved) break;\n        if (++guard > MAX_ITERS_LS) break;\n    }\n\n    // ---- Final output: assignments d_0 ... d_{N-1} ----\n    for (int i = 0; i < N; ++i) {\n        if (i) cout << ' ';\n        cout << assign[i];\n    }\n    cout << '\\n';\n    cout.flush();\n\n    return 0;\n}","ahc026":"#include <bits/stdc++.h>\nusing namespace std;\n\n// Simple xorshift RNG\nstruct XorShift {\n    unsigned long long x;\n    XorShift(unsigned long long seed = 88172645463325252ULL) : x(seed) {}\n    unsigned long long next() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return x;\n    }\n};\n\nstatic const int MAXV = 205;\n\n// Fenwick tree / BIT for counting values in a stack\nstruct BIT {\n    int n;\n    int bit[MAXV];\n\n    void init(int n_) {\n        n = n_;\n        memset(bit, 0, sizeof(bit));\n    }\n\n    void add(int idx, int delta) {\n        for (int i = idx; i <= n; i += i & -i) {\n            bit[i] += delta;\n        }\n    }\n\n    int sumPrefix(int idx) const {\n        if (idx <= 0) return 0;\n        if (idx > n) idx = n;\n        int s = 0;\n        for (int i = idx; i > 0; i -= i & -i) {\n            s += bit[i];\n        }\n        return s;\n    }\n};\n\n// One simulation run with given parameters/weights.\n// bestEnergyLimit: if partial energy reaches/exceeds this, abort the run early.\nstatic pair<long long, vector<pair<int,int>>>\nrunOnce(const vector<vector<int>>& initStacks,\n        const vector<int>& initStackOf,\n        const vector<int>& initPosInStack,\n        const vector<BIT>& initBits,\n        int n, int m,\n        long long bestEnergyLimit,\n        int wPairs, int wSize,\n        int mode,        // 0: pairs only; 1: pairs + smallCount; 2: pairs + nearPairs\n        int wSmall,      // weight for smallCount (mode 1)\n        int smallOffset, // smallCount threshold offset\n        int wNear,       // weight for nearPairs (mode 2)\n        int nearOffset,  // nearPairs threshold offset\n        XorShift& rng)\n{\n    vector<vector<int>> stacks = initStacks;\n    vector<int> stackOf = initStackOf;\n    vector<int> posInStack = initPosInStack;\n    vector<BIT> bits = initBits;\n\n    vector<pair<int,int>> ops;\n    ops.reserve(2 * n + 10);\n    long long energy = 0;\n\n    vector<int> groupVals;\n    groupVals.reserve(n);\n\n    const long long INF = (long long)4e18;\n\n    for (int v = 1; v <= n; v++) {\n        int s = stackOf[v];\n        int idx = posInStack[v];\n\n        // If v is not at the top, move the suffix above it\n        if (idx != (int)stacks[s].size() - 1) {\n            int startIdx = idx + 1;\n            int lenG = (int)stacks[s].size() - startIdx;\n\n            groupVals.clear();\n            groupVals.reserve(lenG);\n            for (int i = startIdx; i < (int)stacks[s].size(); i++) {\n                groupVals.push_back(stacks[s][i]);\n            }\n\n            int dest = -1;\n            long long bestScore = (1LL << 60);\n\n            // Choose destination stack using pair-based heuristics\n            for (int t = 0; t < m; t++) {\n                if (t == s) continue;\n                const BIT &bt = bits[t];\n\n                long long pairs = 0;\n                long long nearPairs = 0;\n\n                int thrNear = (mode == 2 ? min(n, v + nearOffset) : 0);\n\n                for (int x : groupVals) {\n                    int sp = bt.sumPrefix(x - 1);  // #u in T with u < x\n                    pairs += sp;\n\n                    if (mode == 2 && wNear != 0) {\n                        int limit = x - 1;\n                        if (limit > thrNear) limit = thrNear;\n                        if (limit > 0) {\n                            if (limit == x - 1) {\n                                nearPairs += sp;\n                            } else {\n                                nearPairs += bt.sumPrefix(limit);\n                            }\n                        }\n                    }\n                }\n\n                long long score = (long long)wPairs * pairs\n                                  + (long long)wSize * (int)stacks[t].size();\n\n                if (mode == 1 && wSmall != 0) {\n                    int thrSmall = min(n, v + smallOffset);\n                    int smallCount = bt.sumPrefix(thrSmall); // elements <= thrSmall\n                    score += (long long)wSmall * smallCount;\n                }\n\n                if (mode == 2 && wNear != 0) {\n                    score += (long long)wNear * nearPairs;\n                }\n\n                // small random noise for tie-breaking\n                score = score * 16 + (rng.next() & 15);\n\n                if (score < bestScore) {\n                    bestScore = score;\n                    dest = t;\n                }\n            }\n\n            if (dest == -1) {\n                // Fallback (should not happen as m >= 2)\n                dest = (s + 1) % m;\n            }\n\n            int pivot = stacks[s][startIdx];\n            ops.emplace_back(pivot, dest + 1);  // operation 1\n\n            energy += lenG + 1;\n            if (energy >= bestEnergyLimit) {\n                // This run cannot beat the current best\n                return {INF, {}};\n            }\n\n            // Perform move: update stacks, positions, and BITs\n            auto &Ss = stacks[s];\n            auto &Dt = stacks[dest];\n            int oldSize = (int)Ss.size();\n            for (int i = startIdx; i < oldSize; i++) {\n                int box = Ss[i];\n                bits[s].add(box, -1);\n                bits[dest].add(box, 1);\n                stackOf[box] = dest;\n                posInStack[box] = (int)Dt.size();\n                Dt.push_back(box);\n            }\n            Ss.resize(startIdx);\n        }\n\n        // Now v should be on top; remove it\n        s = stackOf[v];\n        auto &S = stacks[s];\n        ops.emplace_back(v, 0);  // operation 2\n        bits[s].add(v, -1);\n        S.pop_back();\n        stackOf[v] = -1;\n        posInStack[v] = -1;\n    }\n\n    return {energy, std::move(ops)};\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int n, m;\n    if (!(cin >> n >> m)) return 0;\n\n    vector<vector<int>> initStacks(m);\n    vector<int> initStackOf(n + 1);\n    vector<int> initPosInStack(n + 1);\n    vector<BIT> initBits(m);\n\n    int perStack = n / m;\n    for (int i = 0; i < m; i++) {\n        initStacks[i].resize(perStack);\n        initBits[i].init(n);\n        for (int j = 0; j < perStack; j++) {\n            int x;\n            cin >> x;\n            initStacks[i][j] = x;\n            initStackOf[x] = i;\n            initPosInStack[x] = j;\n            initBits[i].add(x, 1);\n        }\n    }\n\n    XorShift rng((unsigned long long)chrono::steady_clock::now()\n                     .time_since_epoch().count());\n\n    auto start = chrono::steady_clock::now();\n    auto endTime = start + chrono::milliseconds(1900);  // time guard\n\n    const long long INF = (long long)4e18;\n    long long bestEnergy = INF;\n    vector<pair<int,int>> bestOps;\n\n    int runId = 0;\n    while (true) {\n        int wPairs, wSize;\n        int mode;\n        int wSmall = 0, smallOffset = 0;\n        int wNear = 0, nearOffset = 0;\n\n        if (runId == 0) {\n            // Baseline parameters: simple pairs + size (best known)\n            mode = 0;\n            wPairs = 3;\n            wSize  = 1;\n        } else if (runId == 1) {\n            // Fixed \"small penalty\" variant\n            mode = 1;\n            wPairs = 3;\n            wSize  = 1;\n            wSmall = 2;\n            smallOffset = 20;\n        } else if (runId == 2) {\n            // Fixed \"nearPairs\" variant\n            mode = 2;\n            wPairs = 2;\n            wSize  = 1;\n            wNear  = 3;\n            nearOffset = 20;\n        } else {\n            // Randomized parameters and scoring mode\n            int rmode = (int)(rng.next() % 3); // 0, 1 or 2\n            mode = rmode;\n            if (mode == 0) {\n                // Simple model (pairs + size)\n                wPairs = 1 + (int)(rng.next() % 6);   // 1..6\n                wSize  = (int)(rng.next() % 7) - 2;   // -2..4\n            } else if (mode == 1) {\n                // With small-count penalty\n                wPairs = 2 + (int)(rng.next() % 6);   // 2..7\n                wSize  = (int)(rng.next() % 5);       // 0..4\n                wSmall = 1 + (int)(rng.next() % 5);   // 1..5\n                smallOffset = 10 + (int)(rng.next() % 31); // 10..40\n            } else {\n                // With nearPairs penalty\n                wPairs = 1 + (int)(rng.next() % 5);   // 1..5\n                wSize  = (int)(rng.next() % 5);       // 0..4\n                wNear  = 1 + (int)(rng.next() % 6);   // 1..6\n                nearOffset = 10 + (int)(rng.next() % 31); // 10..40\n            }\n        }\n\n        auto res = runOnce(initStacks, initStackOf, initPosInStack,\n                           initBits, n, m,\n                           bestEnergy,\n                           wPairs, wSize,\n                           mode, wSmall, smallOffset,\n                           wNear, nearOffset,\n                           rng);\n        if (res.first < bestEnergy) {\n            bestEnergy = res.first;\n            bestOps = std::move(res.second);\n        }\n\n        runId++;\n        if (chrono::steady_clock::now() > endTime) break;\n    }\n\n    // Output best sequence of operations\n    for (auto &op : bestOps) {\n        cout << op.first << ' ' << op.second << '\\n';\n    }\n\n    return 0;\n}","ahc027":"#include <bits/stdc++.h>\nusing namespace std;\n\n// ---------- RNG (xorshift) ----------\nstatic uint64_t rng_state = 123456789ULL;\n\nstatic inline uint64_t xorshift64() {\n    uint64_t x = rng_state;\n    x ^= x << 7;\n    x ^= x >> 9;\n    rng_state = x;\n    return x;\n}\n\nstatic inline double rand_double() {\n    // [0,1)\n    return (xorshift64() & ((1ULL << 53) - 1)) * (1.0 / (1ULL << 53));\n}\n\n// ---------- Global structures ----------\nstruct Edge {\n    int to;\n    char dir; // 'U', 'D', 'L', 'R'\n};\n\nint N;\nint V; // N*N\nvector<string> hgrid; // (N-1) x N, between (i,j) and (i+1,j)\nvector<string> vgrid; // N x (N-1), between (i,j) and (i,j+1)\nvector<int> dflat; // N*N\nvector<vector<Edge>> adj;\n\nvector<int> dist_bfs;\nvector<int> parent_bfs;\nvector<char> pdir_bfs;        // direction parent -> node in BFS tree\nvector<vector<int>> children; // children in BFS tree\n\nstring coverMoves;            // covering tour (DFS over BFS tree)\nconstexpr int L_MAX = 100000;\n\n// ---------- Utility ----------\ninline char revdir(char c) {\n    if (c == 'U') return 'D';\n    if (c == 'D') return 'U';\n    if (c == 'L') return 'R';\n    return 'L'; // 'R'\n}\n\n// ---------- DFS on BFS tree to build covering tour ----------\nvoid dfs_cover(int u) {\n    for (int v : children[u]) {\n        char dir = pdir_bfs[v]; // parent -> child\n        coverMoves.push_back(dir);\n        dfs_cover(v);\n        coverMoves.push_back(revdir(dir)); // back to parent\n    }\n}\n\n// ---------- Append shortest path root -> v (using BFS tree) ----------\nvoid append_path_root_to(int v, string &route) {\n    const int root = 0;\n    if (v == root) return;\n    vector<char> tmp;\n    int cur = v;\n    while (cur != root) {\n        tmp.push_back(pdir_bfs[cur]); // parent -> cur\n        cur = parent_bfs[cur];\n    }\n    for (int i = (int)tmp.size() - 1; i >= 0; --i) {\n        route.push_back(tmp[i]);\n    }\n}\n\n// ---------- Append shortest path cur -> root (using BFS tree) ----------\nvoid append_path_to_root(int cur, string &route) {\n    const int root = 0;\n    while (cur != root) {\n        char c = revdir(pdir_bfs[cur]); // cur -> parent\n        route.push_back(c);\n        cur = parent_bfs[cur];\n    }\n}\n\n// ---------- Evaluate a route: exact average dirtiness ----------\nlong double evaluate_route(const string &route) {\n    int L = (int)route.size();\n    if (L == 0) return 0.0L;\n\n    static vector<int> firstVisit, lastVisit;\n    static vector<unsigned long long> sumLen2;\n\n    if ((int)firstVisit.size() != V) {\n        firstVisit.assign(V, 0);\n        lastVisit.assign(V, 0);\n        sumLen2.assign(V, 0ULL);\n    } else {\n        fill(firstVisit.begin(), firstVisit.end(), 0);\n        fill(lastVisit.begin(), lastVisit.end(), 0);\n        fill(sumLen2.begin(), sumLen2.end(), 0ULL);\n    }\n\n    int ci = 0, cj = 0; // start at (0,0)\n    for (int t = 1; t <= L; ++t) {\n        char mv = route[t - 1];\n        if      (mv == 'U') --ci;\n        else if (mv == 'D') ++ci;\n        else if (mv == 'L') --cj;\n        else                ++cj; // 'R'\n        int id = ci * N + cj;\n\n        if (lastVisit[id] == 0) {\n            firstVisit[id] = t;\n            lastVisit[id] = t;\n        } else {\n            int len = t - lastVisit[id];\n            unsigned long long l = (unsigned long long)len;\n            sumLen2[id] += l * (l - 1ULL);\n            lastVisit[id] = t;\n        }\n    }\n\n    unsigned long long totalScore = 0ULL;\n    for (int id = 0; id < V; ++id) {\n        if (lastVisit[id] == 0) continue; // should not happen (covering visits all)\n        int len = (firstVisit[id] + L) - lastVisit[id];\n        unsigned long long l = (unsigned long long)len;\n        sumLen2[id] += l * (l - 1ULL);\n\n        unsigned long long contrib = sumLen2[id] * (unsigned long long)dflat[id];\n        contrib >>= 1; // divide by 2 (len*(len-1) is always even)\n        totalScore += contrib;\n    }\n\n    return (long double)totalScore / (long double)L;\n}\n\n// ---------- Build one candidate route under a given weight vector ----------\nstring build_candidate_route(\n    int startCell,\n    const vector<double> &weight,\n    int Dmax\n) {\n    const int root = 0;\n\n    string route;\n    route.reserve(L_MAX + 10);\n\n    // Covering tour that starts and ends at root\n    route += coverMoves;\n\n    // Move root -> startCell if needed\n    if (startCell != root) {\n        append_path_root_to(startCell, route);\n    }\n\n    int prefixLen = (int)route.size();\n    int S = L_MAX - prefixLen - Dmax; // random-walk length upper bound\n    if (S < 0) S = 0;\n\n    int pos = startCell;\n\n    // Biased random walk\n    for (int step = 0; step < S; ++step) {\n        auto &nb = adj[pos];\n        int deg = (int)nb.size();\n        if (deg == 0) break; // should not happen (connected graph)\n\n        double sumw = 0.0;\n        for (const auto &e : nb) {\n            sumw += weight[e.to];\n        }\n        double r = rand_double() * sumw;\n        double acc = 0.0;\n        int chosen = deg - 1;\n        for (int k = 0; k < deg; ++k) {\n            acc += weight[nb[k].to];\n            if (acc >= r) { chosen = k; break; }\n        }\n        const auto &e = nb[chosen];\n        route.push_back(e.dir);\n        pos = e.to;\n    }\n\n    // Return to root\n    append_path_to_root(pos, route);\n\n    if ((int)route.size() > L_MAX) {\n        // Safety (shouldn't happen with S computed as above)\n        route.resize(L_MAX);\n    }\n\n    return route;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N;\n    hgrid.resize(N - 1);\n    for (int i = 0; i < N - 1; ++i) {\n        cin >> hgrid[i];\n    }\n    vgrid.resize(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> vgrid[i];\n    }\n\n    V = N * N;\n    dflat.assign(V, 0);\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int x;\n            cin >> x;\n            dflat[i * N + j] = x;\n        }\n    }\n\n    // Build adjacency list\n    adj.assign(V, {});\n    auto in_bounds = [&](int i, int j) {\n        return (0 <= i && i < N && 0 <= j && j < N);\n    };\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int id = i * N + j;\n            // Up\n            if (i > 0 && hgrid[i - 1][j] == '0') {\n                int to = (i - 1) * N + j;\n                adj[id].push_back({to, 'U'});\n            }\n            // Down\n            if (i < N - 1 && hgrid[i][j] == '0') {\n                int to = (i + 1) * N + j;\n                adj[id].push_back({to, 'D'});\n            }\n            // Left\n            if (j > 0 && vgrid[i][j - 1] == '0') {\n                int to = i * N + (j - 1);\n                adj[id].push_back({to, 'L'});\n            }\n            // Right\n            if (j < N - 1 && vgrid[i][j] == '0') {\n                int to = i * N + (j + 1);\n                adj[id].push_back({to, 'R'});\n            }\n        }\n    }\n\n    // Sort adjacency: neighbors with larger d first\n    for (int u = 0; u < V; ++u) {\n        sort(adj[u].begin(), adj[u].end(),\n            [&](const Edge &a, const Edge &b) {\n                return dflat[a.to] > dflat[b.to];\n            });\n    }\n\n    // BFS from root to build BFS tree and distances\n    const int root = 0;\n    dist_bfs.assign(V, -1);\n    parent_bfs.assign(V, -1);\n    pdir_bfs.assign(V, 0);\n    queue<int> q;\n    dist_bfs[root] = 0;\n    parent_bfs[root] = root;\n    q.push(root);\n    while (!q.empty()) {\n        int u = q.front(); q.pop();\n        for (const auto &e : adj[u]) {\n            int v = e.to;\n            if (dist_bfs[v] == -1) {\n                dist_bfs[v] = dist_bfs[u] + 1;\n                parent_bfs[v] = u;\n                pdir_bfs[v] = e.dir; // parent -> v\n                q.push(v);\n            }\n        }\n    }\n\n    int Dmax = 0;\n    for (int i = 0; i < V; ++i) {\n        if (dist_bfs[i] > Dmax) Dmax = dist_bfs[i];\n    }\n\n    // Build BFS tree children list\n    children.assign(V, {});\n    for (int v = 0; v < V; ++v) {\n        if (v == root) continue;\n        int p = parent_bfs[v];\n        if (p >= 0 && p < V) {\n            children[p].push_back(v);\n        }\n    }\n    // Sort children by descending d for a slightly better covering\n    for (int u = 0; u < V; ++u) {\n        sort(children[u].begin(), children[u].end(),\n             [&](int a, int b) {\n                 return dflat[a] > dflat[b];\n             });\n    }\n\n    // Build covering tour (edge-doubling DFS)\n    coverMoves.clear();\n    dfs_cover(root);\n\n    // Build anchor list: root + top-K high-d cells\n    int K = 12;\n    vector<int> idx(V);\n    iota(idx.begin(), idx.end(), 0);\n    sort(idx.begin(), idx.end(),\n         [&](int a, int b) {\n             return dflat[a] > dflat[b];\n         });\n    vector<int> anchors;\n    anchors.reserve(K + 1);\n    anchors.push_back(root);\n    for (int id : idx) {\n        if ((int)anchors.size() >= K + 1) break;\n        if (id == root) continue;\n        anchors.push_back(id);\n    }\n\n    // Exponent set for weights\n    vector<double> exps = {0.25, 0.5, 0.75, 1.0};\n    int E = (int)exps.size();\n\n    // Precompute weights for each exponent\n    vector<vector<double>> weights(E, vector<double>(V));\n    for (int ei = 0; ei < E; ++ei) {\n        double p = exps[ei];\n        for (int i = 0; i < V; ++i) {\n            weights[ei][i] = pow((double)dflat[i], p);\n        }\n    }\n\n    string bestRoute;\n    long double bestScore = numeric_limits<long double>::infinity();\n\n    // Baseline: covering tour only\n    {\n        string baseRoute = coverMoves;\n        long double sc = evaluate_route(baseRoute);\n        if (sc < bestScore) {\n            bestScore = sc;\n            bestRoute = std::move(baseRoute);\n        }\n    }\n\n    // Candidates: for each anchor and each exponent\n    for (int anchor : anchors) {\n        for (int ei = 0; ei < E; ++ei) {\n            string route = build_candidate_route(anchor, weights[ei], Dmax);\n            long double sc = evaluate_route(route);\n            if (sc < bestScore) {\n                bestScore = sc;\n                bestRoute = std::move(route);\n            }\n        }\n    }\n\n    cout << bestRoute << '\\n';\n    return 0;\n}","ahc028":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int INF = 1e9;\n\n// ---------------- Overlap and superstring ----------------\n\n// Compute overlap length: max k in [0..4] such that\n// suffix of a of length k == prefix of b of length k.\nint compute_overlap(const string &a, const string &b) {\n    const int L = 5;\n    for (int k = L - 1; k >= 1; --k) { // k = 4..1\n        bool ok = true;\n        for (int i = 0; i < k; ++i) {\n            if (a[L - k + i] != b[i]) {\n                ok = false;\n                break;\n            }\n        }\n        if (ok) return k;\n    }\n    return 0;\n}\n\n// Build superstring S from permutation path\nstring build_superstring(const vector<int> &path,\n                         const vector<string> &words,\n                         const vector<vector<int>> &ov) {\n    int M = (int)path.size();\n    string S = words[path[0]];\n    for (int i = 1; i < M; ++i) {\n        int prev = path[i - 1];\n        int cur  = path[i];\n        int k = ov[prev][cur];\n        S.append(words[cur].begin() + k, words[cur].end());\n    }\n    return S;\n}\n\n// ---------------- Keyboard DP ----------------\n\n// DP cost computation without parent reconstruction\nint compute_cost_no_parent(\n    const string &S,\n    const vector<vector<int>> &dist,\n    const vector<vector<int>> &cellsByLetter,\n    int startIdx\n) {\n    int L = (int)S.size();\n    if (L == 0) return 0;\n    int G = (int)dist.size();\n\n    vector<int> dpPrev(G, INF), dpCur(G, INF);\n    vector<int> prevCells, curCells;\n    prevCells.reserve(G);\n    curCells.reserve(G);\n\n    int c0 = S[0] - 'A';\n    const auto &cand0 = cellsByLetter[c0];\n    prevCells.clear();\n    for (int cell : cand0) {\n        dpPrev[cell] = dist[startIdx][cell];\n        prevCells.push_back(cell);\n    }\n\n    for (int pos = 1; pos < L; ++pos) {\n        int c = S[pos] - 'A';\n        const auto &cand = cellsByLetter[c];\n        curCells.clear();\n\n        for (int b : cand) {\n            int best = INF;\n            for (int a : prevCells) {\n                int val = dpPrev[a] + dist[a][b];\n                if (val < best) best = val;\n            }\n            dpCur[b] = best;\n            curCells.push_back(b);\n        }\n\n        dpPrev.swap(dpCur);\n        prevCells.swap(curCells);\n    }\n\n    int bestCost = INF;\n    for (int a : prevCells) {\n        if (dpPrev[a] < bestCost) bestCost = dpPrev[a];\n    }\n    return bestCost;\n}\n\n// DP with parent reconstruction: returns sequence of cell indices\nvector<int> compute_path_with_parent(\n    const string &S,\n    const vector<vector<int>> &dist,\n    const vector<vector<int>> &cellsByLetter,\n    int startIdx\n) {\n    int L = (int)S.size();\n    int G = (int)dist.size();\n    vector<int> result(L);\n    if (L == 0) return result;\n\n    vector<vector<int>> parent(L, vector<int>(G, -1));\n    vector<int> dpPrev(G, INF), dpCur(G, INF);\n    vector<int> prevCells, curCells;\n    prevCells.reserve(G);\n    curCells.reserve(G);\n\n    int c0 = S[0] - 'A';\n    const auto &cand0 = cellsByLetter[c0];\n    prevCells.clear();\n    for (int cell : cand0) {\n        dpPrev[cell] = dist[startIdx][cell];\n        parent[0][cell] = startIdx;\n        prevCells.push_back(cell);\n    }\n\n    for (int pos = 1; pos < L; ++pos) {\n        int c = S[pos] - 'A';\n        const auto &cand = cellsByLetter[c];\n        curCells.clear();\n\n        for (int b : cand) {\n            int best = INF;\n            int bestPrevCell = -1;\n            for (int a : prevCells) {\n                int val = dpPrev[a] + dist[a][b];\n                if (val < best) {\n                    best = val;\n                    bestPrevCell = a;\n                }\n            }\n            dpCur[b] = best;\n            parent[pos][b] = bestPrevCell;\n            curCells.push_back(b);\n        }\n\n        dpPrev.swap(dpCur);\n        prevCells.swap(curCells);\n    }\n\n    int bestCost = INF;\n    int bestLastCell = -1;\n    for (int a : prevCells) {\n        if (dpPrev[a] < bestCost) {\n            bestCost = dpPrev[a];\n            bestLastCell = a;\n        }\n    }\n\n    int cell = bestLastCell;\n    for (int pos = L - 1; pos >= 0; --pos) {\n        result[pos] = cell;\n        cell = parent[pos][cell]; // for pos=0 this becomes startIdx; ignored later\n    }\n\n    return result;\n}\n\n// ---------------- Permutation local search (overlap-based) ----------------\n\n// Adjacent-swap local search maximizing total overlap sum\nint local_search_adjacent_swaps(vector<int> &path,\n                                const vector<vector<int>> &ov) {\n    int M = (int)path.size();\n    if (M <= 1) return 0;\n\n    vector<int> edgeOv(max(0, M - 1));\n    int totalOv = 0;\n    for (int i = 0; i + 1 < M; ++i) {\n        int val = ov[path[i]][path[i + 1]];\n        edgeOv[i] = val;\n        totalOv += val;\n    }\n\n    if (M <= 2) {\n        return totalOv;\n    }\n\n    bool improved = true;\n    while (improved) {\n        improved = false;\n        for (int i = 0; i < M - 1; ++i) {\n            int delta = 0;\n            if (i == 0) {\n                int A = path[0];\n                int B = path[1];\n                int C = path[2];\n\n                int old1 = ov[A][B];\n                int old2 = ov[B][C];\n\n                int new1 = ov[B][A];\n                int new2 = ov[A][C];\n\n                delta = (new1 + new2) - (old1 + old2);\n                if (delta > 0) {\n                    swap(path[0], path[1]);\n                    edgeOv[0] = new1;\n                    edgeOv[1] = new2;\n                    totalOv += delta;\n                    improved = true;\n                }\n            } else if (i == M - 2) {\n                int D = path[M - 3];\n                int A = path[M - 2];\n                int B = path[M - 1];\n\n                int old1 = ov[D][A];\n                int old2 = ov[A][B];\n\n                int new1 = ov[D][B];\n                int new2 = ov[B][A];\n\n                delta = (new1 + new2) - (old1 + old2);\n                if (delta > 0) {\n                    swap(path[M - 2], path[M - 1]);\n                    edgeOv[M - 3] = new1;\n                    edgeOv[M - 2] = new2;\n                    totalOv += delta;\n                    improved = true;\n                }\n            } else {\n                int D = path[i - 1];\n                int A = path[i];\n                int B = path[i + 1];\n                int C = path[i + 2];\n\n                int old1 = ov[D][A];\n                int old2 = ov[A][B];\n                int old3 = ov[B][C];\n\n                int new1 = ov[D][B];\n                int new2 = ov[B][A];\n                int new3 = ov[A][C];\n\n                delta = (new1 + new2 + new3) - (old1 + old2 + old3);\n                if (delta > 0) {\n                    swap(path[i], path[i + 1]);\n                    edgeOv[i - 1] = new1;\n                    edgeOv[i] = new2;\n                    edgeOv[i + 1] = new3;\n                    totalOv += delta;\n                    improved = true;\n                }\n            }\n        }\n    }\n    return totalOv;\n}\n\n// Relocation local search: move one word Xi to follow Aj, only if overlap sum improves.\n// After each accepted move, recompute DP cost and update global best string if improved.\nvoid relocate_local_search_T(\n    vector<int> path,                 // work on a copy\n    const vector<vector<int>> &ov,\n    const vector<string> &words,\n    const vector<vector<int>> &dist,\n    const vector<vector<int>> &cellsByLetter,\n    int startIdx,\n    int &globalBestT,\n    string &globalBestS\n) {\n    int M = (int)path.size();\n    if (M <= 2) return;\n\n    int totalOv = 0;\n    for (int i = 0; i + 1 < M; ++i) {\n        totalOv += ov[path[i]][path[i + 1]];\n    }\n\n    bool improved = true;\n    while (improved) {\n        improved = false;\n        for (int i = 0; i < M; ++i) {\n            int Xi = path[i];\n            int Li = (i > 0 ? path[i - 1] : -1);\n            int Ri = (i + 1 < M ? path[i + 1] : -1);\n\n            int wLiX  = (i > 0       ? ov[Li][Xi] : 0);\n            int wXRi  = (i + 1 < M   ? ov[Xi][Ri] : 0);\n            int wLiRi = (i > 0 && i + 1 < M ? ov[Li][Ri] : 0);\n\n            for (int j = 0; j < M; ++j) {\n                if (j == i || j == i - 1) continue;\n                int Aj = path[j];\n                int Bj = (j + 1 < M ? path[j + 1] : -1);\n\n                int wAjBj = (j + 1 < M ? ov[Aj][Bj] : 0);\n                int wAjX  = ov[Aj][Xi];\n                int wXBj  = (j + 1 < M ? ov[Xi][Bj] : 0);\n\n                int delta = 0;\n                // remove Xi from its position\n                if (i > 0)        delta -= wLiX;\n                if (i + 1 < M)    delta -= wXRi;\n                if (i > 0 && i + 1 < M) delta += wLiRi;\n                // break insertion edge Aj->Bj\n                if (j + 1 < M)    delta -= wAjBj;\n                // add new edges Aj->Xi and Xi->Bj\n                delta += wAjX;\n                if (j + 1 < M)    delta += wXBj;\n\n                if (delta > 0) {\n                    totalOv += delta;\n\n                    int from = i;\n                    int to = j + 1;\n                    if (from < to) {\n                        path.erase(path.begin() + from);\n                        --to;\n                        path.insert(path.begin() + to, Xi);\n                    } else {\n                        path.erase(path.begin() + from);\n                        path.insert(path.begin() + to, Xi);\n                    }\n\n                    string S = build_superstring(path, words, ov);\n                    int T = compute_cost_no_parent(S, dist, cellsByLetter, startIdx);\n                    if (T < globalBestT) {\n                        globalBestT = T;\n                        globalBestS = move(S);\n                    }\n\n                    improved = true;\n                    goto NEXT_ITER;\n                }\n            }\n        }\n        NEXT_ITER:;\n    }\n}\n\n// ---------------- Main ----------------\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M;\n    if (!(cin >> N >> M)) return 0;\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> words(M);\n    for (int i = 0; i < M; ++i) cin >> words[i];\n\n    int G = N * N;\n    int startIdx = si * N + sj;\n\n    // Precompute cell coordinates\n    vector<pair<int,int>> coord(G);\n    for (int idx = 0; idx < G; ++idx) {\n        coord[idx] = {idx / N, idx % N};\n    }\n\n    // Cells by letter\n    vector<vector<int>> cellsByLetter(26);\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            char c = grid[i][j];\n            int idx = i * N + j;\n            cellsByLetter[c - 'A'].push_back(idx);\n        }\n    }\n\n    // Distance matrix between cells\n    vector<vector<int>> dist(G, vector<int>(G));\n    for (int a = 0; a < G; ++a) {\n        int ax = coord[a].first;\n        int ay = coord[a].second;\n        for (int b = 0; b < G; ++b) {\n            int bx = coord[b].first;\n            int by = coord[b].second;\n            dist[a][b] = abs(ax - bx) + abs(ay - by) + 1;\n        }\n    }\n\n    // Overlap matrix between words\n    vector<vector<int>> ov(M, vector<int>(M, 0));\n    for (int i = 0; i < M; ++i) {\n        for (int j = 0; j < M; ++j) {\n            if (i == j) continue;\n            ov[i][j] = compute_overlap(words[i], words[j]);\n        }\n    }\n\n    mt19937 rng(712367821);\n\n    const int numRestarts = 700;  // increased for more exploration\n\n    int globalBestT = INF;\n    string globalBestS;\n\n    vector<int> bestPathByT;\n    int bestT = INF;\n\n    vector<int> bestPathByOv;\n    int bestOv = -1;\n\n    vector<int> path(M);\n    vector<char> used(M);\n\n    // Multiple restarts: greedy by overlap + adjacent swap LS\n    for (int r = 0; r < numRestarts; ++r) {\n        fill(used.begin(), used.end(), 0);\n\n        int startNode = rng() % M;\n        path[0] = startNode;\n        used[startNode] = 1;\n\n        // Greedy construction by overlap\n        for (int pos = 1; pos < M; ++pos) {\n            int u = path[pos - 1];\n            int bestOverlap = -1;\n            vector<int> cands;\n            cands.reserve(M);\n            for (int v = 0; v < M; ++v) {\n                if (used[v]) continue;\n                int o = ov[u][v];\n                if (o > bestOverlap) {\n                    bestOverlap = o;\n                    cands.clear();\n                    cands.push_back(v);\n                } else if (o == bestOverlap) {\n                    cands.push_back(v);\n                }\n            }\n            int v = cands[rng() % cands.size()];\n            path[pos] = v;\n            used[v] = 1;\n        }\n\n        // Overlap-based local search by adjacent swaps\n        int TOTov = local_search_adjacent_swaps(path, ov);\n\n        if (TOTov > bestOv) {\n            bestOv = TOTov;\n            bestPathByOv = path;\n        }\n\n        // Build superstring and evaluate true DP cost\n        string S = build_superstring(path, words, ov);\n        int T = compute_cost_no_parent(S, dist, cellsByLetter, startIdx);\n\n        if (T < bestT) {\n            bestT = T;\n            bestPathByT = path;\n        }\n        if (T < globalBestT) {\n            globalBestT = T;\n            globalBestS = S;\n        }\n    }\n\n    // Overlap-based relocation local search on best-by-overlap path\n    if (!bestPathByOv.empty()) {\n        relocate_local_search_T(bestPathByOv, ov, words, dist, cellsByLetter,\n                                startIdx, globalBestT, globalBestS);\n    }\n    // And on best-by-cost path (if different)\n    if (!bestPathByT.empty() && bestPathByT != bestPathByOv) {\n        relocate_local_search_T(bestPathByT, ov, words, dist, cellsByLetter,\n                                startIdx, globalBestT, globalBestS);\n    }\n\n    // Reconstruct final finger movement for the best string\n    vector<int> bestCells = compute_path_with_parent(globalBestS, dist, cellsByLetter, startIdx);\n    int L = (int)bestCells.size();\n    for (int pos = 0; pos < L; ++pos) {\n        int idxCell = bestCells[pos];\n        int x = idxCell / N;\n        int y = idxCell % N;\n        cout << x << ' ' << y << '\\n';\n    }\n\n    return 0;\n}","ahc030":"#include <bits/stdc++.h>\nusing namespace std;\n\n// Representation of each field's shape\nstruct Field {\n    int H, W;                             // bounding box size\n    vector<pair<int,int>> offsets;        // shape cells relative to (0,0)\n    vector<char> occ;                     // occupancy grid H x W: 1 if cell in shape\n};\n\n// A single candidate placement of a field\nstruct Placement {\n    int di, dj;                           // translation offset on the N x N grid\n    bool alive;                           // still possible?\n    vector<int> cells;                    // global cell indices covered by this placement\n};\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)) {\n        return 0;\n    }\n    int N2 = N * N;\n\n    // Read field shapes and compute totalOil = sum of all field areas\n    vector<Field> fields(M);\n    int totalOil = 0;\n    for (int k = 0; k < M; ++k) {\n        int d;\n        cin >> d;\n        totalOil += d;\n        vector<pair<int,int>> cells(d);\n        int max_i = 0, max_j = 0;\n        for (int t = 0; t < d; ++t) {\n            int x, y;\n            cin >> x >> y;\n            cells[t] = {x, y};\n            if (x > max_i) max_i = x;\n            if (y > max_j) max_j = y;\n        }\n        Field &f = fields[k];\n        f.H = max_i + 1;\n        f.W = max_j + 1;\n        f.offsets = move(cells);\n        f.occ.assign(f.H * f.W, 0);\n        for (auto &p : f.offsets) {\n            int x = p.first, y = p.second;\n            f.occ[x * f.W + y] = 1;\n        }\n    }\n\n    // Build all candidate placements and cover counts\n    vector<vector<Placement>> placements(M);\n    vector<vector<int>> coverCount(M, vector<int>(N2, 0)); // coverCount[k][cell]\n    vector<int> totalCandidates(M, 0);\n\n    for (int k = 0; k < M; ++k) {\n        Field &f = fields[k];\n        for (int di = 0; di <= N - f.H; ++di) {\n            for (int dj = 0; dj <= N - f.W; ++dj) {\n                Placement p;\n                p.di = di;\n                p.dj = dj;\n                p.alive = true;\n                p.cells.reserve(f.offsets.size());\n                for (auto &off : f.offsets) {\n                    int i = di + off.first;\n                    int j = dj + off.second;\n                    int cid = i * N + j;\n                    p.cells.push_back(cid);\n                    coverCount[k][cid]++;\n                }\n                placements[k].push_back(move(p));\n                totalCandidates[k]++;\n            }\n        }\n    }\n\n    // observed[c]: exact v(c) if drilled; -1 otherwise\n    vector<int> observed(N2, -1);\n    // known[c]: value of v(c) if we have turned it into a hard constraint (from drilling or inference); -1 otherwise\n    vector<int> known(N2, -1);\n\n    // Candidate-based min/max possible v for each cell and elimination potential\n    vector<int> candMin(N2), candMax(N2), elimSum(N2);\n\n    // Inferred min/max after also applying global sum constraint and observed\n    vector<int> infoMin(N2), infoMax(N2);\n\n    // Recompute candMin, candMax, elimSum from current candidate sets\n    auto recomputeCandidateMinMax = [&]() {\n        for (int c = 0; c < N2; ++c) {\n            int mn = 0, mx = 0, el = 0;\n            for (int k = 0; k < M; ++k) {\n                int tc = totalCandidates[k];\n                if (tc <= 0) continue;      // safety\n                int cc = coverCount[k][c];\n                if (cc == tc) mn += 1;      // all placements of k cover c\n                if (cc > 0)    mx += 1;      // some placement covers c\n                if (cc > 0 && cc < tc) {\n                    // Potential elimination for this field at this cell\n                    el += min(cc, tc - cc);\n                }\n            }\n            candMin[c] = mn;\n            candMax[c] = mx;\n            elimSum[c] = el;\n        }\n    };\n\n    // Compute infoMin/infoMax by combining candidate-based bounds + observed + global sum.\n    auto recomputeInfoBounds = [&]() {\n        // Start from candidate bounds\n        for (int c = 0; c < N2; ++c) {\n            infoMin[c] = candMin[c];\n            infoMax[c] = candMax[c];\n        }\n        // Apply observed (exact drilled values override everything)\n        for (int c = 0; c < N2; ++c) {\n            if (observed[c] != -1) {\n                infoMin[c] = infoMax[c] = observed[c];\n            }\n        }\n\n        // Iterative refinement using global sum: sum v(c) = totalOil\n        const int MAX_ITER = 10;\n        for (int iter = 0; iter < MAX_ITER; ++iter) {\n            long long Smin = 0, Smax = 0;\n            for (int c = 0; c < N2; ++c) {\n                Smin += infoMin[c];\n                Smax += infoMax[c];\n            }\n            if (Smin > totalOil || totalOil > Smax) {\n                // Inconsistent bounds (should not happen). Stop refinement to stay safe.\n                break;\n            }\n            bool changed = false;\n            for (int c = 0; c < N2; ++c) {\n                int L = infoMin[c];\n                int U = infoMax[c];\n                long long restMin = Smin - L; // sum of mins of all other cells\n                long long restMax = Smax - U; // sum of maxs of all other cells\n                int newL = max(L, totalOil - (int)restMax);\n                int newU = min(U, totalOil - (int)restMin);\n                if (newL < 0) newL = 0;\n                if (newU < newL) newU = newL;\n                if (newL != L || newU != U) {\n                    infoMin[c] = newL;\n                    infoMax[c] = newU;\n                    changed = true;\n                }\n            }\n            if (!changed) break;\n        }\n    };\n\n    // Apply hard constraint v(c) = val to prune candidate placements\n    auto applyConstraint = [&](int c, int val) {\n        for (int k = 0; k < M; ++k) {\n            int tc_before = totalCandidates[k];\n            if (tc_before <= 0) continue; // safety\n\n            int cc = coverCount[k][c];\n            bool minCk = (cc == tc_before); // all placements of k cover c?\n            bool maxCk = (cc > 0);          // some placement covers c?\n\n            int min_without_k = candMin[c] - (minCk ? 1 : 0);\n            int max_without_k = candMax[c] - (maxCk ? 1 : 0);\n\n            Field &f = fields[k];\n\n            for (Placement &p : placements[k]) {\n                if (!p.alive) continue;\n\n                // Does this placement cover cell c?\n                int delta = 0;\n                int di = p.di, dj = p.dj;\n                int ci = c / N;\n                int cj = c % N;\n                int li = ci - di;\n                int lj = cj - dj;\n                if (0 <= li && li < f.H && 0 <= lj && lj < f.W) {\n                    if (f.occ[li * f.W + lj]) delta = 1;\n                }\n\n                int min_possible = delta + min_without_k;\n                int max_possible = delta + max_without_k;\n\n                if (val < min_possible || val > max_possible) {\n                    // This placement cannot be part of any configuration consistent\n                    // with this constraint; remove it.\n                    p.alive = false;\n                    totalCandidates[k]--;\n                    // Update cover counts for all cells covered by this placement\n                    for (int cell2 : p.cells) {\n                        coverCount[k][cell2]--;\n                    }\n                }\n            }\n        }\n    };\n\n    // Exact enumeration of remaining placements when search space is small.\n    // Returns true if it found new determined cells (put in cellsOut/valsOut).\n    auto tryEnumeration = [&](vector<int> &cellsOut, vector<int> &valsOut) -> bool {\n        cellsOut.clear();\n        valsOut.clear();\n\n        // Gather fields with >1 candidate and count them\n        vector<pair<int,int>> multi; // {candidateCount, fieldIndex}\n        multi.reserve(M);\n        for (int k = 0; k < M; ++k) {\n            int cnt = totalCandidates[k];\n            if (cnt <= 0) {\n                // Inconsistent candidate set; give up enumeration.\n                return false;\n            }\n            if (cnt > 1) multi.emplace_back(cnt, k);\n        }\n\n        if (multi.empty()) {\n            // All fields have a unique placement.\n            // v(c) is fully determined by these placements.\n            vector<int> baseSum(N2, 0);\n            for (int k = 0; k < M; ++k) {\n                // Find the single alive placement\n                int idx = -1;\n                for (int pi = 0; pi < (int)placements[k].size(); ++pi) {\n                    if (placements[k][pi].alive) { idx = pi; break; }\n                }\n                if (idx == -1) return false; // safety\n                for (int cell2 : placements[k][idx].cells) {\n                    baseSum[cell2]++;\n                }\n            }\n            bool anyNew = false;\n            for (int c = 0; c < N2; ++c) {\n                int val = baseSum[c];\n                if (known[c] != -1) {\n                    continue;\n                }\n                if (observed[c] != -1 && observed[c] != val) {\n                    continue;\n                }\n                cellsOut.push_back(c);\n                valsOut.push_back(val);\n                anyNew = true;\n            }\n            return anyNew;\n        }\n\n        // Sort fields with multiple candidates by increasing candidate count\n        sort(multi.begin(), multi.end());\n\n        const long double PROD_LIMIT = 60000.0L; // max number of full assignments to consider\n        long double prod = 1.0L;\n        for (auto &pr : multi) {\n            prod *= pr.first;\n            if (prod > PROD_LIMIT) {\n                return false; // too many combinations; skip enumeration\n            }\n        }\n\n        int V = (int)multi.size();\n        vector<int> varField(V);\n        for (int i = 0; i < V; ++i) varField[i] = multi[i].second;\n\n        // Prepare candidate placement lists per variable field\n        vector<vector<int>> candList(V);\n        for (int i = 0; i < V; ++i) {\n            int k = varField[i];\n            vector<int> &lst = candList[i];\n            lst.reserve(multi[i].first);\n            for (int pi = 0; pi < (int)placements[k].size(); ++pi) {\n                if (placements[k][pi].alive) lst.push_back(pi);\n            }\n            if ((int)lst.size() != multi[i].first) {\n                return false;\n            }\n        }\n\n        // baseSum: contributions from fields with exactly one candidate\n        vector<int> baseSum(N2, 0);\n        for (int k = 0; k < M; ++k) {\n            if (totalCandidates[k] == 1) {\n                int idx = -1;\n                for (int pi = 0; pi < (int)placements[k].size(); ++pi) {\n                    if (placements[k][pi].alive) { idx = pi; break; }\n                }\n                if (idx == -1) return false; // safety\n                for (int cell2 : placements[k][idx].cells) {\n                    baseSum[cell2]++;\n                }\n            }\n        }\n\n        // partialSum: contributions from the chosen placements of variable fields\n        vector<int> partialSum(N2, 0);\n\n        // For enumeration results\n        vector<int> assignMin(N2, INT_MAX);\n        vector<int> assignMax(N2, -1);\n        long long solutions = 0;\n\n        const long long NODE_LIMIT = 400000; // limit on DFS nodes\n        long long nodesVisited = 0;\n        bool aborted = false;\n\n        function<void(int)> dfs = [&](int idx) {\n            if (aborted) return;\n            if (idx == V) {\n                // Complete assignment; verify consistency with known/observed\n                for (int c = 0; c < N2; ++c) {\n                    int val = baseSum[c] + partialSum[c];\n                    if (known[c] != -1 && val != known[c]) return;\n                    if (known[c] == -1 && observed[c] != -1 && val != observed[c]) return;\n                }\n                // Valid complete assignment; record v(c)\n                solutions++;\n                for (int c = 0; c < N2; ++c) {\n                    int val = baseSum[c] + partialSum[c];\n                    if (val < assignMin[c]) assignMin[c] = val;\n                    if (val > assignMax[c]) assignMax[c] = val;\n                }\n                return;\n            }\n\n            int k = varField[idx];\n            vector<int> &cand = candList[idx];\n\n            for (int pid : cand) {\n                Placement &pl = placements[k][pid];\n                bool ok = true;\n\n                // Apply this placement's contribution\n                for (int cell2 : pl.cells) {\n                    partialSum[cell2]++;\n                    int val = baseSum[cell2] + partialSum[cell2];\n                    if (known[cell2] != -1 && val > known[cell2]) {\n                        ok = false;\n                    } else if (known[cell2] == -1 && observed[cell2] != -1 && val > observed[cell2]) {\n                        ok = false;\n                    }\n                }\n\n                if (ok) {\n                    dfs(idx + 1);\n                }\n\n                // Revert\n                for (int cell2 : pl.cells) {\n                    partialSum[cell2]--;\n                }\n\n                nodesVisited++;\n                if (nodesVisited > NODE_LIMIT) {\n                    aborted = true;\n                    return;\n                }\n            }\n        };\n\n        dfs(0);\n\n        if (aborted || solutions == 0) {\n            return false;\n        }\n\n        bool anyNew = false;\n        for (int c = 0; c < N2; ++c) {\n            if (known[c] != -1) continue;\n            if (observed[c] != -1) continue;\n            if (assignMin[c] == INT_MAX) continue;\n            if (assignMin[c] == assignMax[c]) {\n                cellsOut.push_back(c);\n                valsOut.push_back(assignMin[c]);\n                anyNew = true;\n            }\n        }\n        return anyNew;\n    };\n\n    int drilledCount = 0;\n    const int MAX_OPS = 2 * N2 - 1; // leave room for final answer\n\n    while (true) {\n        // Update candidate-based bounds and inferred bounds\n        recomputeCandidateMinMax();\n        recomputeInfoBounds();\n\n        // Collect new known cells from exact observations or interval collapse\n        vector<int> newCells;\n        vector<int> newVals;\n        newCells.reserve(N2);\n        newVals.reserve(N2);\n\n        for (int c = 0; c < N2; ++c) {\n            if (known[c] != -1) continue;\n            if (observed[c] != -1) {\n                newCells.push_back(c);\n                newVals.push_back(observed[c]);\n            } else if (infoMin[c] == infoMax[c]) {\n                newCells.push_back(c);\n                newVals.push_back(infoMin[c]);\n            }\n        }\n\n        if (!newCells.empty()) {\n            // Turn these into hard constraints\n            for (int idx = 0; idx < (int)newCells.size(); ++idx) {\n                int c = newCells[idx];\n                int v = newVals[idx];\n                known[c] = v;\n                applyConstraint(c, v);\n            }\n            continue; // go back to recompute with new constraints\n        }\n\n        // No simple new known cells from intervals. Check if everything is determined.\n        bool allKnown = true;\n        for (int c = 0; c < N2; ++c) {\n            if (known[c] == -1) {\n                allKnown = false;\n                break;\n            }\n        }\n        if (allKnown) break;\n\n        // Try exact enumeration when search space is small\n        {\n            vector<int> enumCells;\n            vector<int> enumVals;\n            bool got = tryEnumeration(enumCells, enumVals);\n            if (got) {\n                for (int idx = 0; idx < (int)enumCells.size(); ++idx) {\n                    int c = enumCells[idx];\n                    int v = enumVals[idx];\n                    if (known[c] == -1) {\n                        known[c] = v;\n                        applyConstraint(c, v);\n                    }\n                }\n                continue; // re-run main loop with stronger constraints\n            }\n        }\n\n        // If we exhausted the allowed number of drills, stop drilling\n        if (drilledCount >= MAX_OPS) break;\n\n        // Choose next cell to drill among unknown cells:\n        // prefer cells with infoMin < infoMax and high elimSum, breaking ties by interval width.\n        int bestCell = -1;\n        long long bestScore = -1; // composite score: elimSum * big + diff\n        for (int c = 0; c < N2; ++c) {\n            if (known[c] != -1) continue;              // already determined\n            if (infoMin[c] == infoMax[c]) continue;    // already effectively determined\n            int diff = infoMax[c] - infoMin[c];\n            int elim = elimSum[c];\n            if (diff <= 0 && elim <= 0) continue;\n            long long score = (long long)elim * 1000LL + diff; // weights: elim >> diff\n            if (score > bestScore) {\n                bestScore = score;\n                bestCell = c;\n            }\n        }\n        // Fallback: if still none, pick widest interval\n        if (bestCell == -1) {\n            int bestDiff = -1;\n            for (int c = 0; c < N2; ++c) {\n                if (known[c] != -1) continue;\n                int diff = infoMax[c] - infoMin[c];\n                if (diff > bestDiff) {\n                    bestDiff = diff;\n                    bestCell = c;\n                }\n            }\n        }\n        if (bestCell == -1) break; // nothing left to drill\n\n        int bi = bestCell / N;\n        int bj = bestCell % N;\n\n        // Drill this cell\n        cout << \"q 1 \" << bi << ' ' << bj << '\\n' << flush;\n        int v_resp;\n        if (!(cin >> v_resp)) return 0;\n        observed[bestCell] = v_resp;\n        drilledCount++;\n    }\n\n    // Final inference: recompute bounds one last time\n    recomputeCandidateMinMax();\n    recomputeInfoBounds();\n\n    vector<pair<int,int>> has_oil;\n    has_oil.reserve(N2);\n    for (int c = 0; c < N2; ++c) {\n        int val;\n        if (known[c] != -1) {\n            val = known[c];\n        } else if (observed[c] != -1) {\n            val = observed[c];\n        } else {\n            // Fallback: use inferred min (should be close or equal to true)\n            val = infoMin[c];\n        }\n        if (val > 0) {\n            int i = c / N;\n            int j = c % N;\n            has_oil.emplace_back(i, j);\n        }\n    }\n\n    // Output the answer\n    cout << \"a \" << has_oil.size();\n    for (auto &p : has_oil) {\n        cout << ' ' << p.first << ' ' << p.second;\n    }\n    cout << '\\n' << flush;\n\n    // Read verdict (1 = correct, 0 = wrong); should be 1 if logic is correct.\n    int verdict;\n    if (!(cin >> verdict)) return 0;\n\n    return 0;\n}","ahc031":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Rect {\n    int i0, j0, i1, j1;\n};\n\n// Greedy \"water-filling\" stripes assignment.\n// dem: demands (areas) for the items (in any order).\n// H  : height of the stripe region.\n// W  : total width limit.\n// Returns: (total shortage in cells, widths for each item in dem order).\npair<long long, vector<int>> stripes_assign(const vector<long long> &dem, int H, int W) {\n    int M = (int)dem.size();\n    vector<int> w(M, 1);      // each item gets at least width 1\n    int widthSum = M;\n    long long base = H;\n\n    // Max-heap of (residual shortage if width=1, index)\n    priority_queue<pair<long long,int>> pq;\n    for (int i = 0; i < M; i++) {\n        long long r = dem[i] - base;  // residual if width=1\n        if (r > 0) pq.emplace(r, i);\n    }\n\n    while (widthSum < W && !pq.empty()) {\n        auto [r, idx] = pq.top();\n        pq.pop();\n        if (r <= 0) break;\n        w[idx]++;\n        widthSum++;\n        r -= base;\n        if (r > 0) pq.emplace(r, idx);\n    }\n\n    long long def = 0;\n    for (int i = 0; i < M; i++) {\n        long long cap = 1LL * H * w[i];\n        long long diff = dem[i] - cap;\n        if (diff > 0) def += diff;\n    }\n\n    return {def, w};\n}\n\n// Deterministic guillotine packing heuristic (per day).\n// Returns (shortage in cells, rectangles for each reservation index).\npair<long long, vector<Rect>> run_guillotine(const vector<long long> &dem, int W) {\n    int N = (int)dem.size();\n    vector<Rect> rects(N);\n\n    vector<Rect> freeR;\n    freeR.push_back({0, 0, W, W});\n\n    // Order reservations by descending area\n    vector<int> order(N);\n    iota(order.begin(), order.end(), 0);\n    sort(order.begin(), order.end(),\n         [&](int i, int j) { return dem[i] > dem[j]; });\n\n    vector<bool> assigned(N, false);\n    bool fail = false;\n\n    for (int t = 0; t < N; t++) {\n        int idx = order[t];\n        long long A = dem[idx];\n\n        long long bestWaste = LLONG_MAX;\n        int bestF = -1;\n        int bestOrient = -1; // 0 = vertical (full height), 1 = horizontal (full width), 2 = full rectangle\n        int bestW = 0, bestH = 0;\n\n        int bestSmallF = -1;\n        long long bestSmallArea = -1;\n\n        for (int f = 0; f < (int)freeR.size(); f++) {\n            Rect R = freeR[f];\n            int i0 = R.i0, j0 = R.j0, i1 = R.i1, j1 = R.j1;\n            int rh = i1 - i0;\n            int rw = j1 - j0;\n            if (rh <= 0 || rw <= 0) continue;\n            long long areaR = 1LL * rh * rw;\n\n            if (areaR >= A) {\n                // Vertical option: full height\n                long long reqW = (A + rh - 1) / rh;\n                if (reqW <= rw) {\n                    long long allocArea = 1LL * reqW * rh;\n                    long long waste = allocArea - A;\n                    if (waste < bestWaste) {\n                        bestWaste = waste;\n                        bestF = f;\n                        bestOrient = 0;\n                        bestW = (int)reqW;\n                        bestH = rh;\n                    }\n                }\n                // Horizontal option: full width\n                long long reqH = (A + rw - 1) / rw;\n                if (reqH <= rh) {\n                    long long allocArea = 1LL * reqH * rw;\n                    long long waste = allocArea - A;\n                    if (waste < bestWaste) {\n                        bestWaste = waste;\n                        bestF = f;\n                        bestOrient = 1;\n                        bestW = rw;\n                        bestH = (int)reqH;\n                    }\n                }\n                // Full-rectangle option\n                long long allocArea = areaR;\n                long long waste = allocArea - A;\n                if (waste < bestWaste) {\n                    bestWaste = waste;\n                    bestF = f;\n                    bestOrient = 2;\n                    bestW = rw;\n                    bestH = rh;\n                }\n            } else {\n                // Can't fully satisfy A with this rectangle; remember best for partial use\n                if (areaR > bestSmallArea) {\n                    bestSmallArea = areaR;\n                    bestSmallF = f;\n                }\n            }\n        }\n\n        if (bestF != -1) {\n            // Use a rectangle from freeR[bestF] with chosen orientation\n            Rect R = freeR[bestF];\n            int i0 = R.i0, j0 = R.j0, i1 = R.i1, j1 = R.j1;\n            int rh = i1 - i0;\n            int rw = j1 - j0;\n\n            if (bestOrient == 0) {\n                // Vertical: full height, width = bestW\n                int wAlloc = bestW;\n                Rect used = {i0, j0, i1, j0 + wAlloc};\n                rects[idx] = used;\n                assigned[idx] = true;\n\n                Rect right = {i0, j0 + wAlloc, i1, j1};\n                freeR[bestF] = freeR.back();\n                freeR.pop_back();\n                if (right.i1 > right.i0 && right.j1 > right.j0) {\n                    freeR.push_back(right);\n                }\n            } else if (bestOrient == 1) {\n                // Horizontal: full width, height = bestH\n                int hAlloc = bestH;\n                Rect used = {i0, j0, i0 + hAlloc, j1};\n                rects[idx] = used;\n                assigned[idx] = true;\n\n                Rect bottom = {i0 + hAlloc, j0, i1, j1};\n                freeR[bestF] = freeR.back();\n                freeR.pop_back();\n                if (bottom.i1 > bottom.i0 && bottom.j1 > bottom.j0) {\n                    freeR.push_back(bottom);\n                }\n            } else {\n                // Full rectangle\n                Rect used = {i0, j0, i1, j1};\n                rects[idx] = used;\n                assigned[idx] = true;\n                freeR[bestF] = freeR.back();\n                freeR.pop_back();\n            }\n        } else {\n            if (bestSmallF == -1) {\n                fail = true;\n                break;\n            }\n            // No free rectangle can fully satisfy A; use largest free rectangle\n            Rect R = freeR[bestSmallF];\n            rects[idx] = R;\n            assigned[idx] = true;\n            freeR[bestSmallF] = freeR.back();\n            freeR.pop_back();\n        }\n    }\n\n    if (fail) {\n        return {LLONG_MAX, vector<Rect>()};\n    }\n\n    bool allAssigned = true;\n    for (int k = 0; k < N; k++) {\n        if (!assigned[k]) { allAssigned = false; break; }\n    }\n    if (!allAssigned) {\n        return {LLONG_MAX, vector<Rect>()};\n    }\n\n    long long def = 0;\n    for (int k = 0; k < N; k++) {\n        const Rect &r = rects[k];\n        long long area = 1LL * (r.i1 - r.i0) * (r.j1 - r.j0);\n        long long diff = dem[k] - area;\n        if (diff > 0) def += diff;\n    }\n    return {def, rects};\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int W, D, N;\n    if (!(cin >> W >> D >> N)) return 0;\n\n    vector<vector<long long>> a(D, vector<long long>(N));\n    for (int d = 0; d < D; d++) {\n        for (int k = 0; k < N; k++) {\n            cin >> a[d][k];\n        }\n    }\n\n    const int C = 3; // 0=stripe, 1=hybrid, 2=guillotine\n\n    // Pre-allocate structures\n    vector<vector<vector<Rect>>> rects(D, vector<vector<Rect>>(C, vector<Rect>(N)));\n    vector<vector<long long>> defCells(D, vector<long long>(C, LLONG_MAX));\n\n    int NSeg = W * (W - 1); // number of interior segments per orientation\n    int S64 = (NSeg + 63) / 64;\n\n    vector<vector<vector<uint64_t>>> Hbits(D, vector<vector<uint64_t>>(C, vector<uint64_t>(S64)));\n    vector<vector<vector<uint64_t>>> Vbits(D, vector<vector<uint64_t>>(C, vector<uint64_t>(S64)));\n\n    // Static DP table for subset-sum row packing\n    static bool dp[51][1001];\n\n    // ---------- Build candidates and their edge bitsets for all days ----------\n    for (int d = 0; d < D; d++) {\n        const auto &dem = a[d];\n\n        // -------- Candidate 0: baseline full-height stripes --------\n        auto [defStripe, widthsStripe] = stripes_assign(dem, W, W);\n        defCells[d][0] = defStripe;\n        {\n            int x = 0;\n            for (int k = 0; k < N; k++) {\n                int w = widthsStripe[k];\n                int j0 = x;\n                int j1 = x + w;\n                if (j1 > W) j1 = W; // safety clamp\n                x = j1;\n                rects[d][0][k] = {0, j0, W, j1};\n            }\n        }\n\n        // -------- Candidate 1: hybrid layout (small rows + big stripes) --------\n        {\n            vector<int> smallIdx, bigIdx;\n            smallIdx.reserve(N);\n            bigIdx.reserve(N);\n            for (int k = 0; k < N; k++) {\n                if (dem[k] < W) smallIdx.push_back(k);\n                else bigIdx.push_back(k);\n            }\n\n            if (smallIdx.empty()) {\n                // No smalls -> hybrid same as stripes\n                rects[d][1] = rects[d][0];\n                defCells[d][1] = defCells[d][0];\n            } else {\n                int S = (int)smallIdx.size();\n                vector<int> smallRow(N, -1), smallJ0(N, 0);\n                vector<int> remaining = smallIdx;\n                vector<int> rowUsedWidth;\n                rowUsedWidth.reserve(S);\n\n                int row = 0;\n                while (!remaining.empty()) {\n                    int M = (int)remaining.size();\n                    vector<int> w(M);\n                    for (int i = 0; i < M; i++) {\n                        w[i] = (int)dem[remaining[i]]; // dem[idx] < W, safe\n                    }\n\n                    // DP: dp[i][j] reachable using first i items with sum j\n                    for (int i = 0; i <= M; i++)\n                        for (int j = 0; j <= W; j++)\n                            dp[i][j] = false;\n                    dp[0][0] = true;\n\n                    for (int i = 0; i < M; i++) {\n                        int wi = w[i];\n                        for (int j = 0; j <= W; j++) {\n                            if (!dp[i][j]) continue;\n                            dp[i+1][j] = true; // skip\n                            if (j + wi <= W) dp[i+1][j + wi] = true; // take\n                        }\n                    }\n\n                    int best = 0;\n                    for (int j = W; j >= 1; j--) {\n                        if (dp[M][j]) { best = j; break; }\n                    }\n                    if (best == 0) {\n                        best = w[0];\n                    }\n\n                    // Reconstruct subset\n                    vector<int> use(M, 0);\n                    int j = best;\n                    for (int i = M - 1; i >= 0; i--) {\n                        if (j >= w[i] && dp[i][j - w[i]]) {\n                            use[i] = 1;\n                            j -= w[i];\n                        } else {\n                            use[i] = 0;\n                        }\n                    }\n\n                    int curWidth = 0;\n                    vector<int> newRemaining;\n                    newRemaining.reserve(M);\n                    for (int i = 0; i < M; i++) {\n                        int idx = remaining[i];\n                        if (use[i]) {\n                            int j0 = curWidth;\n                            int j1 = j0 + w[i];\n                            if (j1 > W) j1 = W; // safety\n                            smallRow[idx] = row;\n                            smallJ0[idx] = j0;\n                            curWidth = j1;\n                        } else {\n                            newRemaining.push_back(idx);\n                        }\n                    }\n                    remaining.swap(newRemaining);\n                    rowUsedWidth.push_back(curWidth);\n                    row++;\n                }\n\n                int H_small = row;\n                if (H_small > W) {\n                    // Should not happen; fallback to stripes\n                    rects[d][1] = rects[d][0];\n                    defCells[d][1] = defCells[d][0];\n                } else if (bigIdx.empty()) {\n                    // Only small items: zero shortage\n                    for (int idx : smallIdx) {\n                        int r = smallRow[idx];\n                        int j0 = smallJ0[idx];\n                        int j1 = j0 + (int)dem[idx];\n                        if (j1 > W) j1 = W;\n                        rects[d][1][idx] = {r, j0, r + 1, j1};\n                    }\n                    defCells[d][1] = 0;\n                } else {\n                    int H_big = W - H_small;\n                    if (H_big <= 0) {\n                        // No space for bigs; fallback\n                        rects[d][1] = rects[d][0];\n                        defCells[d][1] = defCells[d][0];\n                    } else {\n                        int Mbig = (int)bigIdx.size();\n                        vector<pair<long long,int>> bigList;\n                        bigList.reserve(Mbig);\n                        for (int idx : bigIdx) {\n                            bigList.emplace_back(dem[idx], idx);\n                        }\n                        sort(bigList.begin(), bigList.end(),\n                             [&](const pair<long long,int> &p1, const pair<long long,int> &p2) {\n                                 return p1.first < p2.first;\n                             });\n\n                        vector<long long> bigDemands(Mbig);\n                        vector<int> bigOrderIndex(Mbig);\n                        for (int i = 0; i < Mbig; i++) {\n                            bigDemands[i] = bigList[i].first;\n                            bigOrderIndex[i] = bigList[i].second;\n                        }\n\n                        auto [defBig, widthsBig] = stripes_assign(bigDemands, H_big, W);\n\n                        // Small rectangles\n                        for (int idx : smallIdx) {\n                            int r = smallRow[idx];\n                            int j0 = smallJ0[idx];\n                            int j1 = j0 + (int)dem[idx];\n                            if (j1 > W) j1 = W;\n                            rects[d][1][idx] = {r, j0, r + 1, j1};\n                        }\n\n                        // Big rectangles as vertical stripes in [H_small, W)\n                        int x = 0;\n                        for (int i = 0; i < Mbig; i++) {\n                            int idx = bigOrderIndex[i];\n                            int w = widthsBig[i];\n                            int j0 = x;\n                            int j1 = x + w;\n                            if (j1 > W) j1 = W;\n                            x = j1;\n                            rects[d][1][idx] = {H_small, j0, W, j1};\n                        }\n\n                        defCells[d][1] = defBig;\n                    }\n                }\n            }\n        }\n\n        // -------- Candidate 2: guillotine packing --------\n        {\n            auto [defGuill, rectGuillVec] = run_guillotine(dem, W);\n            if (defGuill == LLONG_MAX) {\n                // Fallback to stripes\n                defCells[d][2] = defCells[d][0];\n                rects[d][2] = rects[d][0];\n            } else {\n                defCells[d][2] = defGuill;\n                rects[d][2] = move(rectGuillVec);\n            }\n        }\n\n        // -------- Build H/V bitsets for all 3 candidates on this day --------\n        for (int c = 0; c < C; c++) {\n            // Clear bitsets\n            fill(Hbits[d][c].begin(), Hbits[d][c].end(), 0ULL);\n            fill(Vbits[d][c].begin(), Vbits[d][c].end(), 0ULL);\n\n            // Mark edges\n            for (int k = 0; k < N; k++) {\n                const Rect &r = rects[d][c][k];\n                int i0 = r.i0, j0 = r.j0, i1 = r.i1, j1 = r.j1;\n\n                // Horizontal edges (internal only)\n                // top edge at i0\n                if (i0 > 0) {\n                    int i = i0;\n                    int base = (i - 1) * W;\n                    for (int j = j0; j < j1; j++) {\n                        int idx = base + j; // 0 <= idx < (W-1)*W\n                        int word = idx >> 6;\n                        int bit = idx & 63;\n                        Hbits[d][c][word] |= (1ULL << bit);\n                    }\n                }\n                // bottom edge at i1\n                if (i1 < W) {\n                    int i = i1;\n                    int base = (i - 1) * W;\n                    for (int j = j0; j < j1; j++) {\n                        int idx = base + j;\n                        int word = idx >> 6;\n                        int bit = idx & 63;\n                        Hbits[d][c][word] |= (1ULL << bit);\n                    }\n                }\n\n                // Vertical edges (internal only)\n                // left edge at j0\n                if (j0 > 0) {\n                    int j = j0;\n                    for (int i = i0; i < i1; i++) {\n                        int idx = i * (W - 1) + (j - 1); // 0 <= idx < W*(W-1)\n                        int word = idx >> 6;\n                        int bit = idx & 63;\n                        Vbits[d][c][word] |= (1ULL << bit);\n                    }\n                }\n                // right edge at j1\n                if (j1 < W) {\n                    int j = j1;\n                    for (int i = i0; i < i1; i++) {\n                        int idx = i * (W - 1) + (j - 1);\n                        int word = idx >> 6;\n                        int bit = idx & 63;\n                        Vbits[d][c][word] |= (1ULL << bit);\n                    }\n                }\n            }\n        }\n    }\n\n    // ---------- DP over days to choose candidates minimizing total cost ----------\n    vector<long long> dpPrev(C, LLONG_MAX), dpCur(C, LLONG_MAX);\n    vector<array<int,3>> parent(D); // parent[d][c] = prev candidate index\n\n    // Day 0: no partition cost\n    for (int c = 0; c < C; c++) {\n        long long areaCost = defCells[0][c] * 100LL;\n        dpPrev[c] = areaCost;\n        parent[0][c] = -1;\n    }\n\n    for (int d = 1; d < D; d++) {\n        for (int c = 0; c < C; c++) dpCur[c] = LLONG_MAX;\n\n        // Precompute transition costs L(prev,cur) between day d-1 and d\n        long long L[3][3];\n        for (int p = 0; p < C; p++) {\n            for (int c = 0; c < C; c++) {\n                long long l = 0;\n                // Horizontal segments\n                for (int w64 = 0; w64 < S64; w64++) {\n                    uint64_t x = Hbits[d-1][p][w64] ^ Hbits[d][c][w64];\n                    if (x) l += __builtin_popcountll(x);\n                }\n                // Vertical segments\n                for (int w64 = 0; w64 < S64; w64++) {\n                    uint64_t x = Vbits[d-1][p][w64] ^ Vbits[d][c][w64];\n                    if (x) l += __builtin_popcountll(x);\n                }\n                L[p][c] = l;\n            }\n        }\n\n        for (int c = 0; c < C; c++) {\n            long long areaCost = defCells[d][c] * 100LL;\n            long long best = LLONG_MAX;\n            int bestPrev = -1;\n            for (int p = 0; p < C; p++) {\n                if (dpPrev[p] == LLONG_MAX) continue;\n                long long cost = dpPrev[p] + areaCost + L[p][c];\n                if (cost < best) {\n                    best = cost;\n                    bestPrev = p;\n                }\n            }\n            dpCur[c] = best;\n            parent[d][c] = bestPrev;\n        }\n\n        dpPrev.swap(dpCur);\n    }\n\n    // Choose best candidate for last day\n    long long bestTotal = LLONG_MAX;\n    int lastC = 0;\n    for (int c = 0; c < C; c++) {\n        if (dpPrev[c] < bestTotal) {\n            bestTotal = dpPrev[c];\n            lastC = c;\n        }\n    }\n\n    // Reconstruct chosen candidate per day\n    vector<int> chosen(D);\n    chosen[D-1] = lastC;\n    for (int d = D-1; d >= 1; d--) {\n        chosen[d-1] = parent[d][chosen[d]];\n    }\n\n    // ---------- Output rectangles according to chosen candidates ----------\n    for (int d = 0; d < D; d++) {\n        int c = chosen[d];\n        for (int k = 0; k < N; k++) {\n            Rect r = rects[d][c][k];\n            int i0 = r.i0;\n            int j0 = r.j0;\n            int i1 = r.i1;\n            int j1 = r.j1;\n            // Final safety clamps\n            if (i0 < 0) i0 = 0;\n            if (i1 > W) i1 = W;\n            if (j0 < 0) j0 = 0;\n            if (j1 > W) j1 = W;\n            if (i0 >= i1) i1 = min(W, i0 + 1);\n            if (j0 >= j1) j1 = min(W, j0 + 1);\n            cout << i0 << ' ' << j0 << ' ' << i1 << ' ' << j1 << '\\n';\n        }\n    }\n\n    return 0;\n}","ahc032":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const long long MOD = 998244353LL;\n\n// Fast RNG (xorshift64)\nstruct XorShift64 {\n    uint64_t x;\n    XorShift64(uint64_t seed = 88172645463325252ull) {\n        x = seed ? seed : 88172645463325252ull;\n    }\n    inline uint64_t next() {\n        uint64_t y = x;\n        y ^= y << 7;\n        y ^= y >> 9;\n        return x = y;\n    }\n    inline int next_int(int n) { // 0..n-1\n        return (int)(next() % (uint64_t)n);\n    }\n    inline double next_double() { // [0,1)\n        return (next() >> 11) * (1.0 / (1ULL << 53));\n    }\n};\n\nstruct Op {\n    int m, p, q;\n};\n\nstruct CellChange {\n    int idx;\n    int oldv;\n    int newv;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    auto global_start = chrono::steady_clock::now();\n    const double TOTAL_LIMIT = 1.9; // safety margin under 2.0s\n\n    int N, M, K;\n    if (!(cin >> N >> M >> K)) return 0;\n    const int NN = N * N;\n\n    // Read initial board\n    vector<int> initial_board(NN);\n    long long initial_score = 0;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            long long v;\n            cin >> v;\n            v %= MOD;\n            initial_board[i * N + j] = (int)v;\n            initial_score += v;\n        }\n    }\n\n    // Read stamps s[m][3][3]\n    static int s[20][3][3];\n    for (int m = 0; m < M; ++m) {\n        for (int i = 0; i < 3; ++i) {\n            for (int j = 0; j < 3; ++j) {\n                long long v;\n                cin >> v;\n                v %= MOD;\n                s[m][i][j] = (int)v;\n            }\n        }\n    }\n\n    // Precompute all candidate operations (m, p, q)\n    vector<Op> all_ops;\n    all_ops.reserve(M * (N - 2) * (N - 2));\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                all_ops.push_back({m, p, q});\n            }\n        }\n    }\n    const int NUM_OPS = (int)all_ops.size(); // N=9,M=20 => 980\n\n    // Precompute for each op: its 9 cell indices and increment values\n    vector<array<int, 9>> op_cells(NUM_OPS);\n    vector<array<int, 9>> op_vals(NUM_OPS);\n    // For fast lookup: board-index -> pos (0..8) in op or -1\n    vector<array<int8_t, 81>> op_pos(NUM_OPS);\n\n    for (int op_id = 0; op_id < NUM_OPS; ++op_id) {\n        const Op &op = all_ops[op_id];\n        int m = op.m, p = op.p, q = op.q;\n        array<int, 9> cells;\n        array<int, 9> vals;\n        int t = 0;\n        for (int di = 0; di < 3; ++di) {\n            int r = p + di;\n            int base = r * N;\n            for (int dj = 0; dj < 3; ++dj) {\n                int c = q + dj;\n                int idx = base + c;\n                cells[t] = idx;\n                vals[t] = s[m][di][dj];\n                ++t;\n            }\n        }\n        op_cells[op_id] = cells;\n        op_vals[op_id] = vals;\n\n        auto &pm = op_pos[op_id];\n        pm.fill(-1);\n        for (int i = 0; i < 9; ++i) {\n            pm[cells[i]] = (int8_t)i;\n        }\n    }\n\n    // RNG\n    uint64_t seed = chrono::high_resolution_clock::now().time_since_epoch().count();\n    XorShift64 rng(seed);\n\n    // Working board and greedy initial solution\n    vector<int> board = initial_board;\n    long long cur_score = initial_score;\n    vector<int> cur_ops;\n    cur_ops.reserve(K);\n\n    // Greedy: repeatedly add best positive operation\n    for (int step = 0; step < K; ++step) {\n        long long best_delta = 0;\n        int best_id = -1;\n        for (int op_id = 0; op_id < NUM_OPS; ++op_id) {\n            const auto &cells = op_cells[op_id];\n            const auto &vals  = op_vals[op_id];\n            long long delta = 0;\n            for (int t = 0; t < 9; ++t) {\n                int d = vals[t];\n                if (d == 0) continue;\n                int idx = cells[t];\n                int x = board[idx];\n                int tmp = x + d;\n                if (tmp >= MOD) tmp -= MOD;\n                delta += tmp - x;\n            }\n            if (delta > best_delta) {\n                best_delta = delta;\n                best_id = op_id;\n            }\n        }\n        if (best_id == -1 || best_delta <= 0) break;\n\n        const auto &cells = op_cells[best_id];\n        const auto &vals  = op_vals[best_id];\n        for (int t = 0; t < 9; ++t) {\n            int d = vals[t];\n            if (d == 0) continue;\n            int idx = cells[t];\n            int x = board[idx];\n            int tmp = x + d;\n            if (tmp >= MOD) tmp -= MOD;\n            board[idx] = tmp;\n        }\n        cur_score += best_delta;\n        cur_ops.push_back(best_id);\n    }\n\n    long long best_score = cur_score;\n    vector<int> best_ops = cur_ops;\n\n    // Simulated Annealing\n    const double SA_TIME_LIMIT = 1.6; // seconds for SA\n    auto sa_start = chrono::steady_clock::now();\n    const double T0 = 1e9;\n    const double T_end = 1e6;\n    double T = T0;\n\n    CellChange changes[18]; // max affected cells in REPLACE\n    int iteration = 0;\n\n    while (true) {\n        if ((iteration & 1023) == 0) {\n            auto now = chrono::steady_clock::now();\n            double elapsed_sa = chrono::duration<double>(now - sa_start).count();\n            if (elapsed_sa >= SA_TIME_LIMIT) break;\n            double progress = elapsed_sa / SA_TIME_LIMIT;\n            if (progress > 1.0) progress = 1.0;\n            T = T0 + (T_end - T0) * progress;\n        }\n        ++iteration;\n\n        int L = (int)cur_ops.size();\n        int move_type; // 0=ADD,1=REMOVE,2=REPLACE\n        if (L == 0) {\n            move_type = 0;\n        } else if (L == K) {\n            move_type = (rng.next_int(2) == 0 ? 1 : 2);\n        } else {\n            int r = rng.next_int(100);\n            if (r < 40) move_type = 0;        // 40% ADD\n            else if (r < 80) move_type = 2;   // 40% REPLACE\n            else move_type = 1;               // 20% REMOVE\n        }\n\n        long long deltaScore = 0;\n        int chN = 0;\n\n        if (move_type == 0) { // ADD\n            int op_new = rng.next_int(NUM_OPS);\n            const auto &cells = op_cells[op_new];\n            const auto &vals  = op_vals[op_new];\n\n            deltaScore = 0;\n            chN = 0;\n            for (int t = 0; t < 9; ++t) {\n                int d = vals[t];\n                if (d == 0) continue;\n                int idx = cells[t];\n                int x = board[idx];\n                int tmp = x + d;\n                if (tmp >= MOD) tmp -= MOD;\n                if (tmp != x) {\n                    deltaScore += tmp - x;\n                    changes[chN++] = {idx, x, tmp};\n                }\n            }\n\n            bool accept;\n            if (deltaScore >= 0) {\n                accept = true;\n            } else if (-deltaScore > 20.0 * T) {\n                accept = false;\n            } else {\n                double prob = exp((double)deltaScore / T);\n                accept = (rng.next_double() < prob);\n            }\n\n            if (accept) {\n                for (int i = 0; i < chN; ++i) {\n                    board[changes[i].idx] = changes[i].newv;\n                }\n                cur_score += deltaScore;\n                cur_ops.push_back(op_new);\n                if (cur_score > best_score) {\n                    best_score = cur_score;\n                    best_ops = cur_ops;\n                }\n            }\n\n        } else if (move_type == 1) { // REMOVE\n            if (L == 0) continue;\n            int idx_op = rng.next_int(L);\n            int op_old = cur_ops[idx_op];\n            const auto &cells = op_cells[op_old];\n            const auto &vals  = op_vals[op_old];\n\n            deltaScore = 0;\n            chN = 0;\n            for (int t = 0; t < 9; ++t) {\n                int d = vals[t];\n                if (d == 0) continue;\n                int idx = cells[t];\n                int x = board[idx];\n                int tmp = x - d;\n                if (tmp < 0) tmp += MOD;\n                if (tmp != x) {\n                    deltaScore += tmp - x;\n                    changes[chN++] = {idx, x, tmp};\n                }\n            }\n\n            bool accept;\n            if (deltaScore >= 0) {\n                accept = true;\n            } else if (-deltaScore > 20.0 * T) {\n                accept = false;\n            } else {\n                double prob = exp((double)deltaScore / T);\n                accept = (rng.next_double() < prob);\n            }\n\n            if (accept) {\n                for (int i = 0; i < chN; ++i) {\n                    board[changes[i].idx] = changes[i].newv;\n                }\n                cur_score += deltaScore;\n                cur_ops[idx_op] = cur_ops.back();\n                cur_ops.pop_back();\n                if (cur_score > best_score) {\n                    best_score = cur_score;\n                    best_ops = cur_ops;\n                }\n            }\n\n        } else { // REPLACE\n            if (L == 0) continue;\n            int idx_old = rng.next_int(L);\n            int op_old = cur_ops[idx_old];\n            int op_new = rng.next_int(NUM_OPS);\n            if (op_new == op_old) continue;\n\n            const auto &cellsOld = op_cells[op_old];\n            const auto &valsOld  = op_vals[op_old];\n            const auto &cellsNew = op_cells[op_new];\n            const auto &valsNew  = op_vals[op_new];\n\n            int idxList[18];\n            int uc = 0;\n            for (int t = 0; t < 9; ++t) idxList[uc++] = cellsOld[t];\n            for (int t = 0; t < 9; ++t) {\n                int idx = cellsNew[t];\n                bool found = false;\n                for (int z = 0; z < uc; ++z) {\n                    if (idxList[z] == idx) { found = true; break; }\n                }\n                if (!found) idxList[uc++] = idx;\n            }\n\n            auto &posOldMap = op_pos[op_old];\n            auto &posNewMap = op_pos[op_new];\n\n            deltaScore = 0;\n            chN = 0;\n            for (int t = 0; t < uc; ++t) {\n                int idx = idxList[t];\n                int x = board[idx];\n\n                int posOld = (int)posOldMap[idx];\n                int d_old = (posOld >= 0 ? valsOld[posOld] : 0);\n                int posNew = (int)posNewMap[idx];\n                int d_new = (posNew >= 0 ? valsNew[posNew] : 0);\n                int diff = d_new - d_old;\n                if (diff == 0) continue;\n\n                int tmp = x + diff;\n                if (tmp < 0) tmp += MOD;\n                else if (tmp >= MOD) tmp -= MOD;\n\n                if (tmp != x) {\n                    deltaScore += tmp - x;\n                    changes[chN++] = {idx, x, tmp};\n                }\n            }\n\n            bool accept;\n            if (deltaScore >= 0) {\n                accept = true;\n            } else if (-deltaScore > 20.0 * T) {\n                accept = false;\n            } else {\n                double prob = exp((double)deltaScore / T);\n                accept = (rng.next_double() < prob);\n            }\n\n            if (accept) {\n                for (int i = 0; i < chN; ++i) {\n                    board[changes[i].idx] = changes[i].newv;\n                }\n                cur_score += deltaScore;\n                cur_ops[idx_old] = op_new;\n                if (cur_score > best_score) {\n                    best_score = cur_score;\n                    best_ops = cur_ops;\n                }\n            }\n        }\n    }\n\n    // Final deterministic local improvement from best SA solution\n    vector<int> sol_ops = best_ops;\n    vector<int> boardHC = initial_board;\n    long long scoreHC = initial_score;\n\n    // Rebuild boardHC from sol_ops\n    for (int op_id : sol_ops) {\n        const auto &cells = op_cells[op_id];\n        const auto &vals  = op_vals[op_id];\n        for (int t = 0; t < 9; ++t) {\n            int d = vals[t];\n            if (d == 0) continue;\n            int idx = cells[t];\n            int x = boardHC[idx];\n            int tmp = x + d;\n            if (tmp >= MOD) tmp -= MOD;\n            boardHC[idx] = tmp;\n            scoreHC += tmp - x;\n        }\n    }\n\n    // Hill climbing: best ADD / best REMOVE\n    const int MAX_HC_ITERS = 2000;\n    for (int iter = 0; iter < MAX_HC_ITERS; ++iter) {\n        auto now = chrono::steady_clock::now();\n        double elapsed_total = chrono::duration<double>(now - global_start).count();\n        if (elapsed_total >= TOTAL_LIMIT) break;\n\n        int L = (int)sol_ops.size();\n\n        long long bestAddDelta = 0;\n        int bestAddOp = -1;\n        if (L < K) {\n            for (int op_id = 0; op_id < NUM_OPS; ++op_id) {\n                const auto &cells = op_cells[op_id];\n                const auto &vals  = op_vals[op_id];\n                long long delta = 0;\n                for (int t = 0; t < 9; ++t) {\n                    int d = vals[t];\n                    if (d == 0) continue;\n                    int idx = cells[t];\n                    int x = boardHC[idx];\n                    int tmp = x + d;\n                    if (tmp >= MOD) tmp -= MOD;\n                    delta += tmp - x;\n                }\n                if (delta > bestAddDelta) {\n                    bestAddDelta = delta;\n                    bestAddOp = op_id;\n                }\n            }\n        }\n\n        long long bestRemDelta = 0;\n        int bestRemIdx = -1;\n        for (int i = 0; i < L; ++i) {\n            int op_id = sol_ops[i];\n            const auto &cells = op_cells[op_id];\n            const auto &vals  = op_vals[op_id];\n            long long delta = 0;\n            for (int t = 0; t < 9; ++t) {\n                int d = vals[t];\n                if (d == 0) continue;\n                int idx = cells[t];\n                int x = boardHC[idx];\n                int tmp = x - d;\n                if (tmp < 0) tmp += MOD;\n                delta += tmp - x;\n            }\n            if (delta > bestRemDelta) {\n                bestRemDelta = delta;\n                bestRemIdx = i;\n            }\n        }\n\n        if (bestAddDelta <= 0 && bestRemDelta <= 0) break;\n\n        if (bestAddDelta >= bestRemDelta && bestAddDelta > 0 && L < K && bestAddOp != -1) {\n            // Apply best ADD\n            const auto &cells = op_cells[bestAddOp];\n            const auto &vals  = op_vals[bestAddOp];\n            for (int t = 0; t < 9; ++t) {\n                int d = vals[t];\n                if (d == 0) continue;\n                int idx = cells[t];\n                int x = boardHC[idx];\n                int tmp = x + d;\n                if (tmp >= MOD) tmp -= MOD;\n                boardHC[idx] = tmp;\n                scoreHC += tmp - x;\n            }\n            sol_ops.push_back(bestAddOp);\n        } else if (bestRemDelta > 0 && bestRemIdx != -1) {\n            // Apply best REMOVE\n            int op_id = sol_ops[bestRemIdx];\n            const auto &cells = op_cells[op_id];\n            const auto &vals  = op_vals[op_id];\n            for (int t = 0; t < 9; ++t) {\n                int d = vals[t];\n                if (d == 0) continue;\n                int idx = cells[t];\n                int x = boardHC[idx];\n                int tmp = x - d;\n                if (tmp < 0) tmp += MOD;\n                boardHC[idx] = tmp;\n                scoreHC += tmp - x;\n            }\n            sol_ops[bestRemIdx] = sol_ops.back();\n            sol_ops.pop_back();\n        } else {\n            break;\n        }\n    }\n\n    // Extra random REPLACE hill-climb (only accept positive moves)\n    const int MAX_RR_TRIES = 200000;\n    int tries = 0;\n    while (tries < MAX_RR_TRIES) {\n        auto now = chrono::steady_clock::now();\n        double elapsed_total = chrono::duration<double>(now - global_start).count();\n        if (elapsed_total >= TOTAL_LIMIT) break;\n\n        int L = (int)sol_ops.size();\n        if (L == 0) break;\n\n        int idx_old = rng.next_int(L);\n        int op_old = sol_ops[idx_old];\n        int op_new = rng.next_int(NUM_OPS);\n        if (op_new == op_old) {\n            ++tries;\n            continue;\n        }\n\n        const auto &cellsOld = op_cells[op_old];\n        const auto &valsOld  = op_vals[op_old];\n        const auto &cellsNew = op_cells[op_new];\n        const auto &valsNew  = op_vals[op_new];\n        auto &posOldMap = op_pos[op_old];\n        auto &posNewMap = op_pos[op_new];\n\n        int idxList[18];\n        int uc = 0;\n        for (int t = 0; t < 9; ++t) idxList[uc++] = cellsOld[t];\n        for (int t = 0; t < 9; ++t) {\n            int idx = cellsNew[t];\n            bool found = false;\n            for (int z = 0; z < uc; ++z) {\n                if (idxList[z] == idx) { found = true; break; }\n            }\n            if (!found) idxList[uc++] = idx;\n        }\n\n        long long delta = 0;\n        for (int t = 0; t < uc; ++t) {\n            int idx = idxList[t];\n            int x = boardHC[idx];\n\n            int posOld = (int)posOldMap[idx];\n            int d_old = (posOld >= 0 ? valsOld[posOld] : 0);\n            int posNew = (int)posNewMap[idx];\n            int d_new = (posNew >= 0 ? valsNew[posNew] : 0);\n            int diff = d_new - d_old;\n            if (diff == 0) continue;\n\n            int tmp = x + diff;\n            if (tmp < 0) tmp += MOD;\n            else if (tmp >= MOD) tmp -= MOD;\n            delta += tmp - x;\n        }\n\n        if (delta > 0) {\n            // apply replace\n            for (int t = 0; t < uc; ++t) {\n                int idx = idxList[t];\n                int x = boardHC[idx];\n\n                int posOld = (int)posOldMap[idx];\n                int d_old = (posOld >= 0 ? valsOld[posOld] : 0);\n                int posNew = (int)posNewMap[idx];\n                int d_new = (posNew >= 0 ? valsNew[posNew] : 0);\n                int diff = d_new - d_old;\n                if (diff == 0) continue;\n\n                int tmp = x + diff;\n                if (tmp < 0) tmp += MOD;\n                else if (tmp >= MOD) tmp -= MOD;\n                boardHC[idx] = tmp;\n            }\n            scoreHC += delta;\n            sol_ops[idx_old] = op_new;\n            tries = 0; // reset since we improved\n        } else {\n            ++tries;\n        }\n    }\n\n    // Output final solution\n    cout << (int)sol_ops.size() << '\\n';\n    for (int op_id : sol_ops) {\n        const Op &op = all_ops[op_id];\n        cout << op.m << ' ' << op.p << ' ' << op.q << '\\n';\n    }\n\n    return 0;\n}","ahc033":"#include <bits/stdc++.h>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    if (!(cin >> N)) return 0; // N == 5\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    const int totalContainers = N * N; // 25\n\n    // For each container id, its receiving (spawn) row.\n    vector<int> spawnRow(totalContainers);\n    for (int r = 0; r < N; ++r) {\n        for (int j = 0; j < N; ++j) {\n            int id = A[r][j];\n            spawnRow[id] = r;\n        }\n    }\n\n    // Grid: -1 = empty, otherwise container id.\n    vector<vector<int>> grid(N, vector<int>(N, -1));\n\n    // Container states.\n    const int NOT_SPAWNED = 0, ON_GRID = 1, CARRIED = 2, DISPATCHED = 3;\n    vector<int> state(totalContainers, NOT_SPAWNED);\n\n    // Positions of containers when ON_GRID; (-1,-1) otherwise.\n    vector<int> posx(totalContainers, -1), posy(totalContainers, -1);\n\n    // Receiving gate spawn indices per row.\n    int next_idx[5] = {0, 0, 0, 0, 0};\n    bool spawn_done[5] = {false, false, false, false, false};\n\n    // Big crane (index 0).\n    int bx = 0, by = 0;    // position\n    int carry = -1;        // carried container id, -1 if none\n\n    // For each dispatch row r, next id to dispatch for that row.\n    int nextRowId[5];\n    for (int r = 0; r < N; ++r) nextRowId[r] = r * N;\n\n    // Operation strings for cranes.\n    vector<string> ops(N);\n\n    int dispatched_count = 0;\n\n    auto stepTowards = [&](int gx, int gy) -> char {\n        if (bx < gx) return 'D';\n        if (bx > gx) return 'U';\n        if (by < gy) return 'R';\n        if (by > gy) return 'L';\n        return '.';\n    };\n\n    const int MAX_TURNS = 10000;\n    for (int t = 0; t < MAX_TURNS && dispatched_count < totalContainers; ++t) {\n        // Step 1: spawn containers at receiving gates.\n        for (int r = 0; r < N; ++r) {\n            if (next_idx[r] < N &&\n                grid[r][0] == -1 &&\n                !(carry != -1 && bx == r && by == 0)) {\n                int id = A[r][next_idx[r]];\n                grid[r][0] = id;\n                state[id] = ON_GRID;\n                posx[id] = r;\n                posy[id] = 0;\n                ++next_idx[r];\n                if (next_idx[r] == N) spawn_done[r] = true;\n            }\n        }\n\n        // Step 2: decide big crane command.\n        char big_cmd = '.';\n\n        if (dispatched_count >= totalContainers) {\n            big_cmd = '.';\n        } else if (carry != -1) {\n            // Carrying some container.\n            int rc = carry / N;\n            if (carry == nextRowId[rc]) {\n                // This container is the next required for its row -> dispatch it.\n                int gx = rc;\n                int gy = N - 1;\n                if (bx == gx && by == gy) {\n                    big_cmd = 'Q';\n                } else {\n                    big_cmd = stepTowards(gx, gy);\n                }\n            } else {\n                // Not yet needed for its row -> store it.\n                int dr = carry / N;\n\n                // Prefer storing in dest row dr.\n                bool storedHere = false;\n                if (bx == dr && by >= 1 && by <= N - 2 && grid[bx][by] == -1) {\n                    // Already at an empty interior cell in dest row.\n                    big_cmd = 'Q';\n                    storedHere = true;\n                }\n\n                if (!storedHere) {\n                    int bestX = -1, bestY = -1;\n                    int bestDist = INT_MAX;\n\n                    // 1) Dest row interior cells (dr,1..3).\n                    for (int y = 1; y <= N - 2; ++y) {\n                        if (grid[dr][y] == -1) {\n                            int dist = abs(bx - dr) + abs(by - y);\n                            if (dist < bestDist) {\n                                bestDist = dist;\n                                bestX = dr;\n                                bestY = y;\n                            }\n                        }\n                    }\n                    // 2) Dest row gate (dr,0) if spawn is done.\n                    if (spawn_done[dr] && grid[dr][0] == -1) {\n                        int dist = abs(bx - dr) + abs(by - 0);\n                        if (dist < bestDist) {\n                            bestDist = dist;\n                            bestX = dr;\n                            bestY = 0;\n                        }\n                    }\n\n                    if (bestX != -1) {\n                        // We found a destination-row storage spot.\n                        if (bx == bestX && by == bestY) {\n                            big_cmd = 'Q';\n                        } else {\n                            big_cmd = stepTowards(bestX, bestY);\n                        }\n                    } else {\n                        // No dest-row spot; fallback to global interior / finished gates.\n                        bool canStoreHere = (by >= 1 && by <= N - 2 && grid[bx][by] == -1);\n                        if (canStoreHere) {\n                            big_cmd = 'Q';\n                        } else {\n                            int gX = -1, gY = -1;\n                            int gDist = INT_MAX;\n\n                            // Global interior cells.\n                            for (int x = 0; x < N; ++x) {\n                                for (int y = 1; y <= N - 2; ++y) {\n                                    if (grid[x][y] == -1) {\n                                        int dist = abs(bx - x) + abs(by - y);\n                                        if (dist < gDist) {\n                                            gDist = dist;\n                                            gX = x; gY = y;\n                                        }\n                                    }\n                                }\n                            }\n                            // Gates of rows whose spawn is done.\n                            for (int x = 0; x < N; ++x) {\n                                if (spawn_done[x] && grid[x][0] == -1) {\n                                    int dist = abs(bx - x) + abs(by - 0);\n                                    if (dist < gDist) {\n                                        gDist = dist;\n                                        gX = x; gY = 0;\n                                    }\n                                }\n                            }\n\n                            if (gX != -1) {\n                                if (bx == gX && by == gY) {\n                                    big_cmd = 'Q';\n                                } else {\n                                    big_cmd = stepTowards(gX, gY);\n                                }\n                            } else {\n                                // Extremely unlikely: no place to store, just idle.\n                                big_cmd = '.';\n                            }\n                        }\n                    }\n                }\n            }\n        } else {\n            // Not carrying: choose best next target among rows.\n            int bestId = -1;\n            int bestCost = INT_MAX;\n\n            for (int r = 0; r < N; ++r) {\n                // Ensure nextRowId[r] is not behind (safety).\n                while (nextRowId[r] < (r + 1) * N &&\n                       state[nextRowId[r]] == DISPATCHED) {\n                    ++nextRowId[r];\n                }\n                int id = nextRowId[r];\n                if (id >= (r + 1) * N) continue; // row r done\n\n                if (state[id] == ON_GRID) {\n                    int cx = posx[id], cy = posy[id];\n                    if (cx == -1) continue; // safety\n                    int dist = abs(bx - cx) + abs(by - cy);\n                    int cost = dist; // ON_GRID preferred (no penalty)\n                    if (cost < bestCost) {\n                        bestCost = cost;\n                        bestId = id;\n                    }\n                } else if (state[id] == NOT_SPAWNED) {\n                    int sr = spawnRow[id];\n                    int distGate = abs(bx - sr) + abs(by - 0);\n                    // Large penalty to prefer ON_GRID containers first.\n                    int extra = 20;\n                    int cost = distGate + extra;\n                    if (cost < bestCost) {\n                        bestCost = cost;\n                        bestId = id;\n                    }\n                }\n                // CARRIED case should not happen here.\n            }\n\n            if (bestId == -1) {\n                big_cmd = '.';\n            } else if (state[bestId] == ON_GRID) {\n                int cx = posx[bestId], cy = posy[bestId];\n                if (bx == cx && by == cy) {\n                    big_cmd = 'P';\n                } else {\n                    big_cmd = stepTowards(cx, cy);\n                }\n            } else if (state[bestId] == NOT_SPAWNED) {\n                int sr = spawnRow[bestId];\n                if (grid[sr][0] != -1) {\n                    // Clear blocking container from its gate.\n                    if (bx == sr && by == 0) {\n                        big_cmd = 'P';\n                    } else {\n                        big_cmd = stepTowards(sr, 0);\n                    }\n                } else {\n                    // Gate empty but id not spawned yet: move to gate and wait.\n                    if (bx == sr && by == 0) {\n                        big_cmd = '.';\n                    } else {\n                        big_cmd = stepTowards(sr, 0);\n                    }\n                }\n            } else {\n                big_cmd = '.';\n            }\n        }\n\n        // Small cranes: bomb at t=0, then idle.\n        char small_cmd = (t == 0 ? 'B' : '.');\n        ops[0].push_back(big_cmd);\n        for (int i = 1; i < N; ++i) ops[i].push_back(small_cmd);\n\n        // Apply big crane action.\n        if (big_cmd == 'P') {\n            if (carry == -1 && grid[bx][by] != -1) {\n                carry = grid[bx][by];\n                state[carry] = CARRIED;\n                posx[carry] = -1;\n                posy[carry] = -1;\n                grid[bx][by] = -1;\n            }\n        } else if (big_cmd == 'Q') {\n            if (carry != -1 && grid[bx][by] == -1) {\n                grid[bx][by] = carry;\n                state[carry] = ON_GRID;\n                posx[carry] = bx;\n                posy[carry] = by;\n                carry = -1;\n            }\n        } else if (big_cmd == 'U') {\n            if (bx > 0) --bx;\n        } else if (big_cmd == 'D') {\n            if (bx < N - 1) ++bx;\n        } else if (big_cmd == 'L') {\n            if (by > 0) --by;\n        } else if (big_cmd == 'R') {\n            if (by < N - 1) ++by;\n        } else {\n            // '.', 'B' for big crane: no movement.\n        }\n\n        // Step 3: dispatch containers at right edge.\n        for (int i = 0; i < N; ++i) {\n            int &cell = grid[i][N - 1];\n            if (cell != -1) {\n                int id = cell;\n                cell = -1;\n                state[id] = DISPATCHED;\n                posx[id] = -1;\n                posy[id] = -1;\n                ++dispatched_count;\n                int r = id / N;\n                if (nextRowId[r] == id) {\n                    ++nextRowId[r];\n                }\n            }\n        }\n    }\n\n    // Output operation strings.\n    for (int i = 0; i < N; ++i) {\n        cout << ops[i] << '\\n';\n    }\n\n    return 0;\n}","ahc034":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int MAXN = 20;\nconst int TOT_LIMIT = 100000;\n// Leave room for fallback (~<2000 ops)\nconst int LIMIT_GREEDY = TOT_LIMIT - 2000;\n\nint N;\nlong long h[MAXN][MAXN];         // mutable heights\nlong long orig_h[MAXN][MAXN];    // original heights (for potential)\nlong long negPotential[MAXN][MAXN]; // precomputed negative potential around each cell\n\nvector<string> ops;\n\nint cur_r = 0, cur_c = 0;  // current truck position\nlong long load_truck = 0;  // current truck load\nlong long base_total = 0;  // sum of |h[i][j]|, used in greedy\n\nvector<pair<int,int>> snakePath;\n\n// ----------------------------------------------------------------------\n// Build snake Hamiltonian path for fallback (row-wise snake)\n// ----------------------------------------------------------------------\nvoid buildSnakePath() {\n    snakePath.clear();\n    snakePath.reserve(MAXN * MAXN);\n    for (int i = 0; i < N; ++i) {\n        if (i % 2 == 0) {\n            for (int j = 0; j < N; ++j) {\n                snakePath.emplace_back(i, j);\n            }\n        } else {\n            for (int j = N - 1; j >= 0; --j) {\n                snakePath.emplace_back(i, j);\n            }\n        }\n    }\n}\n\n// ----------------------------------------------------------------------\n// Precompute negative potential: for each cell (i,j), sum of nearby\n// negative deficits within a small radius R, using original heights.\n// This is static heuristic information to guide where to go when empty.\n// ----------------------------------------------------------------------\nvoid precomputeNegPotential() {\n    const int R = 6; // radius for local negative potential\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            long long sum = 0;\n            for (int di = -R; di <= R; ++di) {\n                int ni = i + di;\n                if (ni < 0 || ni >= N) continue;\n                int rem = R - abs(di);\n                int cj1 = max(0, j - rem);\n                int cj2 = min(N - 1, j + rem);\n                for (int nj = cj1; nj <= cj2; ++nj) {\n                    long long v = orig_h[ni][nj];\n                    if (v < 0) sum += -v;\n                }\n            }\n            negPotential[i][j] = sum;\n        }\n    }\n}\n\n// ----------------------------------------------------------------------\n// Basic movement: move step-by-step (no opportunistic loading/unloading)\n// Used in fallback and when truck is empty in greedy.\n// ----------------------------------------------------------------------\nvoid move_to_basic(int tr, int tc) {\n    while (cur_r < tr) {\n        ++cur_r;\n        ops.emplace_back(\"D\");\n    }\n    while (cur_r > tr) {\n        --cur_r;\n        ops.emplace_back(\"U\");\n    }\n    while (cur_c < tc) {\n        ++cur_c;\n        ops.emplace_back(\"R\");\n    }\n    while (cur_c > tc) {\n        --cur_c;\n        ops.emplace_back(\"L\");\n    }\n}\n\n// ----------------------------------------------------------------------\n// Movement when loaded in greedy phase: choose between two shortest\n// Manhattan paths (vertical-then-horizontal vs horizontal-then-vertical)\n// based on how much negative capacity they pass, then traverse that path\n// and opportunistically unload into negative cells along the way.\n// ----------------------------------------------------------------------\nvoid move_to_loaded(int tr, int tc) {\n    int r0 = cur_r, c0 = cur_c;\n    int dr = tr - r0;\n    int dc = tc - c0;\n\n    vector<char> path1, path2;\n    path1.reserve(abs(dr) + abs(dc));\n    path2.reserve(abs(dr) + abs(dc));\n\n    // Path1: vertical first, then horizontal\n    if (dr > 0) for (int k = 0; k < dr; ++k) path1.push_back('D');\n    else       for (int k = 0; k < -dr; ++k) path1.push_back('U');\n    if (dc > 0) for (int k = 0; k < dc; ++k) path1.push_back('R');\n    else        for (int k = 0; k < -dc; ++k) path1.push_back('L');\n\n    // Path2: horizontal first, then vertical\n    if (dc > 0) for (int k = 0; k < dc; ++k) path2.push_back('R');\n    else        for (int k = 0; k < -dc; ++k) path2.push_back('L');\n    if (dr > 0) for (int k = 0; k < dr; ++k) path2.push_back('D');\n    else       for (int k = 0; k < -dr; ++k) path2.push_back('U');\n\n    auto eval_path = [&](const vector<char>& path) -> long long {\n        int r = r0, c = c0;\n        long long rem = load_truck;\n        long long sum_unload = 0;\n        for (char ch : path) {\n            if (ch == 'D') ++r;\n            else if (ch == 'U') --r;\n            else if (ch == 'R') ++c;\n            else --c;\n            if (rem <= 0) continue;\n            long long v = h[r][c];\n            if (v < 0) {\n                long long need = -v;\n                long long d = min(rem, need);\n                sum_unload += d;\n                rem -= d;\n                if (rem == 0) break;\n            }\n        }\n        return sum_unload;\n    };\n\n    long long s1 = eval_path(path1);\n    long long s2 = eval_path(path2);\n    const vector<char>& best = (s2 > s1 ? path2 : path1);\n\n    for (char ch : best) {\n        if (ch == 'D') { ++cur_r; ops.emplace_back(\"D\"); }\n        else if (ch == 'U') { --cur_r; ops.emplace_back(\"U\"); }\n        else if (ch == 'R') { ++cur_c; ops.emplace_back(\"R\"); }\n        else { --cur_c; ops.emplace_back(\"L\"); }\n\n        if (load_truck > 0) {\n            long long v = h[cur_r][cur_c];\n            if (v < 0) {\n                long long need = -v;\n                long long d = min(load_truck, need);\n                if (d > 0) {\n                    ops.emplace_back(\"-\" + to_string(d));\n                    load_truck -= d;\n                    h[cur_r][cur_c] += d;\n                    base_total -= d; // |h| decreases by d\n                }\n            }\n        }\n    }\n}\n\n// ----------------------------------------------------------------------\n// Find positive cell to load from when truck is empty.\n// Uses a heuristic that balances distance from current truck position\n// and precomputed local negative potential.\n// We minimize metric = 200 * distance - negPotential[i][j].\n// Tie-break by smaller distance, then larger h[i][j].\n// ----------------------------------------------------------------------\npair<int,int> findPositiveAdvanced() {\n    int bestR = -1, bestC = -1;\n    long long bestMetric = (1LL << 60);\n    int bestd = INT_MAX;\n    long long bestVal = -1;\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            long long v = h[i][j];\n            if (v <= 0) continue;\n            int d = abs(i - cur_r) + abs(j - cur_c);\n            long long metric = 200LL * d - negPotential[i][j]; // tune weights\n\n            if (metric < bestMetric ||\n                (metric == bestMetric &&\n                 (d < bestd || (d == bestd && v > bestVal)))) {\n                bestMetric = metric;\n                bestd = d;\n                bestVal = v;\n                bestR = i;\n                bestC = j;\n            }\n        }\n    }\n    return {bestR, bestC};\n}\n\n// ----------------------------------------------------------------------\n// Find nearest negative cell from current position (for truck with load).\n// Minimize Manhattan distance, tie-break by larger |h|.\n// ----------------------------------------------------------------------\npair<int,int> findNearestNegative() {\n    int bestR = -1, bestC = -1;\n    int bestd = INT_MAX;\n    long long bestVal = -1;\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            long long v = h[i][j];\n            if (v >= 0) continue;\n            int d = abs(i - cur_r) + abs(j - cur_c);\n            long long absV = -v;\n            if (d < bestd || (d == bestd && absV > bestVal)) {\n                bestd = d;\n                bestVal = absV;\n                bestR = i;\n                bestC = j;\n            }\n        }\n    }\n    return {bestR, bestC};\n}\n\n// ----------------------------------------------------------------------\n// Stage 1: Greedy shipping between positives and negatives\n// - When empty: go to positive chosen by Advanced heuristic\n// - When loaded: go to nearest negative, with opportunistic unloading\n// ----------------------------------------------------------------------\nvoid greedy_phase() {\n    base_total = 0;\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            base_total += llabs(h[i][j]);\n\n    while (base_total > 0 && (int)ops.size() < LIMIT_GREEDY) {\n        if (load_truck == 0) {\n            auto [pr, pc] = findPositiveAdvanced();\n            if (pr == -1) break; // no positive, but base_total>0 => should not happen\n            move_to_basic(pr, pc);\n\n            long long v = h[pr][pc];\n            if (v > 0) {\n                long long d = v;\n                ops.emplace_back(\"+\" + to_string(d));\n                load_truck += d;\n                h[pr][pc] = 0;\n                base_total -= d;\n            }\n        } else {\n            auto [nr, nc] = findNearestNegative();\n            if (nr == -1) break; // no negative but load>0 => inconsistent\n            move_to_loaded(nr, nc);\n\n            long long v = h[nr][nc];\n            if (v < 0 && load_truck > 0) {\n                long long need = -v;\n                long long d = min(load_truck, need);\n                if (d > 0) {\n                    ops.emplace_back(\"-\" + to_string(d));\n                    load_truck -= d;\n                    h[nr][nc] += d;\n                    base_total -= d;\n                }\n            }\n        }\n    }\n}\n\n// ----------------------------------------------------------------------\n// Stage 2: fallback using two-pass snake sweep to guarantee completion\n// ----------------------------------------------------------------------\nvoid fallback_snake() {\n    // Unload any remaining load at current cell\n    if (load_truck > 0) {\n        ops.emplace_back(\"-\" + to_string(load_truck));\n        h[cur_r][cur_c] += load_truck;\n        load_truck = 0;\n    }\n\n    // Move to (0,0), the start of snakePath\n    move_to_basic(0, 0);\n\n    int M = (int)snakePath.size();\n\n    // Forward pass\n    for (int idx = 0; idx < M; ++idx) {\n        int r = snakePath[idx].first;\n        int c = snakePath[idx].second;\n        move_to_basic(r, c);\n\n        long long v = h[r][c];\n        if (v > 0) {\n            long long d = v;\n            ops.emplace_back(\"+\" + to_string(d));\n            load_truck += d;\n            h[r][c] = 0;\n        } else if (v < 0 && load_truck > 0) {\n            long long need = -v;\n            long long d = min(load_truck, need);\n            ops.emplace_back(\"-\" + to_string(d));\n            load_truck -= d;\n            h[r][c] += d;\n        }\n    }\n\n    // Backward pass\n    for (int idx = M - 1; idx >= 0; --idx) {\n        int r = snakePath[idx].first;\n        int c = snakePath[idx].second;\n        move_to_basic(r, c);\n\n        long long v = h[r][c];\n        if (v < 0 && load_truck > 0) {\n            long long need = -v;\n            long long d = min(load_truck, need);\n            ops.emplace_back(\"-\" + to_string(d));\n            load_truck -= d;\n            h[r][c] += d;\n        }\n    }\n    // After this, by conservation, all heights should be zero and load_truck == 0.\n}\n\n// ----------------------------------------------------------------------\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    if (!(cin >> N)) return 0;\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j) {\n            cin >> h[i][j];\n            orig_h[i][j] = h[i][j];\n        }\n\n    precomputeNegPotential();\n    buildSnakePath();\n\n    cur_r = 0;\n    cur_c = 0;\n    load_truck = 0;\n    ops.clear();\n\n    greedy_phase();\n\n    // Check if everything is leveled\n    bool all_zero = true;\n    for (int i = 0; i < N && all_zero; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (h[i][j] != 0) {\n                all_zero = false;\n                break;\n            }\n        }\n    }\n\n    // If greedy didn't finish, use fallback snake\n    if (!all_zero && (int)ops.size() < TOT_LIMIT) {\n        fallback_snake();\n    }\n\n    // Absolute safety: never output more than 100000 operations\n    if ((int)ops.size() > TOT_LIMIT) {\n        ops.resize(TOT_LIMIT);\n    }\n\n    for (const string &s : ops) {\n        cout << s << '\\n';\n    }\n    return 0;\n}","ahc035":"#include <bits/stdc++.h>\nusing namespace std;\n\n/*\nHeuristic strategy with dimension-weighted synergy and SA:\n\n- N=6, M=15, T=10 fixed.\n- Seed count per generation: S = 2*N*(N-1) = 60.\n- Each turn:\n  1) Compute normalized scores using global per-dim maxima from initial seeds.\n  2) Compute current per-dim maxima Y_l over this generation.\n     Define per-dimension weights:\n        w_l = 1 + ALPHA * (1 - Y_l / X_l)\n     so under-saturated dimensions get higher weight.\n  3) Compute pairwise \"synergy\" for all seeds:\n       S(a,b) = sum_l w_l * max(x_a_l, x_b_l) / X_l.\n  4) Select 36 seeds:\n       - Dimension champions (best for each dimension).\n       - Then greedily add seeds using a score:\n           score(k) = normV[k] + \u03bb * avg_synergy_to_selected(k)\n         (\u03bb ~ 0.35).\n  5) Among the 36 selected seeds, compute \"centrality\":\n       cent(s) = avg synergy to other selected seeds.\n     Order seeds by:\n       normV[s] + \u03b3 * cent(s) + champion_bonus (if s is a dimension champion)\n     (\u03b3 ~ 0.45, champion_bonus ~ 0.25).\n  6) Greedy initial placement:\n       - Positions sorted by degree (center > edge > corner).\n       - Place seeds in the above order to positions maximizing incremental synergy.\n  7) Simulated annealing on the placement:\n       - Objective = sum_edge synergy(arr[u], arr[v]) (synergy-only objective).\n       - Random swaps with Metropolis acceptance.\n       - 300,000 iterations per turn, temperature from 0.8 down to 0.01.\n       - Track best arrangement encountered.\n  8) Output arrangement, then read next generation seeds.\n*/\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, T;\n    if (!(cin >> N >> M >> T)) return 0;\n\n    const int SEED_COUNT = 2 * N * (N - 1); // 60 for N=6\n    const int SZ = N * N;                   // 36 for N=6\n    const int MAXS = 60;                    // max seed count\n\n    // Current seeds: x[k][l]\n    vector<vector<int>> x(SEED_COUNT, vector<int>(M));\n    for (int i = 0; i < SEED_COUNT; i++) {\n        for (int l = 0; l < M; l++) cin >> x[i][l];\n    }\n\n    // Global per-dimension maxima from initial seeds\n    vector<int> X_global(M, 0);\n    for (int l = 0; l < M; l++) {\n        int mx = 0;\n        for (int i = 0; i < SEED_COUNT; i++) {\n            mx = max(mx, x[i][l]);\n        }\n        X_global[l] = mx;\n    }\n\n    // Active dimensions (those with X_global[l] > 0, to avoid division by zero)\n    vector<int> active_dims;\n    active_dims.reserve(M);\n    for (int l = 0; l < M; l++) {\n        if (X_global[l] > 0) active_dims.push_back(l);\n    }\n\n    // Precompute grid adjacency (neighbors) and edges\n    vector<vector<int>> neighbors(SZ);\n    vector<pair<int,int>> edges;\n    edges.reserve(2 * N * (N - 1));\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            int pos = i * N + j;\n            if (j + 1 < N) {\n                int q = pos + 1;\n                edges.emplace_back(pos, q);\n                neighbors[pos].push_back(q);\n                neighbors[q].push_back(pos);\n            }\n            if (i + 1 < N) {\n                int q = pos + N;\n                edges.emplace_back(pos, q);\n                neighbors[pos].push_back(q);\n                neighbors[q].push_back(pos);\n            }\n        }\n    }\n\n    // Positions sorted by degree (center > edge > corner)\n    vector<int> pos_by_deg(SZ);\n    iota(pos_by_deg.begin(), pos_by_deg.end(), 0);\n    sort(pos_by_deg.begin(), pos_by_deg.end(), [&](int a, int b) {\n        if (neighbors[a].size() != neighbors[b].size())\n            return neighbors[a].size() > neighbors[b].size();\n        return a < b;\n    });\n\n    // Simple xorshift RNG (deterministic)\n    uint64_t rng_state = 88172645463325252ull;\n    auto rng = [&]() -> uint64_t {\n        rng_state ^= (rng_state << 7);\n        rng_state ^= (rng_state >> 9);\n        return rng_state;\n    };\n    auto rand01 = [&]() -> double {\n        // 53-bit precision uniform in [0,1)\n        return (rng() >> 11) * (1.0 / (1ULL << 53));\n    };\n\n    // Normalized total scores per seed\n    vector<double> normV(SEED_COUNT);\n\n    // Synergy matrix (pairwise)\n    static double synergy[MAXS][MAXS];\n\n    // Dimension weights updated each turn\n    vector<double> dim_weight(M, 1.0);\n\n    const double ALPHA  = 0.7;   // dimension-under-saturation weight\n    const double LAMBDA = 0.35;  // weight for synergy in selection\n    const double GAMMA  = 0.45;  // weight for synergy centrality in ordering\n    const double CH_BONUS = 0.25;// bonus in ordering for dimension champions\n\n    const int ITER = 300000;     // SA iterations per turn\n    const double T0 = 0.8;\n    const double T1 = 0.01;\n    const double INV_ITER = 1.0 / (double)ITER;\n\n    for (int turn = 0; turn < T; turn++) {\n        // 1. Compute normalized total score for each seed\n        for (int k = 0; k < SEED_COUNT; k++) {\n            double s = 0.0;\n            for (int idx = 0; idx < (int)active_dims.size(); idx++) {\n                int l = active_dims[idx];\n                s += (double)x[k][l] / (double)X_global[l];\n            }\n            normV[k] = s;\n        }\n\n        // 2. Compute current per-dim maxima Y_l and dimension weights\n        vector<int> Y(M, 0);\n        for (int l = 0; l < M; l++) {\n            int mx = 0;\n            for (int k = 0; k < SEED_COUNT; k++) {\n                mx = max(mx, x[k][l]);\n            }\n            Y[l] = mx;\n        }\n        for (int l = 0; l < M; l++) {\n            if (X_global[l] <= 0) {\n                dim_weight[l] = 1.0;\n            } else {\n                double ratio = (double)Y[l] / (double)X_global[l]; // 0..1\n                dim_weight[l] = 1.0 + ALPHA * (1.0 - ratio);\n            }\n        }\n\n        // 3. Compute synergy matrix for all seeds using dim_weight\n        for (int i = 0; i < SEED_COUNT; i++) {\n            synergy[i][i] = 0.0;\n            for (int j = i + 1; j < SEED_COUNT; j++) {\n                double s = 0.0;\n                for (int idx = 0; idx < (int)active_dims.size(); idx++) {\n                    int l = active_dims[idx];\n                    double w = dim_weight[l];\n                    s += w * (double)max(x[i][l], x[j][l]) / (double)X_global[l];\n                }\n                synergy[i][j] = synergy[j][i] = s;\n            }\n        }\n\n        // 4. Select 36 seeds: dimension champions + synergy-guided greedy fill\n        vector<int> selected;\n        selected.reserve(SZ);\n        vector<char> used(SEED_COUNT, 0);\n        vector<char> isChampion(SEED_COUNT, 0);\n\n        // 4-1. Dimension champions\n        for (int idx = 0; idx < (int)active_dims.size(); idx++) {\n            int l = active_dims[idx];\n            int best = -1;\n            int bestVal = -1;\n            double bestNorm = -1.0;\n            for (int k = 0; k < SEED_COUNT; k++) {\n                int v = x[k][l];\n                if (v > bestVal || (v == bestVal && normV[k] > bestNorm)) {\n                    bestVal = v;\n                    bestNorm = normV[k];\n                    best = k;\n                }\n            }\n            if (best != -1 && !used[best]) {\n                used[best] = 1;\n                isChampion[best] = 1;\n                selected.push_back(best);\n                if ((int)selected.size() == SZ) break;\n            }\n        }\n\n        // 4-2. Greedy fill with synergy-based score\n        while ((int)selected.size() < SZ) {\n            int bestK = -1;\n            double bestScore = -1e100;\n\n            for (int k = 0; k < SEED_COUNT; k++) {\n                if (used[k]) continue;\n                double avgSyn = 0.0;\n                if (!selected.empty()) {\n                    double sumSyn = 0.0;\n                    for (int s : selected) sumSyn += synergy[k][s];\n                    avgSyn = sumSyn / (double)selected.size();\n                }\n                double score = normV[k] + LAMBDA * avgSyn;\n                if (score > bestScore) {\n                    bestScore = score;\n                    bestK = k;\n                }\n            }\n            if (bestK == -1) {\n                // Fallback: pick any unused seed\n                for (int k = 0; k < SEED_COUNT; k++) {\n                    if (!used[k]) {\n                        bestK = k;\n                        break;\n                    }\n                }\n                if (bestK == -1) break; // should not happen\n            }\n            used[bestK] = 1;\n            selected.push_back(bestK);\n        }\n\n        // 5. Compute centrality for selected seeds (within the selected set)\n        vector<double> cent(SZ);\n        for (int i = 0; i < SZ; i++) {\n            double s = 0.0;\n            for (int j = 0; j < SZ; j++) {\n                if (i == j) continue;\n                s += synergy[selected[i]][selected[j]];\n            }\n            cent[i] = s / max(1, SZ - 1);\n        }\n\n        // 6. Order selected seeds for placement:\n        //    by normV + GAMMA * centrality + CH_BONUS if champion\n        vector<int> seed_order(SZ);\n        iota(seed_order.begin(), seed_order.end(), 0);\n        sort(seed_order.begin(), seed_order.end(), [&](int a, int b) {\n            double sa = normV[selected[a]] + GAMMA * cent[a]\n                        + (isChampion[selected[a]] ? CH_BONUS : 0.0);\n            double sb = normV[selected[b]] + GAMMA * cent[b]\n                        + (isChampion[selected[b]] ? CH_BONUS : 0.0);\n            if (sa != sb) return sa > sb;\n            return selected[a] < selected[b];\n        });\n\n        // 7. Greedy initial placement:\n        //    Put seeds in \"seed_order\" into positions \"pos_by_deg\"\n        //    maximizing incremental synergy.\n        vector<int> pos_to_seed(SZ, -1);\n        for (int idx = 0; idx < SZ; idx++) {\n            int seed_id = selected[seed_order[idx]]; // actual seed index\n            int bestPos = -1;\n            double bestInc = -1e100;\n\n            for (int pos : pos_by_deg) {\n                if (pos_to_seed[pos] != -1) continue;\n                double inc = 0.0;\n                for (int nb : neighbors[pos]) {\n                    if (pos_to_seed[nb] != -1) {\n                        int nbSeed = pos_to_seed[nb];\n                        inc += synergy[seed_id][nbSeed];\n                    }\n                }\n                if (inc > bestInc + 1e-9 ||\n                    (fabs(inc - bestInc) <= 1e-9 &&\n                     neighbors[pos].size() >\n                        (bestPos == -1 ? -1 : (int)neighbors[bestPos].size()))) {\n                    bestInc = inc;\n                    bestPos = pos;\n                }\n            }\n            if (bestPos == -1) bestPos = pos_by_deg[0]; // fallback (should not happen)\n            pos_to_seed[bestPos] = seed_id;\n        }\n\n        // Current arrangement: arr[pos] = seed index\n        vector<int> arr = pos_to_seed;\n\n        // Compute initial total synergy score (objective)\n        double cur_score = 0.0;\n        for (auto &e : edges) {\n            cur_score += synergy[arr[e.first]][arr[e.second]];\n        }\n\n        // Prepare for SA: track best arrangement\n        vector<int> best_arr = arr;\n        double best_score = cur_score;\n\n        // 8. Simulated annealing to improve placement (synergy-only objective)\n        for (int it = 0; it < ITER; it++) {\n            int p1 = (int)(rng() % SZ);\n            int p2 = (int)(rng() % SZ);\n            if (p1 == p2) continue;\n\n            int s1 = arr[p1];\n            int s2 = arr[p2];\n            if (s1 == s2) continue;\n\n            double delta = 0.0;\n\n            // Edges incident to p1 (excluding p2)\n            for (int nb : neighbors[p1]) {\n                if (nb == p2) continue; // edge (p1,p2) symmetric, no net change\n                int s_nb = arr[nb];\n                delta -= synergy[s1][s_nb];\n                delta += synergy[s2][s_nb];\n            }\n            // Edges incident to p2 (excluding p1)\n            for (int nb : neighbors[p2]) {\n                if (nb == p1) continue;\n                int s_nb = arr[nb];\n                delta -= synergy[s2][s_nb];\n                delta += synergy[s1][s_nb];\n            }\n\n            bool accept = false;\n            if (delta >= 0.0) {\n                accept = true;\n            } else {\n                double T = T0 + (T1 - T0) * (double)it * INV_ITER;\n                double prob = exp(delta / T); // delta < 0\n                if (rand01() < prob) accept = true;\n            }\n\n            if (accept) {\n                cur_score += delta;\n                swap(arr[p1], arr[p2]);\n                if (cur_score > best_score) {\n                    best_score = cur_score;\n                    best_arr = arr;\n                }\n            }\n        }\n\n        // Use best arrangement found\n        arr = best_arr;\n\n        // 9. Output arrangement for this turn\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                if (j) cout << ' ';\n                cout << arr[i * N + j];\n            }\n            cout << '\\n';\n        }\n        cout.flush();\n\n        // 10. Read next generation seeds\n        if (turn + 1 < T) {\n            for (int i = 0; i < SEED_COUNT; i++) {\n                for (int l = 0; l < M; l++) {\n                    cin >> x[i][l];\n                }\n            }\n        } else {\n            // For completeness, also attempt to read final seeds if provided\n            for (int i = 0; i < SEED_COUNT; i++) {\n                for (int l = 0; l < M; l++) {\n                    int tmp;\n                    if (!(cin >> tmp)) {\n                        break;\n                    }\n                }\n            }\n        }\n    }\n\n    return 0;\n}","ahc038":"#include <bits/stdc++.h>\nusing namespace std;\n\n// Directions: 0=Right, 1=Down, 2=Left, 3=Up\nconst int DX[4] = {0, 1, 0, -1};\nconst int DY[4] = {1, 0, -1, 0};\n\n// Hungarian algorithm for square cost matrix (minimization).\n// Returns assignment: match[i] = j (0-based), minimizing sum cost[i][match[i]].\nvector<int> hungarian(const vector<vector<int>>& a) {\n    int n = (int)a.size();\n    const int INF = 1e9;\n    vector<int> u(n + 1), v(n + 1), p(n + 1), way(n + 1);\n\n    for (int i = 1; i <= n; i++) {\n        p[0] = i;\n        int j0 = 0;\n        vector<int> minv(n + 1, INF);\n        vector<char> used(n + 1, false);\n        do {\n            used[j0] = true;\n            int i0 = p[j0];\n            int delta = INF, j1 = 0;\n            for (int j = 1; j <= n; j++) if (!used[j]) {\n                int cur = a[i0 - 1][j - 1] - u[i0] - v[j];\n                if (cur < minv[j]) {\n                    minv[j] = cur;\n                    way[j] = j0;\n                }\n                if (minv[j] < delta) {\n                    delta = minv[j];\n                    j1 = j;\n                }\n            }\n            for (int j = 0; j <= n; j++) {\n                if (used[j]) {\n                    u[p[j]] += delta;\n                    v[j]     -= delta;\n                } else {\n                    minv[j]  -= delta;\n                }\n            }\n            j0 = j1;\n        } while (p[j0] != 0);\n        do {\n            int j1 = way[j0];\n            p[j0]  = p[j1];\n            j0     = j1;\n        } while (j0);\n    }\n\n    vector<int> match(n);\n    for (int j = 1; j <= n; j++) {\n        if (p[j] > 0) match[p[j] - 1] = j - 1;\n    }\n    return match;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, V;\n    if (!(cin >> N >> M >> V)) return 0;\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    // Current takoyaki occupancy\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            if (s[i][j] == '1') occ[i][j] = 1;\n        }\n    }\n\n    // Collect mismatched cells\n    vector<pair<int,int>> sources; // s=1, t=0\n    vector<pair<int,int>> targets; // s=0, t=1\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (s[i][j] == '1' && t[i][j] == '0') {\n                sources.emplace_back(i, j);\n            } else if (s[i][j] == '0' && t[i][j] == '1') {\n                targets.emplace_back(i, j);\n            }\n        }\n    }\n    int K = (int)sources.size(); // number of pairs\n\n    // Arm: 2 vertices: 0=root, 1=fingertip, length 1\n    const int Vp = 2;\n    const int fingerVertex = 1; // fingertip id\n\n    struct PairInfo {\n        int sx, sy;\n        int tx, ty;\n    };\n    vector<PairInfo> pairs;\n\n    // Choose a good initial root position: center-of-mass of all mismatched cells.\n    int rootX = 0, rootY = 0;\n    if (K > 0) {\n        long long sumX = 0, sumY = 0;\n        for (auto &p : sources) {\n            sumX += p.first;\n            sumY += p.second;\n        }\n        for (auto &p : targets) {\n            sumX += p.first;\n            sumY += p.second;\n        }\n        int cnt = 2 * K;\n        double avgX = (double)sumX / cnt;\n        double avgY = (double)sumY / cnt;\n        rootX = max(0, min(N - 1, (int)llround(avgX)));\n        rootY = max(0, min(N - 1, (int)llround(avgY)));\n    }\n    int initRootX = rootX, initRootY = rootY;\n\n    if (K > 0) {\n        vector<int> matchT(K, -1);\n\n        if (K <= 150) {\n            // Use optimal Hungarian assignment for small K.\n            vector<vector<int>> costST(K, vector<int>(K));\n            for (int i = 0; i < K; i++) {\n                for (int j = 0; j < K; j++) {\n                    costST[i][j] = abs(sources[i].first - targets[j].first)\n                                 + abs(sources[i].second - targets[j].second);\n                }\n            }\n            matchT = hungarian(costST);\n        } else {\n            // Precompute distances and all edges for greedy global matching\n            vector<vector<int>> dist(K, vector<int>(K));\n            struct Edge {\n                int d, i, j;\n            };\n            vector<Edge> edges;\n            edges.reserve(K * K);\n\n            for (int i = 0; i < K; i++) {\n                for (int j = 0; j < K; j++) {\n                    int d = abs(sources[i].first - targets[j].first)\n                          + abs(sources[i].second - targets[j].second);\n                    dist[i][j] = d;\n                    edges.push_back({d, i, j});\n                }\n            }\n\n            // Sort edges by distance\n            sort(edges.begin(), edges.end(), [](const Edge &a, const Edge &b) {\n                return a.d < b.d;\n            });\n\n            // Global greedy matching using sorted edges\n            vector<char> usedS(K, 0), usedT(K, 0);\n            int matched = 0;\n            for (const auto &e : edges) {\n                int i = e.i, j = e.j;\n                if (!usedS[i] && !usedT[j]) {\n                    usedS[i] = usedT[j] = 1;\n                    matchT[i] = j;\n                    if (++matched == K) break;\n                }\n            }\n\n            // Local improvement on matching: try swapping targets of pairs (i, j)\n            if (K >= 2) {\n                int maxPass;\n                if (K <= 80) maxPass = 8;\n                else if (K <= 200) maxPass = 5;\n                else maxPass = 3;\n\n                for (int pass = 0; pass < maxPass; pass++) {\n                    bool improved = false;\n                    for (int i = 0; i < K; i++) {\n                        int a = matchT[i];\n                        for (int j = i + 1; j < K; j++) {\n                            int b = matchT[j];\n                            int delta = dist[i][b] + dist[j][a]\n                                      - dist[i][a] - dist[j][b];\n                            if (delta < 0) {\n                                swap(matchT[i], matchT[j]);\n                                a = matchT[i];\n                                improved = true;\n                            }\n                        }\n                    }\n                    if (!improved) break;\n                }\n            }\n        }\n\n        // Build pairs from final matching\n        pairs.resize(K);\n        for (int i = 0; i < K; i++) {\n            int j = matchT[i];\n            pairs[i].sx = sources[i].first;\n            pairs[i].sy = sources[i].second;\n            pairs[i].tx = targets[j].first;\n            pairs[i].ty = targets[j].second;\n        }\n    }\n\n    // Determine order of processing pairs: nearest neighbor from fingertip position,\n    // then refined by 2-opt on pair order (path).\n    vector<int> order;\n    if (K > 0) {\n        order.reserve(K);\n        vector<char> usedPair(K, 0);\n\n        // Initial fingertip position: root at (initRootX, initRootY), dir=Right => finger at (x, y+1)\n        int curFx = initRootX + DX[0];\n        int curFy = initRootY + DY[0];\n\n        // Nearest neighbor construction\n        for (int step = 0; step < K; step++) {\n            int bestId = -1;\n            int bestD = INT_MAX;\n            for (int i = 0; i < K; i++) if (!usedPair[i]) {\n                int d = abs(curFx - pairs[i].sx) + abs(curFy - pairs[i].sy);\n                if (d < bestD) {\n                    bestD = d;\n                    bestId = i;\n                }\n            }\n            usedPair[bestId] = 1;\n            order.push_back(bestId);\n            curFx = pairs[bestId].tx;\n            curFy = pairs[bestId].ty;\n        }\n\n        // 2-opt refinement on order, using cost from target of i to source of j\n        if (K >= 4) {\n            vector<vector<int>> transCost(K, vector<int>(K));\n            for (int i = 0; i < K; i++) {\n                for (int j = 0; j < K; j++) {\n                    transCost[i][j] = abs(pairs[i].tx - pairs[j].sx)\n                                    + abs(pairs[i].ty - pairs[j].sy);\n                }\n            }\n            int maxPass;\n            if (K <= 120) maxPass = 8;\n            else if (K <= 250) maxPass = 5;\n            else maxPass = 2;\n\n            for (int pass = 0; pass < maxPass; pass++) {\n                bool improved = false;\n                for (int a = 1; a < K - 2 && !improved; a++) {\n                    for (int b = a + 1; b < K - 1; b++) {\n                        int A = order[a - 1];\n                        int B = order[a];\n                        int C = order[b];\n                        int D = order[b + 1];\n                        int oldCost = transCost[A][B] + transCost[C][D];\n                        int newCost = transCost[A][C] + transCost[B][D];\n                        if (newCost < oldCost) {\n                            reverse(order.begin() + a, order.begin() + b + 1);\n                            improved = true;\n                            break;\n                        }\n                    }\n                }\n                if (!improved) break;\n            }\n        }\n    }\n\n    // Command sequence\n    vector<string> cmds;\n    cmds.reserve(100000);\n\n    int rootXsim = initRootX, rootYsim = initRootY; // simulation root position\n    int dir = 0;              // 0=Right initially\n    bool holding = false;\n\n    auto add_step = [&](char mv, char rot, bool doP) {\n        string S(2 * Vp, '.'); // length 4\n        S[0] = mv;\n        S[1] = rot;\n        if (doP) {\n            S[Vp + fingerVertex] = 'P'; // fingertip action (index 3)\n        }\n        cmds.push_back(S);\n\n        // Update root position\n        if (mv == 'U') rootXsim--;\n        else if (mv == 'D') rootXsim++;\n        else if (mv == 'L') rootYsim--;\n        else if (mv == 'R') rootYsim++;\n\n        // Update direction of edge (0,1)\n        if (rot == 'L') dir = (dir + 3) & 3;\n        else if (rot == 'R') dir = (dir + 1) & 3;\n    };\n\n    auto finger_x = [&]() { return rootXsim + DX[dir]; };\n    auto finger_y = [&]() { return rootYsim + DY[dir]; };\n\n    // Move root to (nx, ny) and orientation to ndir, overlapping movement & rotation\n    auto move_root_dir = [&](int nx, int ny, int ndir) {\n        int dx = nx - rootXsim;\n        int dy = ny - rootYsim;\n        vector<char> path;\n        if (dx > 0) path.insert(path.end(), dx, 'D');\n        else if (dx < 0) path.insert(path.end(), -dx, 'U');\n        if (dy > 0) path.insert(path.end(), dy, 'R');\n        else if (dy < 0) path.insert(path.end(), -dy, 'L');\n\n        int diff = (ndir - dir + 4) & 3;\n        int rotSteps = 0;\n        char rotChar = '.';\n        if (diff == 0) {\n            rotSteps = 0;\n        } else if (diff == 1) {\n            rotSteps = 1;\n            rotChar = 'R';\n        } else if (diff == 2) {\n            rotSteps = 2;\n            rotChar = 'R'; // two clockwise rotations\n        } else { // diff == 3\n            rotSteps = 1;\n            rotChar = 'L';\n        }\n\n        int moveSteps = (int)path.size();\n        int overlap = min(rotSteps, moveSteps);\n        for (int i = 0; i < moveSteps; i++) {\n            char mv = path[i];\n            char rot = (i < overlap ? rotChar : '.');\n            add_step(mv, rot, false);\n        }\n        for (int i = overlap; i < rotSteps; i++) {\n            // rotate in place\n            add_step('.', rotChar, false);\n        }\n    };\n\n    // Move fingertip exactly to (tx, ty)\n    auto move_finger_to = [&](int tx, int ty) {\n        int bestNX = rootXsim, bestNY = rootYsim, bestDir = dir;\n        int bestCost = INT_MAX;\n\n        for (int ndir = 0; ndir < 4; ndir++) {\n            int nrX = tx - DX[ndir];\n            int nrY = ty - DY[ndir];\n            if (nrX < 0 || nrX >= N || nrY < 0 || nrY >= N) continue;\n            int distRoot = abs(nrX - rootXsim) + abs(nrY - rootYsim);\n            int diff = (ndir - dir + 4) & 3;\n            int rotCost = min(diff, 4 - diff); // number of 90-degree rotations\n            int cost = max(distRoot, rotCost); // rotations overlapped with movement\n            if (cost < bestCost) {\n                bestCost = cost;\n                bestNX = nrX;\n                bestNY = nrY;\n                bestDir = ndir;\n            }\n        }\n\n        move_root_dir(bestNX, bestNY, bestDir);\n        // fingertip now at (tx, ty)\n    };\n\n    if (K > 0) {\n        for (int idx : order) {\n            const auto &P = pairs[idx];\n\n            // ===== PICK PHASE =====\n            size_t prevSize = cmds.size();\n            move_finger_to(P.sx, P.sy);\n            int fx = finger_x(), fy = finger_y();\n\n            bool doPick = false;\n            if (!holding && fx >= 0 && fx < N && fy >= 0 && fy < N && occ[fx][fy] == 1) {\n                doPick = true;\n                holding = true;\n                occ[fx][fy] = 0;\n            }\n\n            if (doPick) {\n                size_t curSize = cmds.size();\n                if (curSize > prevSize) {\n                    // Merge pick into the last movement/rotation step\n                    cmds[curSize - 1][Vp + fingerVertex] = 'P';\n                } else {\n                    // No movement/rotation was needed; add a standalone P step\n                    add_step('.', '.', true);\n                }\n            }\n\n            // ===== DROP PHASE =====\n            prevSize = cmds.size();\n            move_finger_to(P.tx, P.ty);\n            fx = finger_x();\n            fy = finger_y();\n\n            bool doDrop = false;\n            if (holding && fx >= 0 && fx < N && fy >= 0 && fy < N && occ[fx][fy] == 0) {\n                doDrop = true;\n                holding = false;\n                occ[fx][fy] = 1;\n            }\n\n            if (doDrop) {\n                size_t curSize = cmds.size();\n                if (curSize > prevSize) {\n                    // Merge drop into the last movement/rotation step\n                    cmds[curSize - 1][Vp + fingerVertex] = 'P';\n                } else {\n                    // No movement/rotation needed; add a standalone P step\n                    add_step('.', '.', true);\n                }\n            }\n        }\n    }\n\n    // Output\n    // 1) Tree description: 2 vertices: 0 (root), 1 (fingertip), length 1\n    cout << Vp << '\\n';\n    cout << 0 << ' ' << 1 << '\\n';\n\n    // 2) Initial root position\n    cout << initRootX << ' ' << initRootY << '\\n';\n\n    // 3) Operation sequence\n    for (const string &S : cmds) {\n        cout << S << '\\n';\n    }\n\n    return 0;\n}","ahc039":"#include <bits/stdc++.h>\nusing namespace std;\n\n// =================== Geometry utilities ===================\n\nbool pointInPolygon(int px, int py, const vector<pair<int,int>>& poly) {\n    int n = (int)poly.size();\n    bool inside = false;\n    for (int i = 0, j = n - 1; i < n; j = i++) {\n        long long xi = poly[i].first, yi = poly[i].second;\n        long long xj = poly[j].first, yj = poly[j].second;\n\n        long long minx = min(xi, xj), maxx = max(xi, xj);\n        long long miny = min(yi, yj), maxy = max(yi, yj);\n        long long cross = (xj - xi) * 1LL * (py - yi) - (yj - yi) * 1LL * (px - xi);\n        if (cross == 0 && px >= minx && px <= maxx && py >= miny && py <= maxy) {\n            return true; // on edge\n        }\n\n        // Even-odd rule, ignoring horizontal edges\n        bool cond = ((yi > py) != (yj > py));\n        if (cond) {\n            double interX = xi + (double)(xj - xi) * (double)(py - yi) / (double)(yj - yi);\n            if (interX > px) inside = !inside;\n        }\n    }\n    return inside;\n}\n\nint evaluatePolygonDiff(const vector<pair<int,int>>& poly,\n                        const vector<int>& xs, const vector<int>& ys, int N) {\n    if (poly.empty()) return INT_MIN / 2;\n    int total = 2 * N;\n    int minx = INT_MAX, maxx = INT_MIN, miny = INT_MAX, maxy = INT_MIN;\n    for (auto &p : poly) {\n        minx = min(minx, p.first);\n        maxx = max(maxx, p.first);\n        miny = min(miny, p.second);\n        maxy = max(maxy, p.second);\n    }\n\n    int diff = 0;\n    for (int i = 0; i < total; ++i) {\n        int x = xs[i], y = ys[i];\n        if (x < minx || x > maxx || y < miny || y > maxy) continue;\n        if (pointInPolygon(x, y, poly)) {\n            diff += (i < N ? 1 : -1);\n        }\n    }\n    return diff;\n}\n\n// Build outer boundary polygon from a 4-connected component mask of grid cells.\nvector<pair<int,int>> buildPolygonFromMask(\n    int H, int W,\n    const vector<char>& inside,\n    const vector<int>& xCoord,\n    const vector<int>& yCoord\n) {\n    int V = (H + 1) * (W + 1);\n    vector<vector<int>> adj(V);\n\n    auto cellInside = [&](int i, int j) -> bool {\n        if (i < 0 || i >= H || j < 0 || j >= W) return false;\n        return inside[i * W + j] != 0;\n    };\n    auto vertIndex = [&](int r, int c) -> int {\n        return r * (W + 1) + c;\n    };\n    auto addEdge = [&](int u, int v) {\n        adj[u].push_back(v);\n        adj[v].push_back(u);\n    };\n\n    // Build boundary edges\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            if (!cellInside(i, j)) continue;\n\n            // Left side\n            if (j == 0 || !cellInside(i, j - 1)) {\n                int u = vertIndex(i, j);\n                int v = vertIndex(i + 1, j);\n                addEdge(u, v);\n            }\n            // Right side\n            if (j == W - 1 || !cellInside(i, j + 1)) {\n                int u = vertIndex(i, j + 1);\n                int v = vertIndex(i + 1, j + 1);\n                addEdge(u, v);\n            }\n            // Bottom side\n            if (i == 0 || !cellInside(i - 1, j)) {\n                int u = vertIndex(i, j);\n                int v = vertIndex(i, j + 1);\n                addEdge(u, v);\n            }\n            // Top side\n            if (i == H - 1 || !cellInside(i + 1, j)) {\n                int u = vertIndex(i + 1, j);\n                int v = vertIndex(i + 1, j + 1);\n                addEdge(u, v);\n            }\n        }\n    }\n\n    vector<char> used(V, 0);\n    vector<pair<int,int>> bestPoly;\n    long long bestAreaAbs = -1;\n\n    for (int start = 0; start < V; ++start) {\n        if (used[start] || adj[start].empty()) continue;\n\n        vector<int> cyc;\n        int cur = start;\n        int prev = -1;\n        int safety = 0;\n\n        while (true) {\n            cyc.push_back(cur);\n            used[cur] = 1;\n\n            if (adj[cur].empty()) {\n                cyc.clear();\n                break;\n            }\n\n            int nxt;\n            if ((int)adj[cur].size() == 1) {\n                nxt = adj[cur][0];\n            } else {\n                if (adj[cur][0] != prev) nxt = adj[cur][0];\n                else nxt = adj[cur][1];\n            }\n\n            prev = cur;\n            cur = nxt;\n            if (cur == start) break;\n\n            if (++safety > V * 4) {\n                cyc.clear();\n                break;\n            }\n        }\n\n        if (cyc.empty() || (int)cyc.size() < 4) continue;\n\n        // Convert to coordinates\n        vector<pair<int,int>> ptsRaw;\n        ptsRaw.reserve(cyc.size());\n        for (int vid : cyc) {\n            int r = vid / (W + 1);\n            int c = vid % (W + 1);\n            int x = xCoord[c];\n            int y = yCoord[r];\n            ptsRaw.emplace_back(x, y);\n        }\n\n        // Remove collinear vertices\n        int m = (int)ptsRaw.size();\n        vector<pair<int,int>> pts;\n        pts.reserve(m);\n        for (int i = 0; i < m; ++i) {\n            auto &prevP = ptsRaw[(i + m - 1) % m];\n            auto &curP  = ptsRaw[i];\n            auto &nextP = ptsRaw[(i + 1) % m];\n            bool collinear =\n                (prevP.first == curP.first && curP.first == nextP.first) ||\n                (prevP.second == curP.second && curP.second == nextP.second);\n            if (!collinear) {\n                pts.push_back(curP);\n            }\n        }\n\n        if ((int)pts.size() < 4) continue;\n        if ((int)pts.size() > 1000) continue;\n\n        // Perimeter check\n        long long per = 0;\n        int m2 = (int)pts.size();\n        for (int i = 0; i < m2; ++i) {\n            auto &a = pts[i];\n            auto &b = pts[(i + 1) % m2];\n            per += llabs((long long)a.first - b.first) + llabs((long long)a.second - b.second);\n        }\n        if (per > 400000LL) continue;\n\n        // Area\n        long long area2 = 0;\n        for (int i = 0; i < m2; ++i) {\n            long long x1 = pts[i].first, y1 = pts[i].second;\n            long long x2 = pts[(i + 1) % m2].first, y2 = pts[(i + 1) % m2].second;\n            area2 += x1 * y2 - x2 * y1;\n        }\n        long long areaAbs = llabs(area2);\n        if (areaAbs > bestAreaAbs) {\n            bestAreaAbs = areaAbs;\n            bestPoly = std::move(pts);\n        }\n    }\n\n    return bestPoly;\n}\n\nint evaluateRectDiff(int xL, int yB, int xR, int yT,\n                     const vector<int>& xs, const vector<int>& ys, int N) {\n    if (xL > xR || yB > yT) return INT_MIN / 2;\n    int total = 2 * N;\n    int diff = 0;\n    for (int i = 0; i < total; ++i) {\n        int x = xs[i], y = ys[i];\n        if (x >= xL && x <= xR && y >= yB && y <= yT) {\n            diff += (i < N ? 1 : -1);\n        }\n    }\n    return diff;\n}\n\n// =================== Main ===================\n\nstruct Rect {\n    int xL, yB, xR, yT;\n    int diff;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    if (!(cin >> N)) return 0;\n    int total = 2 * N;\n\n    const int MAXC = 100000;\n    const int FULL = MAXC + 1;\n\n    vector<int> xs(total), ys(total);\n    for (int i = 0; i < total; ++i) {\n        cin >> xs[i] >> ys[i];\n    }\n\n    // Global best polygon and best rectangle\n    vector<pair<int,int>> bestPoly = {\n        {0, 0},\n        {MAXC, 0},\n        {MAXC, MAXC},\n        {0, MAXC}\n    };\n    int bestDiff = 0;\n    Rect bestRect = {0, 0, MAXC, MAXC, 0};\n\n    auto updateBestRectWithDiff = [&](int xL, int yB, int xR, int yT, int diff) {\n        if (diff > bestRect.diff) {\n            bestRect = {xL, yB, xR, yT, diff};\n        }\n        if (diff > bestDiff) {\n            bestDiff = diff;\n            bestPoly.clear();\n            bestPoly.push_back({xL, yB});\n            bestPoly.push_back({xR, yB});\n            bestPoly.push_back({xR, yT});\n            bestPoly.push_back({xL, yT});\n        }\n    };\n\n    auto updateBestWithRect = [&](int xL, int yB, int xR, int yT) {\n        if (xL > xR || yB > yT) return;\n        int diff = evaluateRectDiff(xL, yB, xR, yT, xs, ys, N);\n        updateBestRectWithDiff(xL, yB, xR, yT, diff);\n    };\n\n    auto updateBestWithPoly = [&](const vector<pair<int,int>>& poly) {\n        if (poly.empty()) return;\n        int diff = evaluatePolygonDiff(poly, xs, ys, N);\n        if (diff > bestDiff) {\n            bestDiff = diff;\n            bestPoly = poly;\n        }\n    };\n\n    // Grid sizes and weight modes\n    vector<int> gridSizes = {40, 60, 90, 130};\n    // (weight for mackerel, weight for sardine)\n    vector<pair<int,int>> weightModes = {\n        {1, -1},\n        {1, -2},\n        {2, -1}\n    };\n\n    vector<int> cell;\n    vector<long long> colSum;\n\n    for (int S : gridSizes) {\n        int H = S, W = S;\n        vector<int> xCoord(W + 1), yCoord(H + 1);\n        for (int j = 0; j <= W; ++j) {\n            int val = (int)(1LL * j * FULL / W);\n            if (val > MAXC) val = MAXC;\n            xCoord[j] = val;\n        }\n        for (int i = 0; i <= H; ++i) {\n            int val = (int)(1LL * i * FULL / H);\n            if (val > MAXC) val = MAXC;\n            yCoord[i] = val;\n        }\n\n        // Per-cell counts\n        vector<int> mCell(H * W, 0), sCell(H * W, 0);\n        for (int idx = 0; idx < total; ++idx) {\n            int x = xs[idx], y = ys[idx];\n            int cx = (int)(1LL * x * W / FULL);\n            int cy = (int)(1LL * y * H / FULL);\n            if (cx < 0) cx = 0;\n            if (cx >= W) cx = W - 1;\n            if (cy < 0) cy = 0;\n            if (cy >= H) cy = H - 1;\n            int cidx = cy * W + cx;\n            if (idx < N) mCell[cidx]++; else sCell[cidx]++;\n        }\n\n        for (auto [wM, wS] : weightModes) {\n            // Weighted cell values\n            cell.assign(H * W, 0);\n            for (int i = 0; i < H * W; ++i) {\n                cell[i] = wM * mCell[i] + wS * sCell[i];\n            }\n\n            // ---- 2D Kadane to find best sub-rectangle on this grid ----\n            const long long NEG_INF = -(1LL << 60);\n            long long bestSum = NEG_INF;\n            int bestL = 0, bestR = 0, bestT = 0, bestB = 0;\n\n            colSum.assign(W, 0);\n            for (int top = 0; top < H; ++top) {\n                fill(colSum.begin(), colSum.end(), 0);\n                for (int bottom = top; bottom < H; ++bottom) {\n                    int rowOffset = bottom * W;\n                    for (int c = 0; c < W; ++c) {\n                        colSum[c] += cell[rowOffset + c];\n                    }\n                    long long sum = 0;\n                    int curL = 0;\n                    for (int c = 0; c < W; ++c) {\n                        if (sum <= 0) {\n                            sum = colSum[c];\n                            curL = c;\n                        } else {\n                            sum += colSum[c];\n                        }\n                        if (sum > bestSum) {\n                            bestSum = sum;\n                            bestL = curL;\n                            bestR = c;\n                            bestT = top;\n                            bestB = bottom;\n                        }\n                    }\n                }\n            }\n\n            if (bestSum > 0) {\n                int xL = xCoord[bestL];\n                int xR = xCoord[bestR + 1];\n                int yB = yCoord[bestT];\n                int yT = yCoord[bestB + 1];\n                if (xL < 0) xL = 0;\n                if (xR > MAXC) xR = MAXC;\n                if (yB < 0) yB = 0;\n                if (yT > MAXC) yT = MAXC;\n                updateBestWithRect(xL, yB, xR, yT);\n            }\n\n            // ---- Connected positive components -> polygons ----\n            vector<char> visited(H * W, 0);\n            struct Comp {\n                long long sum;\n                vector<pair<int,int>> cells;\n            };\n            vector<Comp> bestComps;\n            const int KCOMP = 2;\n\n            static const int dr[4] = {-1, 1, 0, 0};\n            static const int dc[4] = {0, 0, -1, 1};\n\n            for (int i = 0; i < H; ++i) {\n                for (int j = 0; j < W; ++j) {\n                    int idx = i * W + j;\n                    if (visited[idx] || cell[idx] <= 0) continue;\n\n                    long long curSum = 0;\n                    vector<pair<int,int>> compCells;\n                    compCells.reserve(64);\n\n                    queue<int> q;\n                    visited[idx] = 1;\n                    q.push(idx);\n\n                    while (!q.empty()) {\n                        int u = q.front(); q.pop();\n                        int r = u / W, c = u % W;\n                        compCells.emplace_back(r, c);\n                        curSum += cell[u];\n\n                        for (int d = 0; d < 4; ++d) {\n                            int nr = r + dr[d];\n                            int nc = c + dc[d];\n                            if (nr < 0 || nr >= H || nc < 0 || nc >= W) continue;\n                            int v = nr * W + nc;\n                            if (!visited[v] && cell[v] > 0) {\n                                visited[v] = 1;\n                                q.push(v);\n                            }\n                        }\n                    }\n\n                    if (curSum <= 0) continue;\n\n                    if ((int)bestComps.size() < KCOMP) {\n                        bestComps.push_back({curSum, std::move(compCells)});\n                    } else {\n                        int pos = 0;\n                        if (bestComps[1].sum < bestComps[0].sum) pos = 1;\n                        if (curSum > bestComps[pos].sum) {\n                            bestComps[pos] = {curSum, std::move(compCells)};\n                        }\n                    }\n                }\n            }\n\n            // Build polygon for each stored component\n            for (auto &comp : bestComps) {\n                vector<char> mask(H * W, 0);\n                for (auto &rc : comp.cells) {\n                    mask[rc.first * W + rc.second] = 1;\n                }\n                auto poly = buildPolygonFromMask(H, W, mask, xCoord, yCoord);\n                if (!poly.empty()) {\n                    updateBestWithPoly(poly);\n                }\n            }\n        }\n    }\n\n    // Fallback small rectangles around mackerels if nothing positive\n    if (bestDiff <= 0) {\n        const int delta = 1000;\n        for (int i = 0; i < N; ++i) {\n            int xL = max(0, xs[i] - delta);\n            int xR = min(MAXC, xs[i] + delta);\n            int yB = max(0, ys[i] - delta);\n            int yT = min(MAXC, ys[i] + delta);\n            updateBestWithRect(xL, yB, xR, yT);\n        }\n    }\n\n    // ---------- Local search on rectangles (multi-start) ----------\n\n    vector<int> uniqX = xs, uniqY = ys;\n    sort(uniqX.begin(), uniqX.end());\n    uniqX.erase(unique(uniqX.begin(), uniqX.end()), uniqX.end());\n    sort(uniqY.begin(), uniqY.end());\n    uniqY.erase(unique(uniqY.begin(), uniqY.end()), uniqY.end());\n\n    mt19937 rng(1234567);\n\n    auto randRange = [&](int lo, int hi) -> int {\n        if (lo > hi) return lo;\n        uint32_t r = rng();\n        return lo + (int)(r % (uint32_t)(hi - lo + 1));\n    };\n\n    // Deterministic side refinement for a rectangle\n    auto refineRect = [&](Rect &cur) {\n        if (uniqX.empty() || uniqY.empty()) return;\n        static const int OFFS[6] = {-50, -25, -10, 10, 25, 50};\n        int Mx = (int)uniqX.size();\n        int My = (int)uniqY.size();\n\n        for (int pass = 0; pass < 2; ++pass) {\n            // Left\n            {\n                int idx = (int)(lower_bound(uniqX.begin(), uniqX.end(), cur.xL) - uniqX.begin());\n                if (idx >= Mx) idx = Mx - 1;\n                int base = idx;\n                int bestLocalDiff = cur.diff;\n                int bestLocalX = cur.xL;\n                for (int k = 0; k < 6; ++k) {\n                    int nidx = base + OFFS[k];\n                    if (nidx < 0) nidx = 0;\n                    if (nidx >= Mx) nidx = Mx - 1;\n                    int nx = uniqX[nidx];\n                    if (nx >= cur.xR) continue;\n                    if (nx == cur.xL) continue;\n                    int diff = evaluateRectDiff(nx, cur.yB, cur.xR, cur.yT, xs, ys, N);\n                    if (diff > bestLocalDiff) {\n                        bestLocalDiff = diff;\n                        bestLocalX = nx;\n                    }\n                }\n                if (bestLocalDiff > cur.diff) {\n                    cur.xL = bestLocalX;\n                    cur.diff = bestLocalDiff;\n                    updateBestRectWithDiff(cur.xL, cur.yB, cur.xR, cur.yT, cur.diff);\n                }\n            }\n            // Right\n            {\n                int idx = (int)(upper_bound(uniqX.begin(), uniqX.end(), cur.xR) - uniqX.begin()) - 1;\n                if (idx < 0) idx = 0;\n                int base = idx;\n                int bestLocalDiff = cur.diff;\n                int bestLocalX = cur.xR;\n                for (int k = 0; k < 6; ++k) {\n                    int nidx = base + OFFS[k];\n                    if (nidx < 0) nidx = 0;\n                    if (nidx >= Mx) nidx = Mx - 1;\n                    int nx = uniqX[nidx];\n                    if (nx <= cur.xL) continue;\n                    if (nx == cur.xR) continue;\n                    int diff = evaluateRectDiff(cur.xL, cur.yB, nx, cur.yT, xs, ys, N);\n                    if (diff > bestLocalDiff) {\n                        bestLocalDiff = diff;\n                        bestLocalX = nx;\n                    }\n                }\n                if (bestLocalDiff > cur.diff) {\n                    cur.xR = bestLocalX;\n                    cur.diff = bestLocalDiff;\n                    updateBestRectWithDiff(cur.xL, cur.yB, cur.xR, cur.yT, cur.diff);\n                }\n            }\n            // Bottom\n            {\n                int idx = (int)(lower_bound(uniqY.begin(), uniqY.end(), cur.yB) - uniqY.begin());\n                if (idx >= My) idx = My - 1;\n                int base = idx;\n                int bestLocalDiff = cur.diff;\n                int bestLocalY = cur.yB;\n                for (int k = 0; k < 6; ++k) {\n                    int nidx = base + OFFS[k];\n                    if (nidx < 0) nidx = 0;\n                    if (nidx >= My) nidx = My - 1;\n                    int ny = uniqY[nidx];\n                    if (ny >= cur.yT) continue;\n                    if (ny == cur.yB) continue;\n                    int diff = evaluateRectDiff(cur.xL, ny, cur.xR, cur.yT, xs, ys, N);\n                    if (diff > bestLocalDiff) {\n                        bestLocalDiff = diff;\n                        bestLocalY = ny;\n                    }\n                }\n                if (bestLocalDiff > cur.diff) {\n                    cur.yB = bestLocalY;\n                    cur.diff = bestLocalDiff;\n                    updateBestRectWithDiff(cur.xL, cur.yB, cur.xR, cur.yT, cur.diff);\n                }\n            }\n            // Top\n            {\n                int idx = (int)(upper_bound(uniqY.begin(), uniqY.end(), cur.yT) - uniqY.begin()) - 1;\n                if (idx < 0) idx = 0;\n                int base = idx;\n                int bestLocalDiff = cur.diff;\n                int bestLocalY = cur.yT;\n                for (int k = 0; k < 6; ++k) {\n                    int nidx = base + OFFS[k];\n                    if (nidx < 0) nidx = 0;\n                    if (nidx >= My) nidx = My - 1;\n                    int ny = uniqY[nidx];\n                    if (ny <= cur.yB) continue;\n                    if (ny == cur.yT) continue;\n                    int diff = evaluateRectDiff(cur.xL, cur.yB, cur.xR, ny, xs, ys, N);\n                    if (diff > bestLocalDiff) {\n                        bestLocalDiff = diff;\n                        bestLocalY = ny;\n                    }\n                }\n                if (bestLocalDiff > cur.diff) {\n                    cur.yT = bestLocalY;\n                    cur.diff = bestLocalDiff;\n                    updateBestRectWithDiff(cur.xL, cur.yB, cur.xR, cur.yT, cur.diff);\n                }\n            }\n        }\n    };\n\n    auto localSearchFromSeed = [&](Rect seed) {\n        if (uniqX.empty() || uniqY.empty()) return;\n\n        Rect cur = seed;\n        // Ensure diff is correct\n        cur.diff = evaluateRectDiff(cur.xL, cur.yB, cur.xR, cur.yT, xs, ys, N);\n        updateBestRectWithDiff(cur.xL, cur.yB, cur.xR, cur.yT, cur.diff);\n\n        // Deterministic refinement\n        refineRect(cur);\n\n        int curDiff = cur.diff;\n        int Mx = (int)uniqX.size();\n        int My = (int)uniqY.size();\n        const int ITER = 200;\n        const int RANGE = 50;\n\n        for (int it = 0; it < ITER; ++it) {\n            Rect cand = cur;\n            bool ok = false;\n            int side = randRange(0, 3); // 0:left,1:right,2:bottom,3:top\n\n            for (int attempt = 0; attempt < 5; ++attempt) {\n                if (side == 0) { // move left\n                    int idx = (int)(lower_bound(uniqX.begin(), uniqX.end(), cur.xL) - uniqX.begin());\n                    if (idx >= Mx) idx = Mx - 1;\n                    int lo = max(0, idx - RANGE);\n                    int hi = idx;\n                    if (lo > hi) break;\n                    int newIdx = randRange(lo, hi);\n                    int nx = uniqX[newIdx];\n                    if (nx >= cand.xR) continue;\n                    cand.xL = nx;\n                    ok = true;\n                    break;\n                } else if (side == 1) { // move right\n                    int idx = (int)(upper_bound(uniqX.begin(), uniqX.end(), cur.xR) - uniqX.begin()) - 1;\n                    if (idx < 0) idx = 0;\n                    int lo = idx;\n                    int hi = min(Mx - 1, idx + RANGE);\n                    if (lo > hi) break;\n                    int newIdx = randRange(lo, hi);\n                    int nx = uniqX[newIdx];\n                    if (nx <= cand.xL) continue;\n                    cand.xR = nx;\n                    ok = true;\n                    break;\n                } else if (side == 2) { // move bottom\n                    int idx = (int)(lower_bound(uniqY.begin(), uniqY.end(), cur.yB) - uniqY.begin());\n                    if (idx >= My) idx = My - 1;\n                    int lo = max(0, idx - RANGE);\n                    int hi = idx;\n                    if (lo > hi) break;\n                    int newIdx = randRange(lo, hi);\n                    int ny = uniqY[newIdx];\n                    if (ny >= cand.yT) continue;\n                    cand.yB = ny;\n                    ok = true;\n                    break;\n                } else { // move top\n                    int idx = (int)(upper_bound(uniqY.begin(), uniqY.end(), cur.yT) - uniqY.begin()) - 1;\n                    if (idx < 0) idx = 0;\n                    int lo = idx;\n                    int hi = min(My - 1, idx + RANGE);\n                    if (lo > hi) break;\n                    int newIdx = randRange(lo, hi);\n                    int ny = uniqY[newIdx];\n                    if (ny <= cand.yB) continue;\n                    cand.yT = ny;\n                    ok = true;\n                    break;\n                }\n            }\n\n            if (!ok) continue;\n            if (cand.xL == cur.xL && cand.xR == cur.xR &&\n                cand.yB == cur.yB && cand.yT == cur.yT) continue;\n\n            int diff = evaluateRectDiff(cand.xL, cand.yB, cand.xR, cand.yT, xs, ys, N);\n            if (diff > curDiff) {\n                cur = cand;\n                curDiff = diff;\n                cur.diff = diff;\n                updateBestRectWithDiff(cur.xL, cur.yB, cur.xR, cur.yT, cur.diff);\n            }\n        }\n    };\n\n    // Seeds: bestRect and bounding box of bestPoly\n    Rect seed1 = bestRect;\n    localSearchFromSeed(seed1);\n\n    // Bounding rectangle of bestPoly\n    {\n        int minx = INT_MAX, maxx = INT_MIN, miny = INT_MAX, maxy = INT_MIN;\n        for (auto &p : bestPoly) {\n            minx = min(minx, p.first);\n            maxx = max(maxx, p.first);\n            miny = min(miny, p.second);\n            maxy = max(maxy, p.second);\n        }\n        if (minx < 0) minx = 0;\n        if (maxx > MAXC) maxx = MAXC;\n        if (miny < 0) miny = 0;\n        if (maxy > MAXC) maxy = MAXC;\n        if (minx < maxx && miny < maxy) {\n            Rect seed2 = {minx, miny, maxx, maxy, 0};\n            localSearchFromSeed(seed2);\n        }\n    }\n\n    // Final polygon validity check\n    auto checkPolygon = [&](const vector<pair<int,int>>& poly) -> bool {\n        int m = (int)poly.size();\n        if (m < 4 || m > 1000) return false;\n        long long per = 0;\n        for (int i = 0; i < m; ++i) {\n            auto &a = poly[i];\n            auto &b = poly[(i + 1) % m];\n            per += llabs((long long)a.first - b.first) +\n                   llabs((long long)a.second - b.second);\n        }\n        if (per > 400000LL) return false;\n        set<pair<int,int>> st(poly.begin(), poly.end());\n        if ((int)st.size() != m) return false;\n        return true;\n    };\n\n    if (!checkPolygon(bestPoly)) {\n        bestPoly = {\n            {0, 0},\n            {MAXC, 0},\n            {MAXC, MAXC},\n            {0, MAXC}\n        };\n    }\n\n    cout << bestPoly.size() << '\\n';\n    for (auto &p : bestPoly) {\n        cout << p.first << ' ' << p.second << '\\n';\n    }\n    return 0;\n}","ahc040":"#include <bits/stdc++.h>\nusing namespace std;\nusing ll = long long;\n\nstruct EvalResult {\n    ll W = (1LL << 60);\n    ll H = (1LL << 60);\n    ll S = (1LL << 60);\n    vector<int> cuts; // 0 = cuts[0] < ... < cuts[R] = N\n};\n\n////////////////////\n// Horizontal DP  //\n////////////////////\n\nEvalResult evaluate_orientation_horizontal(const vector<ll>& w0,\n                                           const vector<ll>& h0,\n                                           const vector<int>& rot) {\n    int N = (int)w0.size();\n    const ll INF = (1LL << 62);\n\n    // Oriented sizes\n    vector<ll> width(N), height(N);\n    ll sumW = 0, maxW = 0;\n    long double area = 0.0L;\n    for (int i = 0; i < N; i++) {\n        if (rot[i] == 0) {\n            width[i]  = w0[i];\n            height[i] = h0[i];\n        } else {\n            width[i]  = h0[i];\n            height[i] = w0[i];\n        }\n        sumW += width[i];\n        maxW = max(maxW, width[i]);\n        area += (long double)width[i] * (long double)height[i];\n    }\n\n    EvalResult best;\n    if (sumW == 0) {\n        best.W = best.H = best.S = 0;\n        best.cuts = {0, N};\n        return best;\n    }\n\n    // Candidate width limits\n    vector<ll> Ws;\n    Ws.reserve(16);\n    Ws.push_back(sumW);\n    Ws.push_back(maxW);\n\n    long double base = sqrtl(max((long double)1.0L, area));\n    long double low  = max((long double)maxW, base * 0.5L);\n    long double high = min((long double)sumW, base * 2.0L);\n    if (high < low) high = low;\n\n    const int EXTRA = 10;\n    if (high == low) {\n        ll Wc = (ll)(low + 0.5L);\n        Ws.push_back(Wc);\n    } else {\n        for (int k = 0; k < EXTRA; k++) {\n            long double t = (k + 0.5L) / (long double)EXTRA;\n            long double w = low + (high - low) * t;\n            ll Wc = (ll)(w + 0.5L);\n            if (Wc < maxW) Wc = maxW;\n            if (Wc > sumW) Wc = sumW;\n            Ws.push_back(Wc);\n        }\n    }\n    sort(Ws.begin(), Ws.end());\n    Ws.erase(unique(Ws.begin(), Ws.end()), Ws.end());\n\n    vector<ll> dp(N + 1);\n    vector<int> prev(N + 1);\n\n    for (ll W_limit : Ws) {\n        dp[0] = 0;\n        prev[0] = -1;\n        for (int i = 1; i <= N; i++) {\n            ll bestH = INF;\n            int bestJ = -1;\n            ll rowW = 0;\n            ll rowH = 0;\n            for (int j = i - 1; j >= 0; j--) {\n                rowW += width[j];\n                if (rowW > W_limit) break;\n                if (height[j] > rowH) rowH = height[j];\n                ll cand = dp[j] + rowH;\n                if (cand < bestH) {\n                    bestH = cand;\n                    bestJ = j;\n                }\n            }\n            dp[i] = bestH;\n            prev[i] = bestJ;\n        }\n        if (prev[N] == -1 || dp[N] >= INF) continue;\n\n        vector<int> cuts;\n        int cur = N;\n        cuts.push_back(N);\n        while (cur > 0) {\n            int pj = prev[cur];\n            if (pj < 0) { cuts.clear(); break; }\n            cuts.push_back(pj);\n            cur = pj;\n        }\n        if (cuts.empty()) continue;\n        if (cuts.back() != 0) continue;\n        reverse(cuts.begin(), cuts.end());\n\n        ll Htotal = 0;\n        ll Wactual = 0;\n        int R = (int)cuts.size() - 1;\n        for (int r = 0; r < R; r++) {\n            int L = cuts[r];\n            int Ridx = cuts[r + 1];\n            ll rowW = 0;\n            ll rowH = 0;\n            for (int i = L; i < Ridx; i++) {\n                rowW += width[i];\n                if (height[i] > rowH) rowH = height[i];\n            }\n            Htotal += rowH;\n            if (rowW > Wactual) Wactual = rowW;\n        }\n        ll S = Htotal + Wactual;\n        if (S < best.S) {\n            best.S = S;\n            best.W = Wactual;\n            best.H = Htotal;\n            best.cuts = std::move(cuts);\n        }\n    }\n\n    if (best.S >= (1LL<<60)) {\n        best.cuts = {0, N};\n        ll rowW = 0, rowH = 0;\n        for (int i = 0; i < N; i++) {\n            rowW += width[i];\n            if (height[i] > rowH) rowH = height[i];\n        }\n        best.W = rowW;\n        best.H = rowH;\n        best.S = rowW + rowH;\n    }\n\n    return best;\n}\n\n///////////////////\n// Vertical DP   //\n///////////////////\n\nEvalResult evaluate_orientation_vertical(const vector<ll>& w0,\n                                         const vector<ll>& h0,\n                                         const vector<int>& rot) {\n    int N = (int)w0.size();\n    const ll INF = (1LL << 62);\n\n    // Oriented sizes\n    vector<ll> width(N), height(N);\n    for (int i = 0; i < N; i++) {\n        if (rot[i] == 0) {\n            width[i]  = w0[i];\n            height[i] = h0[i];\n        } else {\n            width[i]  = h0[i];\n            height[i] = w0[i];\n        }\n    }\n\n    // Swapped for DP\n    vector<ll> wS(N), hS(N);\n    ll sumW = 0, maxW = 0;\n    long double area = 0.0L;\n    for (int i = 0; i < N; i++) {\n        wS[i] = height[i];\n        hS[i] = width[i];\n        sumW += wS[i];\n        maxW = max(maxW, wS[i]);\n        area += (long double)wS[i] * (long double)hS[i];\n    }\n\n    EvalResult best;\n    if (sumW == 0) {\n        best.W = best.H = best.S = 0;\n        best.cuts = {0, N};\n        return best;\n    }\n\n    vector<ll> Ws;\n    Ws.reserve(16);\n    Ws.push_back(sumW);\n    Ws.push_back(maxW);\n\n    long double base = sqrtl(max((long double)1.0L, area));\n    long double low  = max((long double)maxW, base * 0.5L);\n    long double high = min((long double)sumW, base * 2.0L);\n    if (high < low) high = low;\n\n    const int EXTRA = 10;\n    if (high == low) {\n        ll Wc = (ll)(low + 0.5L);\n        Ws.push_back(Wc);\n    } else {\n        for (int k = 0; k < EXTRA; k++) {\n            long double t = (k + 0.5L) / (long double)EXTRA;\n            long double w = low + (high - low) * t;\n            ll Wc = (ll)(w + 0.5L);\n            if (Wc < maxW) Wc = maxW;\n            if (Wc > sumW) Wc = sumW;\n            Ws.push_back(Wc);\n        }\n    }\n    sort(Ws.begin(), Ws.end());\n    Ws.erase(unique(Ws.begin(), Ws.end()), Ws.end());\n\n    vector<ll> dp(N + 1);\n    vector<int> prev(N + 1);\n\n    for (ll W_limit : Ws) {\n        dp[0] = 0;\n        prev[0] = -1;\n        for (int i = 1; i <= N; i++) {\n            ll bestH = INF;\n            int bestJ = -1;\n            ll rowW = 0;\n            ll rowH = 0;\n            for (int j = i - 1; j >= 0; j--) {\n                rowW += wS[j];\n                if (rowW > W_limit) break;\n                if (hS[j] > rowH) rowH = hS[j];\n                ll cand = dp[j] + rowH;\n                if (cand < bestH) {\n                    bestH = cand;\n                    bestJ = j;\n                }\n            }\n            dp[i] = bestH;\n            prev[i] = bestJ;\n        }\n        if (prev[N] == -1 || dp[N] >= INF) continue;\n\n        vector<int> cuts;\n        int cur = N;\n        cuts.push_back(N);\n        while (cur > 0) {\n            int pj = prev[cur];\n            if (pj < 0) { cuts.clear(); break; }\n            cuts.push_back(pj);\n            cur = pj;\n        }\n        if (cuts.empty()) continue;\n        if (cuts.back() != 0) continue;\n        reverse(cuts.begin(), cuts.end());\n\n        ll Wcol = 0;\n        ll Hcol = 0;\n        int C = (int)cuts.size() - 1;\n        for (int c = 0; c < C; c++) {\n            int L = cuts[c];\n            int Ridx = cuts[c + 1];\n            ll colW = 0;\n            ll colH = 0;\n            for (int i = L; i < Ridx; i++) {\n                if (width[i] > colW) colW = width[i];\n                colH += height[i];\n            }\n            Wcol += colW;\n            if (colH > Hcol) Hcol = colH;\n        }\n        ll Scol = Wcol + Hcol;\n        if (Scol < best.S) {\n            best.S = Scol;\n            best.W = Wcol;\n            best.H = Hcol;\n            best.cuts = std::move(cuts);\n        }\n    }\n\n    if (best.S >= (1LL<<60)) {\n        best.cuts = {0, N};\n        ll colW = 0, colH = 0;\n        for (int i = 0; i < N; i++) {\n            if (width[i] > colW) colW = width[i];\n            colH += height[i];\n        }\n        best.W = colW;\n        best.H = colH;\n        best.S = best.W + best.H;\n    }\n\n    return best;\n}\n\nstruct Layout {\n    vector<int> rot;\n    EvalResult eval;\n    bool vertical; // false=L (rows), true=U (columns)\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, T;\n    ll sigma;\n    if (!(cin >> N >> T >> sigma)) {\n        return 0;\n    }\n    vector<ll> w0(N), h0(N);\n    for (int i = 0; i < N; i++) {\n        cin >> w0[i] >> h0[i];\n        if (w0[i] < 1) w0[i] = 1;\n        if (h0[i] < 1) h0[i] = 1;\n    }\n\n    // Baseline horizontal orientation search (original behavior)\n    vector<int> rot(N);\n    for (int i = 0; i < N; i++) {\n        // rotate if h0 > w0 so height = min dimension\n        rot[i] = (h0[i] > w0[i]) ? 1 : 0;\n    }\n    EvalResult bestH = evaluate_orientation_horizontal(w0, h0, rot);\n\n    const int BASE_PASSES = 2;\n    for (int pass = 0; pass < BASE_PASSES; pass++) {\n        for (int i = 0; i < N; i++) {\n            rot[i] ^= 1;\n            EvalResult cand = evaluate_orientation_horizontal(w0, h0, rot);\n            if (cand.S < bestH.S) {\n                bestH = cand;\n            } else {\n                rot[i] ^= 1; // revert\n            }\n        }\n    }\n    vector<int> baselineRot = rot;\n    EvalResult baselineEval = bestH;\n\n    mt19937_64 rng(123456789);\n\n    // Precompute layouts for each turn\n    vector<Layout> layouts(T);\n\n    // Turn 0: baseline horizontal layout\n    layouts[0].rot = baselineRot;\n    layouts[0].eval = baselineEval;\n    layouts[0].vertical = false;\n\n    // Turn 1: same orientation, choose best of horizontal/vertical\n    if (T > 1) {\n        Layout lay;\n        lay.rot = baselineRot;\n        EvalResult candH = baselineEval;\n        EvalResult candV = evaluate_orientation_vertical(w0, h0, lay.rot);\n        if (candV.S < candH.S) {\n            lay.vertical = true;\n            lay.eval = candV;\n        } else {\n            lay.vertical = false;\n            lay.eval = candH;\n        }\n        layouts[1] = std::move(lay);\n    }\n\n    // Remaining turns: random multi-bit neighbors of baselineRot,\n    // each evaluated with both horizontal and vertical, keep better.\n    for (int t = 2; t < T; t++) {\n        Layout lay;\n        lay.rot = baselineRot;\n\n        int maxK = min(N, 6); // flip between 2 and 6 bits\n        int k = 2;\n        if (maxK > 2) {\n            k = 2 + (int)(rng() % (maxK - 1)); // 2..maxK\n        }\n        if (k > N) k = N;\n\n        vector<int> idxs;\n        idxs.reserve(k);\n        while ((int)idxs.size() < k) {\n            int x = (int)(rng() % N);\n            bool ok = true;\n            for (int v : idxs) if (v == x) { ok = false; break; }\n            if (ok) idxs.push_back(x);\n        }\n        for (int id : idxs) lay.rot[id] ^= 1;\n\n        EvalResult candH = evaluate_orientation_horizontal(w0, h0, lay.rot);\n        EvalResult candV = evaluate_orientation_vertical(w0, h0, lay.rot);\n        if (candV.S < candH.S) {\n            lay.vertical = true;\n            lay.eval = candV;\n        } else {\n            lay.vertical = false;\n            lay.eval = candH;\n        }\n\n        layouts[t] = std::move(lay);\n    }\n\n    // Output layouts turn by turn\n    for (int t = 0; t < T; t++) {\n        const Layout &L = layouts[t];\n        const vector<int> &rotT = L.rot;\n        const EvalResult &ev = L.eval;\n        bool vertical = L.vertical;\n\n        // Oriented sizes for this layout\n        vector<ll> width(N), height(N);\n        for (int i = 0; i < N; i++) {\n            if (rotT[i] == 0) {\n                width[i]  = w0[i];\n                height[i] = h0[i];\n            } else {\n                width[i]  = h0[i];\n                height[i] = w0[i];\n            }\n        }\n\n        // Group assignment (rows or columns)\n        vector<int> group(N);\n        int G = (int)ev.cuts.size() - 1;\n        for (int g = 0; g < G; g++) {\n            for (int i = ev.cuts[g]; i < ev.cuts[g + 1]; i++) {\n                group[i] = g;\n            }\n        }\n\n        cout << N << '\\n';\n        if (!vertical) {\n            // Horizontal shelves: rows, direction 'L'\n            vector<int> baseRow(G, -1);\n            for (int g = 0; g < G; g++) {\n                int Lidx = ev.cuts[g];\n                int Ridx = ev.cuts[g + 1];\n                ll bestHrow = -1;\n                int bestIdx = Lidx;\n                for (int i = Lidx; i < Ridx; i++) {\n                    if (height[i] > bestHrow) {\n                        bestHrow = height[i];\n                        bestIdx = i;\n                    }\n                }\n                baseRow[g] = bestIdx;\n            }\n            for (int i = 0; i < N; i++) {\n                int r = group[i];\n                int b = (r == 0 ? -1 : baseRow[r - 1]);\n                char d = 'L';\n                cout << i << ' ' << rotT[i] << ' ' << d << ' ' << b << '\\n';\n            }\n        } else {\n            // Vertical shelves: columns, direction 'U'\n            vector<int> baseCol(G, -1);\n            for (int g = 0; g < G; g++) {\n                int Lidx = ev.cuts[g];\n                int Ridx = ev.cuts[g + 1];\n                ll bestWcol = -1;\n                int bestIdx = Lidx;\n                for (int i = Lidx; i < Ridx; i++) {\n                    if (width[i] > bestWcol) {\n                        bestWcol = width[i];\n                        bestIdx = i;\n                    }\n                }\n                baseCol[g] = bestIdx;\n            }\n            for (int i = 0; i < N; i++) {\n                int c = group[i];\n                int b = (c == 0 ? -1 : baseCol[c - 1]);\n                char d = 'U';\n                cout << i << ' ' << rotT[i] << ' ' << d << ' ' << b << '\\n';\n            }\n        }\n        cout.flush();\n\n        ll Wm, Hm;\n        if (!(cin >> Wm >> Hm)) return 0; // ignore measurements\n    }\n\n    return 0;\n}","ahc041":"#include <bits/stdc++.h>\nusing namespace std;\n\n// Simple fast RNG\nstruct FastRand {\n    uint64_t x;\n    FastRand() {\n        x = 88172645463393265ull;\n    }\n    uint64_t next() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return x;\n    }\n    int nextInt(int n) { // 0..n-1\n        return (int)(next() % (uint64_t)n);\n    }\n    double nextDouble() {\n        return (next() >> 11) * (1.0 / 9007199254740992.0); // [0,1)\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, H;\n    if (!(cin >> N >> M >> H)) {\n        return 0;\n    }\n\n    vector<int> A(N);\n    for (int i = 0; i < N; ++i) cin >> A[i];\n\n    vector<vector<int>> adj(N);\n    for (int i = 0; i < M; ++i) {\n        int u, v;\n        cin >> u >> v;\n        adj[u].push_back(v);\n        adj[v].push_back(u);\n    }\n\n    // Coordinates (unused in this solution, but must be read)\n    vector<int> x(N), y(N);\n    for (int i = 0; i < N; ++i) cin >> x[i] >> y[i];\n\n    // ---------- Initial forest construction: greedy by ascending beauty ----------\n    vector<int> parent(N, -1);\n    vector<int> depth(N, 0);\n    vector<char> processed(N, 0);\n\n    vector<int> orderAsc(N);\n    iota(orderAsc.begin(), orderAsc.end(), 0);\n    sort(orderAsc.begin(), orderAsc.end(), [&](int i, int j) {\n        if (A[i] != A[j]) return A[i] < A[j];\n        return i < j;\n    });\n\n    for (int idx = 0; idx < N; ++idx) {\n        int v = orderAsc[idx];\n        processed[v] = 1;\n        int bestParent = -1;\n        int bestDepth = -1;\n        for (int u : adj[v]) {\n            if (!processed[u]) continue;          // only already placed vertices\n            if (depth[u] > H - 1) continue;       // parent depth must allow child depth <= H\n            if (depth[u] > bestDepth) {\n                bestDepth = depth[u];\n                bestParent = u;\n            }\n        }\n        if (bestParent == -1) {\n            parent[v] = -1;\n            depth[v] = 0;\n        } else {\n            parent[v] = bestParent;\n            depth[v] = depth[bestParent] + 1;\n            if (depth[v] > H) depth[v] = H; // safety\n        }\n    }\n\n    // ---------- Build children lists ----------\n    vector<vector<int>> children(N);\n    for (int v = 0; v < N; ++v) {\n        int p = parent[v];\n        if (p != -1) children[p].push_back(v);\n    }\n\n    // ---------- Compute subtreeSum and subHeight bottom-up ----------\n    vector<vector<int>> nodesAtDepth(H + 1);\n    for (int v = 0; v < N; ++v) {\n        int d = depth[v];\n        if (d < 0) d = 0;\n        if (d > H) d = H;\n        nodesAtDepth[d].push_back(v);\n    }\n\n    vector<long long> subtreeSum(N, 0);\n    vector<int> subHeight(N, 0);\n\n    for (int d = H; d >= 0; --d) {\n        for (int v : nodesAtDepth[d]) {\n            long long sum = A[v];\n            int h = 0;\n            for (int c : children[v]) {\n                sum += subtreeSum[c];\n                h = max(h, 1 + subHeight[c]);\n            }\n            subtreeSum[v] = sum;\n            subHeight[v] = h;\n        }\n    }\n\n    // ---------- Compute initial score ----------\n    long long score = 0;\n    for (int v = 0; v < N; ++v) {\n        int d = depth[v];\n        if (d < 0) d = 0;\n        if (d > H) d = H;\n        score += (long long)(d + 1) * (long long)A[v];\n    }\n\n    // From now on, we get depths on demand from parent pointers.\n    auto getDepth = [&](int v) -> int {\n        int d = 0;\n        while (parent[v] != -1) {\n            v = parent[v];\n            ++d;\n        }\n        return d; // \u2264 H\n    };\n\n    // Best solution tracking (we will run extra local search / SA)\n    long long bestScore = score;\n    vector<int> bestParent = parent;\n\n    // ---------- Helpers for local modifications ----------\n    auto recomputeHeightFrom = [&](int start) {\n        int x = start;\n        while (x != -1) {\n            int old_h = subHeight[x];\n            int new_h = 0;\n            for (int c : children[x]) {\n                new_h = max(new_h, 1 + subHeight[c]);\n            }\n            if (new_h == old_h) break;\n            subHeight[x] = new_h;\n            x = parent[x];\n        }\n    };\n\n    auto reparentFn = [&](int v, int newParent, int oldDepth, int newDepth) {\n        int oldParent = parent[v];\n        if (oldParent == newParent) return;\n\n        long long deltaDepth = (long long)(newDepth - oldDepth);\n        long long deltaScore = deltaDepth * subtreeSum[v];\n        score += deltaScore;\n\n        // Update subtreeSum along old parent path: remove subtreeSum[v]\n        if (oldParent != -1) {\n            for (int x = oldParent; x != -1; x = parent[x]) {\n                subtreeSum[x] -= subtreeSum[v];\n            }\n        }\n\n        // Update subtreeSum along new parent path: add subtreeSum[v]\n        if (newParent != -1) {\n            for (int x = newParent; x != -1; x = parent[x]) {\n                subtreeSum[x] += subtreeSum[v];\n            }\n        }\n\n        // Update children lists\n        if (oldParent != -1) {\n            auto &vec = children[oldParent];\n            for (int i = 0; i < (int)vec.size(); ++i) {\n                if (vec[i] == v) {\n                    vec[i] = vec.back();\n                    vec.pop_back();\n                    break;\n                }\n            }\n        }\n        if (newParent != -1) {\n            children[newParent].push_back(v);\n        }\n\n        parent[v] = newParent;\n\n        // Update heights along old and new parent paths\n        if (oldParent != -1) recomputeHeightFrom(oldParent);\n        if (newParent != -1) recomputeHeightFrom(newParent);\n\n        // Record best solution\n        if (score > bestScore) {\n            bestScore = score;\n            bestParent = parent;\n        }\n    };\n\n    // ---------- Greedy hill climbing (depth-increasing only) ----------\n    vector<int> orderDesc(N);\n    iota(orderDesc.begin(), orderDesc.end(), 0);\n    sort(orderDesc.begin(), orderDesc.end(), [&](int i, int j) {\n        if (A[i] != A[j]) return A[i] > A[j];\n        return i < j;\n    });\n\n    bool improved;\n    do {\n        improved = false;\n        for (int v : orderDesc) {\n            int oldParent = parent[v];\n            int oldDepth = getDepth(v);\n            long long bestDelta = 0;\n            int bestP = oldParent;\n            int bestNewDepth = oldDepth;\n\n            for (int u : adj[v]) {\n                if (u == oldParent) continue;\n\n                // Check if u is in subtree of v (to avoid cycles)\n                int x = u;\n                bool cyc = false;\n                while (x != -1) {\n                    if (x == v) {\n                        cyc = true;\n                        break;\n                    }\n                    x = parent[x];\n                }\n                if (cyc) continue;\n\n                int du = getDepth(u);\n                int newDepth = du + 1;\n                if (newDepth > H) continue;\n                if (newDepth + subHeight[v] > H) continue;\n\n                long long deltaScore = (long long)(newDepth - oldDepth) * subtreeSum[v];\n                if (deltaScore > bestDelta) {\n                    bestDelta = deltaScore;\n                    bestP = u;\n                    bestNewDepth = newDepth;\n                }\n            }\n\n            if (bestP != oldParent && bestDelta > 0) {\n                reparentFn(v, bestP, oldDepth, bestNewDepth);\n                improved = true;\n            }\n        }\n    } while (improved);\n\n    // ---------- Simulated annealing to escape local maxima ----------\n    FastRand rng;\n    // Time budget for SA only; initial phases are extra but cheap.\n    const double TIME_LIMIT = 1.7; // seconds\n    const double T0 = 200000.0;\n    const double T1 = 10.0;\n\n    auto startTime = chrono::steady_clock::now();\n    double T = T0;\n\n    int iter = 0;\n    while (true) {\n        ++iter;\n        if ((iter & 1023) == 0) {\n            double elapsed = chrono::duration<double>(chrono::steady_clock::now() - startTime).count();\n            if (elapsed > TIME_LIMIT) break;\n            double t = elapsed / TIME_LIMIT;\n            if (t > 1.0) t = 1.0;\n            T = T0 + (T1 - T0) * t; // linear cooling\n            if (T < T1) T = T1;\n        }\n\n        int v = rng.nextInt(N);\n        int deg = (int)adj[v].size();\n        if (deg == 0 && parent[v] == -1) continue; // just in case\n\n        // Choose a new parent: one of neighbors or -1 (make root)\n        int choice = rng.nextInt(deg + 1); // 0..deg\n        int newParent = (choice == deg ? -1 : adj[v][choice]);\n\n        if (newParent == parent[v]) continue;\n\n        // Cycle check (only needed if newParent != -1)\n        if (newParent != -1) {\n            int x = newParent;\n            bool cyc = false;\n            while (x != -1) {\n                if (x == v) {\n                    cyc = true;\n                    break;\n                }\n                x = parent[x];\n            }\n            if (cyc) continue;\n        }\n\n        int oldDepth = getDepth(v);\n        int newDepth;\n        if (newParent == -1) {\n            newDepth = 0;\n        } else {\n            int du = getDepth(newParent);\n            newDepth = du + 1;\n        }\n\n        if (newDepth > H) continue;\n        if (newDepth + subHeight[v] > H) continue;\n\n        long long deltaScore = (long long)(newDepth - oldDepth) * subtreeSum[v];\n\n        if (deltaScore >= 0) {\n            reparentFn(v, newParent, oldDepth, newDepth);\n        } else {\n            double prob = exp((double)deltaScore / T);  // deltaScore < 0\n            double r = rng.nextDouble();\n            if (r < prob) {\n                reparentFn(v, newParent, oldDepth, newDepth);\n            }\n        }\n    }\n\n    // ---------- Final greedy hill climb after SA ----------\n    do {\n        improved = false;\n        for (int v : orderDesc) {\n            int oldParent = parent[v];\n            int oldDepth = getDepth(v);\n            long long bestDelta = 0;\n            int bestP = oldParent;\n            int bestNewDepth = oldDepth;\n\n            for (int u : adj[v]) {\n                if (u == oldParent) continue;\n\n                // Check if u is in subtree of v (to avoid cycles)\n                int x = u;\n                bool cyc = false;\n                while (x != -1) {\n                    if (x == v) {\n                        cyc = true;\n                        break;\n                    }\n                    x = parent[x];\n                }\n                if (cyc) continue;\n\n                int du = getDepth(u);\n                int newDepth = du + 1;\n                if (newDepth > H) continue;\n                if (newDepth + subHeight[v] > H) continue;\n\n                long long deltaScore = (long long)(newDepth - oldDepth) * subtreeSum[v];\n                if (deltaScore > bestDelta) {\n                    bestDelta = deltaScore;\n                    bestP = u;\n                    bestNewDepth = newDepth;\n                }\n            }\n\n            if (bestP != oldParent && bestDelta > 0) {\n                reparentFn(v, bestP, oldDepth, bestNewDepth);\n                improved = true;\n            }\n        }\n    } while (improved);\n\n    // ---------- Output best found solution ----------\n    for (int i = 0; i < N; ++i) {\n        if (i) cout << ' ';\n        cout << bestParent[i];\n    }\n    cout << '\\n';\n\n    return 0;\n}","ahc042":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Operation {\n    char dir;      // 'U', 'D', 'L', 'R' : direction of the first half\n    int  p;        // row or column index\n    int  len;      // number of shifts in each direction\n    int  cost;     // 2 * len\n    uint64_t mask; // which Oni are removed by this operation (global Oni indices)\n};\n\nstruct LocOp {\n    int cost;\n    uint64_t mask; // mask over local Oni indices\n    int gidx;      // corresponding global operation index\n};\n\nconst int INF = 1e9;\nconst int DP_THRESH = 16; // max Oni in a component to solve exactly with DP\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    if (!(cin >> N)) return 0;\n    vector<string> C(N);\n    for (int i = 0; i < N; ++i) cin >> C[i];\n\n    // Collect Oni and Fuku positions\n    vector<pair<int,int>> oni;  // (row,col) for each Oni\n    vector<vector<int>> oni_id(N, vector<int>(N, -1));\n    vector<vector<bool>> fuku(N, vector<bool>(N, false));\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            char ch = C[i][j];\n            if (ch == 'x') {\n                int id = (int)oni.size();\n                oni.emplace_back(i, j);\n                oni_id[i][j] = id;\n            } else if (ch == 'o') {\n                fuku[i][j] = true;\n            }\n        }\n    }\n\n    int M = (int)oni.size(); // number of Oni, should be 2N\n    if (M == 0) {\n        // No Oni: nothing to do\n        return 0;\n    }\n\n    // Prefix sums of Fuku for rows and columns\n    vector<vector<int>> row_pref(N, vector<int>(N, 0));\n    vector<vector<int>> col_pref(N, vector<int>(N, 0));\n\n    for (int i = 0; i < N; ++i) {\n        int acc = 0;\n        for (int j = 0; j < N; ++j) {\n            if (fuku[i][j]) acc++;\n            row_pref[i][j] = acc;\n        }\n    }\n    for (int j = 0; j < N; ++j) {\n        int acc = 0;\n        for (int i = 0; i < N; ++i) {\n            if (fuku[i][j]) acc++;\n            col_pref[j][i] = acc;\n        }\n    }\n\n    vector<Operation> ops;\n    ops.reserve(4 * N * N);\n\n    // Build all safe column operations\n    for (int j = 0; j < N; ++j) {\n        int total_fuku_col = col_pref[j][N-1];\n\n        // Up-prefix [0..h]\n        for (int h = 0; h < N; ++h) {\n            if (col_pref[j][h] == 0) { // no Fuku in [0..h]\n                uint64_t mask = 0;\n                for (int id = 0; id < M; ++id) {\n                    auto [r, c] = oni[id];\n                    if (c == j && r <= h) {\n                        mask |= (1ULL << id);\n                    }\n                }\n                if (mask) {\n                    int len = h + 1;\n                    Operation op;\n                    op.dir = 'U';\n                    op.p = j;\n                    op.len = len;\n                    op.cost = 2 * len;\n                    op.mask = mask;\n                    ops.push_back(op);\n                }\n            }\n        }\n\n        // Down-suffix [h..N-1]\n        for (int h = 0; h < N; ++h) {\n            int fuku_cnt = total_fuku_col - (h > 0 ? col_pref[j][h-1] : 0);\n            if (fuku_cnt == 0) { // no Fuku in [h..N-1]\n                uint64_t mask = 0;\n                for (int id = 0; id < M; ++id) {\n                    auto [r, c] = oni[id];\n                    if (c == j && r >= h) {\n                        mask |= (1ULL << id);\n                    }\n                }\n                if (mask) {\n                    int len = N - h;\n                    Operation op;\n                    op.dir = 'D';\n                    op.p = j;\n                    op.len = len;\n                    op.cost = 2 * len;\n                    op.mask = mask;\n                    ops.push_back(op);\n                }\n            }\n        }\n    }\n\n    // Build all safe row operations\n    for (int i = 0; i < N; ++i) {\n        int total_fuku_row = row_pref[i][N-1];\n\n        // Left-prefix [0..h]\n        for (int h = 0; h < N; ++h) {\n            if (row_pref[i][h] == 0) { // no Fuku in [0..h]\n                uint64_t mask = 0;\n                for (int id = 0; id < M; ++id) {\n                    auto [r, c] = oni[id];\n                    if (r == i && c <= h) {\n                        mask |= (1ULL << id);\n                    }\n                }\n                if (mask) {\n                    int len = h + 1;\n                    Operation op;\n                    op.dir = 'L';\n                    op.p = i;\n                    op.len = len;\n                    op.cost = 2 * len;\n                    op.mask = mask;\n                    ops.push_back(op);\n                }\n            }\n        }\n\n        // Right-suffix [h..N-1]\n        for (int h = 0; h < N; ++h) {\n            int fuku_cnt = total_fuku_row - (h > 0 ? row_pref[i][h-1] : 0);\n            if (fuku_cnt == 0) { // no Fuku in [h..N-1]\n                uint64_t mask = 0;\n                for (int id = 0; id < M; ++id) {\n                    auto [r, c] = oni[id];\n                    if (r == i && c >= h) {\n                        mask |= (1ULL << id);\n                    }\n                }\n                if (mask) {\n                    int len = N - h;\n                    Operation op;\n                    op.dir = 'R';\n                    op.p = i;\n                    op.len = len;\n                    op.cost = 2 * len;\n                    op.mask = mask;\n                    ops.push_back(op);\n                }\n            }\n        }\n    }\n\n    if (ops.empty()) {\n        // Should not happen due to guarantees\n        return 0;\n    }\n\n    // Deduplicate operations by identical mask, keeping the cheapest one\n    sort(ops.begin(), ops.end(), [](const Operation &a, const Operation &b) {\n        if (a.mask != b.mask) return a.mask < b.mask;\n        if (a.cost != b.cost) return a.cost < b.cost;\n        if (a.dir != b.dir)   return a.dir < b.dir;\n        if (a.p != b.p)       return a.p < b.p;\n        return a.len < b.len;\n    });\n\n    {\n        vector<Operation> filtered;\n        filtered.reserve(ops.size());\n        for (int i = 0; i < (int)ops.size(); ) {\n            int j = i + 1;\n            Operation best = ops[i];\n            while (j < (int)ops.size() && ops[j].mask == ops[i].mask) {\n                if (ops[j].cost < best.cost) best = ops[j];\n                ++j;\n            }\n            filtered.push_back(best);\n            i = j;\n        }\n        ops.swap(filtered);\n    }\n\n    // Dominated-set elimination: remove op_j if its mask is subset of op_i and cost_j >= cost_i\n    sort(ops.begin(), ops.end(), [](const Operation &a, const Operation &b) {\n        if (a.cost != b.cost) return a.cost < b.cost;\n        return a.mask < b.mask;\n    });\n\n    {\n        int K = (int)ops.size();\n        vector<bool> alive(K, true);\n        for (int i = 0; i < K; ++i) {\n            if (!alive[i]) continue;\n            uint64_t mi = ops[i].mask;\n            for (int j = i + 1; j < K; ++j) {\n                if (!alive[j]) continue;\n                uint64_t mj = ops[j].mask;\n                if ((mj & ~mi) == 0ULL) {\n                    // mj is subset of mi with cost_j >= cost_i => dominated\n                    alive[j] = false;\n                }\n            }\n        }\n        vector<Operation> filtered;\n        filtered.reserve(K);\n        for (int i = 0; i < K; ++i) if (alive[i]) filtered.push_back(ops[i]);\n        ops.swap(filtered);\n    }\n\n    int K_ops = (int)ops.size();\n    if (K_ops == 0) return 0;\n\n    // Build cover lists: for each Oni, which operations cover it\n    vector<vector<int>> cover_ops(M);\n    for (int idx = 0; idx < K_ops; ++idx) {\n        uint64_t m = ops[idx].mask;\n        while (m) {\n            int b = __builtin_ctzll(m);\n            m &= m - 1;\n            cover_ops[b].push_back(idx);\n        }\n    }\n\n    // Each Oni must be coverable\n    for (int i = 0; i < M; ++i) {\n        if (cover_ops[i].empty()) {\n            // Should not happen\n            return 0;\n        }\n    }\n\n    uint64_t all_mask = (M == 64) ? ~0ULL : ((1ULL << M) - 1);\n\n    // Build connected components on bipartite graph (Oni and Ops)\n    vector<int> oni_comp(M, -1);\n    vector<int> op_comp(K_ops, -1);\n    int comp_cnt = 0;\n    for (int i = 0; i < M; ++i) {\n        if (oni_comp[i] != -1) continue;\n        // BFS\n        queue<int> q;\n        oni_comp[i] = comp_cnt;\n        q.push(i); // Oni node: 0..M-1; Ops: M..M+K_ops-1\n        while (!q.empty()) {\n            int v = q.front();\n            q.pop();\n            if (v < M) {\n                // Oni node\n                int o = v;\n                for (int op_idx : cover_ops[o]) {\n                    if (op_comp[op_idx] == -1) {\n                        op_comp[op_idx] = comp_cnt;\n                        q.push(M + op_idx);\n                    }\n                }\n            } else {\n                // Operation node\n                int op_idx = v - M;\n                uint64_t m = ops[op_idx].mask;\n                while (m) {\n                    int b = __builtin_ctzll(m);\n                    m &= m - 1;\n                    if (oni_comp[b] == -1) {\n                        oni_comp[b] = comp_cnt;\n                        q.push(b);\n                    }\n                }\n            }\n        }\n        ++comp_cnt;\n    }\n\n    vector<vector<int>> comp_oni(comp_cnt), comp_ops(comp_cnt);\n    for (int i = 0; i < M; ++i) {\n        comp_oni[oni_comp[i]].push_back(i);\n    }\n    for (int k = 0; k < K_ops; ++k) {\n        comp_ops[op_comp[k]].push_back(k);\n    }\n\n    // Global solution: selected global operation indices\n    vector<bool> global_selected(K_ops, false);\n\n    // RNG\n    uint64_t seed = chrono::steady_clock::now().time_since_epoch().count();\n    mt19937_64 rng(seed);\n\n    // Helper: exact DP solver for one component (nO <= DP_THRESH)\n    auto solve_component_dp = [&](int nO, const vector<int> &oniList, const vector<int> &opsList) -> vector<int> {\n        // Map global Oni index -> local index\n        vector<int> g2l(M, -1);\n        for (int i = 0; i < nO; ++i) {\n            g2l[oniList[i]] = i;\n        }\n\n        vector<LocOp> locOps;\n        locOps.reserve(opsList.size());\n        for (int gidx : opsList) {\n            uint64_t gm = ops[gidx].mask;\n            uint64_t lm = 0;\n            uint64_t tmp = gm;\n            while (tmp) {\n                int b = __builtin_ctzll(tmp);\n                tmp &= tmp - 1;\n                int li = g2l[b];\n                if (li >= 0) lm |= (1ULL << li);\n            }\n            if (lm) {\n                LocOp lo{ops[gidx].cost, lm, gidx};\n                locOps.push_back(lo);\n            }\n        }\n\n        int Kc = (int)locOps.size();\n        if (Kc == 0) {\n            // Should not happen, but return empty\n            return {};\n        }\n\n        int FULL = (1 << nO) - 1;\n        int SZ = 1 << nO;\n        vector<int> dp(SZ, INF), prev_state(SZ, -1), prev_op(SZ, -1);\n        dp[0] = 0;\n\n        for (int s = 0; s < SZ; ++s) {\n            if (dp[s] == INF) continue;\n            int base = dp[s];\n            for (int j = 0; j < Kc; ++j) {\n                uint64_t nm = s | locOps[j].mask;\n                int ns = (int)nm;\n                int nc = base + locOps[j].cost;\n                if (nc < dp[ns]) {\n                    dp[ns] = nc;\n                    prev_state[ns] = s;\n                    prev_op[ns] = j;\n                }\n            }\n        }\n\n        if (dp[FULL] == INF) {\n            // Fallback (should not happen)\n            return {};\n        }\n\n        vector<int> chosen_loc;\n        int cur = FULL;\n        while (cur != 0) {\n            int po = prev_op[cur];\n            if (po < 0) break;\n            chosen_loc.push_back(po);\n            cur = prev_state[cur];\n        }\n\n        // Remove duplicates (just in case), and map to global indices\n        vector<bool> used_loc(Kc, false);\n        vector<int> chosen_glob;\n        chosen_glob.reserve(chosen_loc.size());\n        for (int idx : chosen_loc) {\n            if (!used_loc[idx]) {\n                used_loc[idx] = true;\n                chosen_glob.push_back(locOps[idx].gidx);\n            }\n        }\n        return chosen_glob;\n    };\n\n    // For heuristic solver per component (nO > DP_THRESH)\n    auto solve_component_heuristic = [&](int nO, const vector<int> &oniList, const vector<int> &opsList) -> vector<int> {\n        vector<int> g2l(M, -1);\n        for (int i = 0; i < nO; ++i) {\n            g2l[oniList[i]] = i;\n        }\n\n        vector<LocOp> locOps;\n        locOps.reserve(opsList.size());\n        for (int gidx : opsList) {\n            uint64_t gm = ops[gidx].mask;\n            uint64_t lm = 0;\n            uint64_t tmp = gm;\n            while (tmp) {\n                int b = __builtin_ctzll(tmp);\n                tmp &= tmp - 1;\n                int li = g2l[b];\n                if (li >= 0) lm |= (1ULL << li);\n            }\n            if (lm) {\n                LocOp lo{ops[gidx].cost, lm, gidx};\n                locOps.push_back(lo);\n            }\n        }\n\n        int Kc = (int)locOps.size();\n        if (Kc == 0) {\n            // Fallback: nothing\n            return {};\n        }\n\n        // Build cover list for local Oni\n        vector<vector<int>> cover_ops_loc(nO);\n        for (int idx = 0; idx < Kc; ++idx) {\n            uint64_t m = locOps[idx].mask;\n            while (m) {\n                int b = __builtin_ctzll(m);\n                m &= m - 1;\n                cover_ops_loc[b].push_back(idx);\n            }\n        }\n        // If any Oni isn't covered, something's wrong, but skip check.\n\n        // Weights: rarer Oni have higher weight\n        vector<double> oni_weight(nO);\n        for (int i = 0; i < nO; ++i) {\n            int deg = (int)cover_ops_loc[i].size();\n            oni_weight[i] = (deg > 0 ? 1.0 / deg : 1.0);\n        }\n\n        uint64_t FULL = (nO == 64 ? ~0ULL : ((1ULL << nO) - 1));\n\n        // Helper: prune redundant selected operations\n        auto prune_selected = [&](vector<bool> &selected, int &total_cost, vector<int> &cover_count) {\n            bool changed = true;\n            while (changed) {\n                changed = false;\n                uint64_t singular_mask = 0;\n                for (int i = 0; i < nO; ++i) {\n                    if (cover_count[i] == 1) singular_mask |= (1ULL << i);\n                }\n                for (int op_idx = 0; op_idx < Kc; ++op_idx) {\n                    if (!selected[op_idx]) continue;\n                    if ((locOps[op_idx].mask & singular_mask) == 0) {\n                        // Removing this op won't uncover any Oni\n                        selected[op_idx] = false;\n                        total_cost -= locOps[op_idx].cost;\n                        uint64_t m = locOps[op_idx].mask;\n                        while (m) {\n                            int b = __builtin_ctzll(m);\n                            m &= m - 1;\n                            cover_count[b]--;\n                        }\n                        changed = true;\n                    }\n                }\n            }\n        };\n\n        // Local search on a solution (list of local op indices)\n        auto local_search = [&](vector<int> &sel, int &cost) {\n            vector<bool> selected(Kc, false);\n            vector<int> cover_count(nO, 0);\n            int total_cost = 0;\n\n            for (int idx : sel) {\n                if (!selected[idx]) {\n                    selected[idx] = true;\n                    total_cost += locOps[idx].cost;\n                    uint64_t m = locOps[idx].mask;\n                    while (m) {\n                        int b = __builtin_ctzll(m);\n                        m &= m - 1;\n                        cover_count[b]++;\n                    }\n                }\n            }\n\n            prune_selected(selected, total_cost, cover_count);\n\n            for (int i = 0; i < nO; ++i) {\n                if (cover_count[i] == 0) {\n                    return;\n                }\n            }\n\n            vector<int> mark(Kc, 0);\n            int currentMark = 1;\n            vector<int> cand;\n            cand.reserve(64);\n\n            bool improved = true;\n            while (improved) {\n                improved = false;\n\n                uint64_t singular_mask = 0;\n                for (int i = 0; i < nO; ++i) {\n                    if (cover_count[i] == 1) singular_mask |= (1ULL << i);\n                }\n\n                // 1-for-1 replacements\n                for (int a = 0; a < Kc && !improved; ++a) {\n                    if (!selected[a]) continue;\n                    uint64_t U_mask = locOps[a].mask & singular_mask;\n                    if (!U_mask) continue;\n\n                    cand.clear();\n                    if (++currentMark == INT_MAX) {\n                        fill(mark.begin(), mark.end(), 0);\n                        currentMark = 1;\n                    }\n                    uint64_t tmp = U_mask;\n                    while (tmp) {\n                        int b = __builtin_ctzll(tmp);\n                        tmp &= tmp - 1;\n                        for (int op_idx : cover_ops_loc[b]) {\n                            if (mark[op_idx] != currentMark) {\n                                mark[op_idx] = currentMark;\n                                cand.push_back(op_idx);\n                            }\n                        }\n                    }\n\n                    for (int b_idx : cand) {\n                        if (selected[b_idx]) continue;\n                        if (locOps[b_idx].cost >= locOps[a].cost) continue;\n                        if ((locOps[b_idx].mask & U_mask) == U_mask) {\n                            // 1-for-1: a -> b_idx\n                            selected[a] = false;\n                            selected[b_idx] = true;\n                            total_cost += locOps[b_idx].cost - locOps[a].cost;\n\n                            uint64_t ma = locOps[a].mask;\n                            while (ma) {\n                                int bit = __builtin_ctzll(ma);\n                                ma &= ma - 1;\n                                cover_count[bit]--;\n                            }\n                            uint64_t mb = locOps[b_idx].mask;\n                            while (mb) {\n                                int bit = __builtin_ctzll(mb);\n                                mb &= mb - 1;\n                                cover_count[bit]++;\n                            }\n\n                            prune_selected(selected, total_cost, cover_count);\n                            improved = true;\n                            break;\n                        }\n                    }\n                }\n\n                if (improved) continue;\n\n                // 1-for-2 replacements\n                singular_mask = 0;\n                for (int i = 0; i < nO; ++i) {\n                    if (cover_count[i] == 1) singular_mask |= (1ULL << i);\n                }\n\n                for (int a = 0; a < Kc && !improved; ++a) {\n                    if (!selected[a]) continue;\n                    uint64_t U_mask = locOps[a].mask & singular_mask;\n                    if (!U_mask) continue;\n\n                    cand.clear();\n                    if (++currentMark == INT_MAX) {\n                        fill(mark.begin(), mark.end(), 0);\n                        currentMark = 1;\n                    }\n                    uint64_t tmp = U_mask;\n                    while (tmp) {\n                        int b = __builtin_ctzll(tmp);\n                        tmp &= tmp - 1;\n                        for (int op_idx : cover_ops_loc[b]) {\n                            if (mark[op_idx] != currentMark) {\n                                mark[op_idx] = currentMark;\n                                cand.push_back(op_idx);\n                            }\n                        }\n                    }\n\n                    int csz = (int)cand.size();\n                    for (int i1 = 0; i1 < csz && !improved; ++i1) {\n                        int b_idx = cand[i1];\n                        if (selected[b_idx]) continue;\n                        for (int i2 = i1 + 1; i2 < csz; ++i2) {\n                            int c_idx = cand[i2];\n                            if (selected[c_idx]) continue;\n                            int newCost = locOps[b_idx].cost + locOps[c_idx].cost;\n                            if (newCost >= locOps[a].cost) continue;\n                            uint64_t union_mask = locOps[b_idx].mask | locOps[c_idx].mask;\n                            if ((union_mask & U_mask) == U_mask) {\n                                // 1-for-2: a -> b_idx, c_idx\n                                selected[a] = false;\n                                selected[b_idx] = true;\n                                selected[c_idx] = true;\n                                total_cost += newCost - locOps[a].cost;\n\n                                uint64_t ma = locOps[a].mask;\n                                while (ma) {\n                                    int bit = __builtin_ctzll(ma);\n                                    ma &= ma - 1;\n                                    cover_count[bit]--;\n                                }\n                                uint64_t mb = locOps[b_idx].mask;\n                                while (mb) {\n                                    int bit = __builtin_ctzll(mb);\n                                    mb &= mb - 1;\n                                    cover_count[bit]++;\n                                }\n                                uint64_t mc = locOps[c_idx].mask;\n                                while (mc) {\n                                    int bit = __builtin_ctzll(mc);\n                                    mc &= mc - 1;\n                                    cover_count[bit]++;\n                                }\n\n                                prune_selected(selected, total_cost, cover_count);\n                                improved = true;\n                                break;\n                            }\n                        }\n                    }\n                }\n            }\n\n            for (int i = 0; i < nO; ++i) {\n                if (cover_count[i] == 0) return;\n            }\n\n            vector<int> new_sel;\n            new_sel.reserve(nO);\n            for (int i = 0; i < Kc; ++i) if (selected[i]) new_sel.push_back(i);\n            sel.swap(new_sel);\n            cost = total_cost;\n        };\n\n        auto run_greedy = [&](int score_type, int RCL_SIZE) -> pair<int, vector<int>> {\n            uint64_t uncovered = FULL;\n            vector<int> chosen;\n            chosen.reserve(nO);\n            int greedy_cost = 0;\n\n            while (uncovered) {\n                vector<double> bestRatios(RCL_SIZE, -1.0);\n                vector<int> bestIdx(RCL_SIZE, -1);\n\n                for (int i = 0; i < Kc; ++i) {\n                    uint64_t gainMask = locOps[i].mask & uncovered;\n                    if (!gainMask) continue;\n\n                    int nGain = __builtin_popcountll(gainMask);\n                    double wGain = 0.0;\n                    uint64_t tmp = gainMask;\n                    while (tmp) {\n                        int b = __builtin_ctzll(tmp);\n                        tmp &= tmp - 1;\n                        wGain += oni_weight[b];\n                    }\n\n                    double ratio;\n                    switch (score_type) {\n                        case 0: // weighted gain / cost\n                            ratio = wGain / (double)locOps[i].cost;\n                            break;\n                        case 1: // raw gain / cost\n                            ratio = (double)nGain / (double)locOps[i].cost;\n                            break;\n                        case 2: // gain / sqrt(cost)\n                            ratio = (double)nGain / sqrt((double)locOps[i].cost);\n                            break;\n                        case 3: // (weighted gain)^2 / cost\n                        default:\n                            ratio = (wGain * wGain) / (double)locOps[i].cost;\n                            break;\n                    }\n\n                    for (int k = 0; k < RCL_SIZE; ++k) {\n                        if (ratio > bestRatios[k]) {\n                            for (int sh = RCL_SIZE - 1; sh > k; --sh) {\n                                bestRatios[sh] = bestRatios[sh - 1];\n                                bestIdx[sh] = bestIdx[sh - 1];\n                            }\n                            bestRatios[k] = ratio;\n                            bestIdx[k] = i;\n                            break;\n                        }\n                    }\n                }\n\n                if (bestIdx[0] == -1) {\n                    break; // should not\n                }\n\n                int rcl_end = 0;\n                while (rcl_end + 1 < RCL_SIZE && bestIdx[rcl_end + 1] != -1) ++rcl_end;\n                uniform_int_distribution<int> dist(0, rcl_end);\n                int chosen_pos = dist(rng);\n                int op_idx = bestIdx[chosen_pos];\n\n                chosen.push_back(op_idx);\n                uint64_t gainMask = locOps[op_idx].mask & uncovered;\n                uncovered &= ~gainMask;\n                greedy_cost += locOps[op_idx].cost;\n            }\n\n            if (uncovered) {\n                return make_pair(INF, vector<int>());\n            }\n\n            vector<bool> selected(Kc, false);\n            vector<int> cover_count(nO, 0);\n            int total_cost = 0;\n            for (int idx : chosen) {\n                if (!selected[idx]) {\n                    selected[idx] = true;\n                    total_cost += locOps[idx].cost;\n                    uint64_t m = locOps[idx].mask;\n                    while (m) {\n                        int b = __builtin_ctzll(m);\n                        m &= m - 1;\n                        cover_count[b]++;\n                    }\n                }\n            }\n\n            prune_selected(selected, total_cost, cover_count);\n\n            for (int i = 0; i < nO; ++i) {\n                if (cover_count[i] == 0) return make_pair(INF, vector<int>());\n            }\n\n            vector<int> result;\n            result.reserve(nO);\n            for (int i = 0; i < Kc; ++i) if (selected[i]) result.push_back(i);\n            return make_pair(total_cost, move(result));\n        };\n\n        int best_cost = INF;\n        vector<int> best_sel_loc;\n        const int MAX_RUNS = 80;\n        uniform_int_distribution<int> scoreDist(0, 3);\n        uniform_int_distribution<int> rclDist(2, 5);\n\n        for (int iter = 0; iter < MAX_RUNS; ++iter) {\n            int score_type = scoreDist(rng);\n            int RCL_SIZE = rclDist(rng);\n            auto [cost, sel] = run_greedy(score_type, RCL_SIZE);\n            if (cost >= INF) continue;\n\n            int ls_cost = cost;\n            vector<int> ls_sel = sel;\n            local_search(ls_sel, ls_cost);\n\n            uint64_t covered = 0;\n            for (int idx : ls_sel) covered |= locOps[idx].mask;\n            if (covered != FULL) continue;\n\n            if (ls_cost < best_cost) {\n                best_cost = ls_cost;\n                best_sel_loc = move(ls_sel);\n            }\n        }\n\n        // Fallback: simple greedy if no solution found\n        if (best_sel_loc.empty()) {\n            auto [cost, sel] = run_greedy(1, 1);\n            if (cost < INF) {\n                best_cost = cost;\n                best_sel_loc = move(sel);\n            }\n        }\n\n        // Map to global indices\n        vector<int> res;\n        for (int idx : best_sel_loc) {\n            res.push_back(locOps[idx].gidx);\n        }\n        return res;\n    };\n\n    // Solve each component independently\n    for (int c = 0; c < comp_cnt; ++c) {\n        const auto &oniList = comp_oni[c];\n        const auto &opsList = comp_ops[c];\n        int nO = (int)oniList.size();\n        if (nO == 0 || opsList.empty()) continue;\n\n        vector<int> chosen_global;\n        if (nO <= DP_THRESH) {\n            chosen_global = solve_component_dp(nO, oniList, opsList);\n        } else {\n            chosen_global = solve_component_heuristic(nO, oniList, opsList);\n        }\n\n        for (int gidx : chosen_global) {\n            global_selected[gidx] = true;\n        }\n    }\n\n    // Build move sequence from selected global operations\n    vector<pair<char,int>> moves;\n    moves.reserve(1600);\n\n    for (int idx = 0; idx < K_ops; ++idx) {\n        if (!global_selected[idx]) continue;\n        const Operation &op = ops[idx];\n        char d1 = op.dir;\n        char d2;\n        if      (d1 == 'U') d2 = 'D';\n        else if (d1 == 'D') d2 = 'U';\n        else if (d1 == 'L') d2 = 'R';\n        else               d2 = 'L';\n\n        for (int k = 0; k < op.len; ++k) moves.emplace_back(d1, op.p);\n        for (int k = 0; k < op.len; ++k) moves.emplace_back(d2, op.p);\n    }\n\n    int T = (int)moves.size();\n    if (T > 4 * N * N) {\n        // Should not happen, but be safe.\n        return 0;\n    }\n\n    for (auto &mv : moves) {\n        cout << mv.first << ' ' << mv.second << '\\n';\n    }\n\n    return 0;\n}","ahc044":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const int MAXN = 100;\n\nstruct Candidate {\n    int a[MAXN];\n    int b[MAXN];\n    int t[MAXN];\n    int used[MAXN][2]; // edge usage counts: 0 -> a[i], 1 -> b[i]\n    long long E;\n};\n\n// Rotor-router simulation for L weeks, also records edge usage\nvoid evalCandidate(Candidate &cand, int N, int L, const vector<long long> &T) {\n    static int rotor[MAXN];\n    for (int i = 0; i < N; ++i) {\n        cand.t[i] = 0;\n        rotor[i] = 0;\n        cand.used[i][0] = cand.used[i][1] = 0;\n    }\n\n    int cur = 0;  // week 1 cleaner is 0\n\n    // weeks 1..L-1: decide next cleaner\n    for (int week = 0; week < L - 1; ++week) {\n        int x = cur;\n        cand.t[x]++;\n\n        int e = rotor[x];\n        rotor[x] ^= 1;\n        int nxt = (e == 0 ? cand.a[x] : cand.b[x]);\n        cand.used[x][e]++;\n\n        cur = nxt;\n    }\n    // last week: count the final cleaner\n    cand.t[cur]++;\n\n    long long E = 0;\n    for (int i = 0; i < N; ++i) {\n        E += llabs((long long)cand.t[i] - T[i]);\n    }\n    cand.E = E;\n}\n\n// Majority-based initial candidate from an \"ideal\" sequence\nCandidate buildMajorityCandidate(int N, int L, const vector<long long> &T, mt19937_64 &rng) {\n    Candidate cand;\n\n    // Work copy of T, ensure employee 0 appears at least once\n    vector<int> Twork(N);\n    for (int i = 0; i < N; ++i) Twork[i] = (int)T[i];\n\n    if (Twork[0] == 0) {\n        int j = 1;\n        for (int i = 2; i < N; ++i) {\n            if (Twork[i] > Twork[j]) j = i;\n        }\n        if (Twork[j] > 0) {\n            Twork[0] = 1;\n            Twork[j]--;\n        } else {\n            for (int i = 1; i < N; ++i) {\n                if (Twork[i] > 0) {\n                    Twork[i]--;\n                    break;\n                }\n            }\n            Twork[0] = 1;\n        }\n    }\n\n    // Build sequence of length L with counts Twork\n    vector<int> seq(L);\n    int pos = 0;\n    for (int i = 0; i < N; ++i) {\n        for (int k = 0; k < Twork[i]; ++k) {\n            if (pos < L) seq[pos++] = i;\n        }\n    }\n    if (pos < L) {\n        for (; pos < L; ++pos) seq[pos] = 0;\n    } else if (pos > L) {\n        seq.resize(L);\n    }\n\n    shuffle(seq.begin(), seq.end(), rng);\n\n    // Ensure seq[0] == 0 (week1 cleaner is 0)\n    if (seq[0] != 0) {\n        for (int i = 1; i < L; ++i) {\n            if (seq[i] == 0) {\n                swap(seq[0], seq[i]);\n                break;\n            }\n        }\n        seq[0] = 0; // safety\n    }\n\n    vector<vector<int>> freqOdd(N, vector<int>(N, 0));\n    vector<vector<int>> freqEven(N, vector<int>(N, 0));\n    vector<int> cntVisit(N, 0);\n\n    for (int i = 0; i < L - 1; ++i) {\n        int x = seq[i];\n        int y = seq[i + 1];\n        int k = ++cntVisit[x];\n        if (k & 1) freqOdd[x][y]++;\n        else       freqEven[x][y]++;\n    }\n\n    // Fallback destination: employee with largest T[i]\n    int fallback = 0;\n    for (int i = 1; i < N; ++i) {\n        if (T[i] > T[fallback]) fallback = i;\n    }\n\n    for (int x = 0; x < N; ++x) {\n        int best_j = fallback;\n        int best_c = 0;\n        // a_x from odd visits\n        for (int y = 0; y < N; ++y) {\n            if (freqOdd[x][y] > best_c) {\n                best_c = freqOdd[x][y];\n                best_j = y;\n            }\n        }\n        cand.a[x] = best_j;\n\n        best_j = fallback;\n        best_c = 0;\n        // b_x from even visits\n        for (int y = 0; y < N; ++y) {\n            if (freqEven[x][y] > best_c) {\n                best_c = freqEven[x][y];\n                best_j = y;\n            }\n        }\n        cand.b[x] = best_j;\n    }\n\n    evalCandidate(cand, N, L, T);\n    return cand;\n}\n\n// Build destination template from T (simple T+1 weighting)\nvector<int> buildDestTemplate(int N, const vector<long long> &T) {\n    vector<double> w(N);\n    double sumW = 0.0;\n    for (int i = 0; i < N; ++i) {\n        w[i] = (double)T[i] + 1.0; // +1 to avoid zero\n        sumW += w[i];\n    }\n    int totalEdges = 2 * N;\n\n    vector<double> frac(N);\n    vector<int> destCount(N, 0);\n    long long S = 0;\n\n    for (int i = 0; i < N; ++i) {\n        double val = totalEdges * w[i] / sumW;\n        int base = (int)floor(val);\n        destCount[i] = base;\n        frac[i] = val - base;\n        S += base;\n    }\n    int R = totalEdges - (int)S;\n    if (R < 0) R = 0;\n\n    vector<int> ord(N);\n    iota(ord.begin(), ord.end(), 0);\n    sort(ord.begin(), ord.end(), [&](int a, int b) {\n        return frac[a] > frac[b];\n    });\n    for (int k = 0; k < R && k < N; ++k) {\n        destCount[ord[k]]++;\n    }\n\n    vector<int> edgesDest;\n    edgesDest.reserve(totalEdges);\n    for (int i = 0; i < N; ++i) {\n        for (int c = 0; c < destCount[i]; ++c) {\n            edgesDest.push_back(i);\n        }\n    }\n    while ((int)edgesDest.size() > totalEdges) edgesDest.pop_back();\n    while ((int)edgesDest.size() < totalEdges) edgesDest.push_back(0);\n\n    return edgesDest;\n}\n\n// Build a random candidate from a given destination template\nCandidate buildRandomCandidateFromTemplate(const vector<int> &edgesTemplate,\n                                           int N, int L,\n                                           const vector<long long> &T,\n                                           mt19937_64 &rng) {\n    Candidate cand;\n    vector<int> edges = edgesTemplate; // copy\n    shuffle(edges.begin(), edges.end(), rng);\n\n    for (int i = 0; i < N; ++i) {\n        cand.a[i] = edges[2 * i];\n        cand.b[i] = edges[2 * i + 1];\n    }\n    evalCandidate(cand, N, L, T);\n    return cand;\n}\n\n// Random/diversification mutation of one node, guided by deficits\nvoid mutateNode(int idx,\n                Candidate &cand,\n                int N,\n                const vector<long long> &T,\n                const vector<int> &deficit,\n                const vector<int> &posIndices,\n                const vector<long long> &posPrefix,\n                long long sumPos,\n                const vector<long long> &Tprefix,\n                long long sumTw,\n                mt19937_64 &rng) {\n    auto samplePos = [&]() -> int {\n        if (sumPos <= 0 || posIndices.empty()) {\n            return idx; // fallback\n        }\n        long long r = (long long)(rng() % sumPos);\n        int pos = int(lower_bound(posPrefix.begin(), posPrefix.end(), r + 1) - posPrefix.begin());\n        if (pos < 0) pos = 0;\n        if (pos >= (int)posIndices.size()) pos = (int)posIndices.size() - 1;\n        return posIndices[pos];\n    };\n\n    auto sampleTdist = [&]() -> int {\n        if (sumTw <= 0) return idx;\n        long long r = (long long)(rng() % sumTw);\n        int pos = int(upper_bound(Tprefix.begin(), Tprefix.end(), r) - Tprefix.begin());\n        if (pos < 0) pos = 0;\n        if (pos >= N) pos = N - 1;\n        return pos;\n    };\n\n    if (deficit[idx] > 0) {\n        // Node needs more visits: encourage self-loop\n        cand.a[idx] = idx;\n        if (sumPos > 0) {\n            cand.b[idx] = samplePos();\n        } else {\n            cand.b[idx] = sampleTdist();\n        }\n    } else {\n        // Node has enough or too many visits: redirect outflows to under-visited nodes.\n        if (sumPos > 0) {\n            cand.a[idx] = samplePos();\n            cand.b[idx] = samplePos();\n        } else {\n            cand.a[idx] = sampleTdist();\n            cand.b[idx] = sampleTdist();\n        }\n    }\n\n    if (cand.a[idx] < 0) cand.a[idx] = 0;\n    if (cand.a[idx] >= N) cand.a[idx] = N - 1;\n    if (cand.b[idx] < 0) cand.b[idx] = 0;\n    if (cand.b[idx] >= N) cand.b[idx] = N - 1;\n}\n\n// Local search starting from bestLocal; updates globalBest if improved.\n// Stops when time (ms since startTime) exceeds allowedMs or iterations exhausted.\nvoid runLocalSearch(Candidate &bestLocal,\n                    Candidate &globalBest,\n                    int N, int L,\n                    const vector<long long> &T,\n                    const vector<long long> &Tprefix,\n                    long long sumTw,\n                    mt19937_64 &rng,\n                    const chrono::steady_clock::time_point &startTime,\n                    int allowedMs) {\n\n    vector<int> deficit(N);\n    for (int i = 0; i < N; ++i) {\n        deficit[i] = (int)(T[i] - bestLocal.t[i]);\n    }\n\n    vector<int> posIndices;\n    vector<long long> posPrefix;\n    long long sumPos = 0;\n\n    auto updatePosDist = [&]() {\n        posIndices.clear();\n        posPrefix.clear();\n        sumPos = 0;\n        for (int i = 0; i < N; ++i) {\n            if (deficit[i] > 0) {\n                posIndices.push_back(i);\n                sumPos += deficit[i];\n                posPrefix.push_back(sumPos);\n            }\n        }\n    };\n    updatePosDist();\n\n    const int LOCAL_ITER_MAX = 1000000000;\n\n    for (int iter = 0; iter < LOCAL_ITER_MAX; ++iter) {\n        if ((iter & 7) == 0) {\n            auto now = chrono::steady_clock::now();\n            long long elapsed = chrono::duration_cast<chrono::milliseconds>(now - startTime).count();\n            if (elapsed > allowedMs) break;\n        }\n\n        Candidate cand = bestLocal;  // copy\n\n        int numMut = 1;\n        if (iter > 200) numMut = 2;\n        if (iter > 400) numMut = 3;\n\n        auto samplePos = [&]() -> int {\n            if (sumPos <= 0 || posIndices.empty()) {\n                return (int)(rng() % N);\n            }\n            long long r = (long long)(rng() % sumPos);\n            int pos = int(lower_bound(posPrefix.begin(), posPrefix.end(), r + 1) - posPrefix.begin());\n            if (pos < 0) pos = 0;\n            if (pos >= (int)posIndices.size()) pos = (int)posIndices.size() - 1;\n            return posIndices[pos];\n        };\n\n        auto sampleTdist = [&]() -> int {\n            if (sumTw <= 0) return (int)(rng() % N);\n            long long r = (long long)(rng() % sumTw);\n            int pos = int(upper_bound(Tprefix.begin(), Tprefix.end(), r) - Tprefix.begin());\n            if (pos < 0) pos = 0;\n            if (pos >= N) pos = N - 1;\n            return pos;\n        };\n\n        bool usedTargeted = false;\n        bool canTarget = (!posIndices.empty());\n        bool doTargeted = canTarget && (iter % 3 != 2); // ~2/3 of iterations use targeted\n\n        if (doTargeted) {\n            struct EdgeInfo {\n                int x;\n                int edge; // 0 or 1\n                long long score;\n            };\n            vector<EdgeInfo> edges;\n            edges.reserve(2 * N);\n\n            // Build list of \"bad\" edges: many uses into over-visited nodes\n            for (int x = 0; x < N; ++x) {\n                for (int e = 0; e < 2; ++e) {\n                    int uses = bestLocal.used[x][e];\n                    if (uses <= 0) continue;\n                    int child = (e == 0 ? bestLocal.a[x] : bestLocal.b[x]);\n                    if (deficit[child] < 0) {\n                        long long score = (long long)uses * (long long)(-deficit[child]);\n                        edges.push_back({x, e, score});\n                    }\n                }\n            }\n\n            if (!edges.empty() && sumPos > 0) {\n                sort(edges.begin(), edges.end(),\n                     [](const EdgeInfo &p, const EdgeInfo &q) {\n                         return p.score > q.score;\n                     });\n\n                int Ktop = (int)edges.size();\n                if (Ktop > 20) Ktop = 20; // focus on top edges\n\n                for (int m = 0; m < numMut && m < Ktop; ++m) {\n                    int x = edges[m].x;\n                    int e = edges[m].edge;\n\n                    int oldChild = (e == 0 ? cand.a[x] : cand.b[x]);\n                    int newChild = oldChild;\n\n                    int tries = 0;\n                    while (tries < 5) {\n                        newChild = samplePos();\n                        if (newChild != oldChild) break;\n                        ++tries;\n                    }\n                    if (newChild == oldChild) {\n                        newChild = samplePos();\n                    }\n\n                    if (newChild < 0) newChild = 0;\n                    if (newChild >= N) newChild = N - 1;\n\n                    if (e == 0) cand.a[x] = newChild;\n                    else        cand.b[x] = newChild;\n                }\n                usedTargeted = true;\n            }\n        }\n\n        if (!usedTargeted) {\n            // Fallback / diversification: random node-based mutation\n            for (int k = 0; k < numMut; ++k) {\n                int idx = (int)(rng() % N);\n                mutateNode(idx, cand, N, T, deficit,\n                           posIndices, posPrefix, sumPos,\n                           Tprefix, sumTw, rng);\n            }\n        }\n\n        evalCandidate(cand, N, L, T);\n\n        if (cand.E < bestLocal.E) {\n            bestLocal = cand;\n            for (int i = 0; i < N; ++i) {\n                deficit[i] = (int)(T[i] - bestLocal.t[i]);\n            }\n            updatePosDist();\n        }\n\n        if (cand.E < globalBest.E) {\n            globalBest = cand;\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, L;\n    if (!(cin >> N >> L)) {\n        return 0;\n    }\n    vector<long long> T(N);\n    for (int i = 0; i < N; ++i) cin >> T[i];\n\n    mt19937_64 rng(123456789ULL);\n\n    auto startTime = chrono::steady_clock::now();\n    const int TIME_LIMIT_MS = 1950;\n\n    // Pre-build destination template from T\n    vector<int> destTemplate = buildDestTemplate(N, T);\n\n    // Build a pool of initial candidates\n    vector<Candidate> pool;\n    pool.reserve(64);\n\n    // Majority-based candidate\n    pool.push_back(buildMajorityCandidate(N, L, T, rng));\n\n    // Random candidates from destination template\n    const int INIT_RANDOM = 40;\n    for (int i = 0; i < INIT_RANDOM; ++i) {\n        pool.push_back(buildRandomCandidateFromTemplate(destTemplate, N, L, T, rng));\n    }\n\n    // Sort pool by error\n    sort(pool.begin(), pool.end(), [](const Candidate &a, const Candidate &b) {\n        return a.E < b.E;\n    });\n\n    // Global best starts as best of pool\n    Candidate globalBest = pool[0];\n\n    // Precompute T-weighted distribution for fallback sampling in local search\n    vector<long long> Tprefix(N);\n    long long sumTw = 0;\n    for (int i = 0; i < N; ++i) {\n        sumTw += (long long)T[i] + 1;\n        Tprefix[i] = sumTw;\n    }\n\n    // Multi-start local search from top seeds\n    int numSeeds = min(3, (int)pool.size());\n    for (int s = 0; s < numSeeds; ++s) {\n        auto now = chrono::steady_clock::now();\n        long long elapsed = chrono::duration_cast<chrono::milliseconds>(now - startTime).count();\n        if (elapsed > TIME_LIMIT_MS) break;\n\n        Candidate bestLocal = pool[s];\n\n        // Allocate time slices: 0.6, 0.85, 1.0 fractions of TIME_LIMIT_MS\n        double frac;\n        if (s == 0) frac = 0.6;\n        else if (s == 1) frac = 0.85;\n        else frac = 1.0;\n\n        int allowedMs = (int)(TIME_LIMIT_MS * frac);\n        runLocalSearch(bestLocal, globalBest, N, L, T, Tprefix, sumTw, rng, startTime, allowedMs);\n    }\n\n    // Output global best found a_i, b_i\n    for (int i = 0; i < N; ++i) {\n        int ai = globalBest.a[i];\n        int bi = globalBest.b[i];\n        if (ai < 0) ai = 0;\n        if (ai >= N) ai = N - 1;\n        if (bi < 0) bi = 0;\n        if (bi >= N) bi = N - 1;\n        cout << ai << ' ' << bi << '\\n';\n    }\n\n    return 0;\n}","ahc045":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int MAXN = 800;\n\nint N, M, Q, L, W;\nint G_in[400];                 // original group sizes\nint lx[MAXN], rx[MAXN], ly[MAXN], ry[MAXN];\nint cx[MAXN], cy[MAXN];        // centers\nint baseDist[MAXN][MAXN];      // squared approx distances\nuint8_t goodCnt[MAXN][MAXN];   // how many times edge appears in query-MST\n\nint B_bias = 0;                // bias in squared-distance units for MST selection\nint CROSS_PEN = 0;             // penalty in sqrt-distance units for cutting a good edge\n\n// Hilbert order of (x, y) with coordinates in [0, 2^pow_bits)\nstatic uint64_t hilbert_order(int x, int y, int pow_bits) {\n    uint64_t res = 0;\n    for (int s = pow_bits - 1; s >= 0; --s) {\n        int rx = (x >> s) & 1;\n        int ry = (y >> s) & 1;\n        res <<= 2;\n        res |= (uint64_t)((rx * 3) ^ ry);\n        if (ry == 0) {\n            if (rx == 1) {\n                x = ((1 << pow_bits) - 1) - x;\n                y = ((1 << pow_bits) - 1) - y;\n            }\n            std::swap(x, y);\n        }\n    }\n    return res;\n}\n\n// Build MST for one group using Prim with adjusted weights for selection only.\n// Edges are recorded in edgesOut; cost is NOT accumulated here.\nvoid buildMSTForGroup(const vector<int> &nodes,\n                      vector<pair<int,int>> &edgesOut) {\n    int m = (int)nodes.size();\n    if (m <= 1) return;\n\n    const int INF = 1000000007;\n    edgesOut.clear();\n    edgesOut.reserve(max(0, m - 1));\n\n    static int best[MAXN];\n    static int parentIdx[MAXN];\n    static bool used[MAXN];\n\n    for (int i = 0; i < m; ++i) {\n        best[i] = INF;\n        parentIdx[i] = -1;\n        used[i] = false;\n    }\n\n    int root = 0;\n    used[root] = true;\n    // Initialize distances from root\n    for (int j = 1; j < m; ++j) {\n        int u = nodes[root];\n        int v = nodes[j];\n        int w = baseDist[u][v];\n        if (B_bias > 0) {\n            uint8_t cnt = goodCnt[u][v];\n            if (cnt) {\n                int cnti = (int)cnt;\n                if (cnti > 3) cnti = 3;\n                int sub = B_bias * cnti;\n                w = max(0, w - sub);\n            }\n        }\n        best[j] = w;\n        parentIdx[j] = root;\n    }\n\n    for (int it = 1; it < m; ++it) {\n        int t = -1;\n        int val = INF;\n        for (int i = 0; i < m; ++i) {\n            if (!used[i] && best[i] < val) {\n                val = best[i];\n                t = i;\n            }\n        }\n        if (t == -1) break; // should not happen\n\n        used[t] = true;\n        int u = nodes[t];\n        int pIdx = parentIdx[t];\n        if (pIdx != -1) {\n            int v = nodes[pIdx];\n            edgesOut.emplace_back(u, v);\n        }\n\n        // Update distances using new node t\n        for (int i = 0; i < m; ++i) {\n            if (!used[i]) {\n                int uu = u;\n                int vv = nodes[i];\n                int w = baseDist[uu][vv];\n                if (B_bias > 0) {\n                    uint8_t cnt = goodCnt[uu][vv];\n                    if (cnt) {\n                        int cnti = (int)cnt;\n                        if (cnti > 3) cnti = 3;\n                        int sub = B_bias * cnti;\n                        w = max(0, w - sub);\n                    }\n                }\n                if (w < best[i]) {\n                    best[i] = w;\n                    parentIdx[i] = t;\n                }\n            }\n        }\n    }\n}\n\nstruct Solution {\n    vector<vector<int>> groups;\n    vector<vector<pair<int,int>>> edges;\n    long long cost; // approximate cost in sqrt-distance units + penalties\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    if (!(cin >> N >> M >> Q >> L >> W)) {\n        return 0;\n    }\n    for (int i = 0; i < M; ++i) cin >> G_in[i];\n    for (int i = 0; i < N; ++i) {\n        cin >> lx[i] >> rx[i] >> ly[i] >> ry[i];\n    }\n\n    // Approximate coordinates by centers\n    for (int i = 0; i < N; ++i) {\n        cx[i] = (lx[i] + rx[i]) / 2;\n        cy[i] = (ly[i] + ry[i]) / 2;\n    }\n\n    // Precompute squared distances between all pairs\n    for (int i = 0; i < N; ++i) {\n        baseDist[i][i] = 0;\n        for (int j = i + 1; j < N; ++j) {\n            long dx = (long)cx[i] - (long)cx[j];\n            long dy = (long)cy[i] - (long)cy[j];\n            long v = dx * dx + dy * dy;\n            if (v > INT_MAX) v = INT_MAX;\n            int d = (int)v;\n            baseDist[i][j] = baseDist[j][i] = d;\n        }\n    }\n\n    // Initialize goodCnt to zero\n    for (int i = 0; i < N; ++i) {\n        memset(goodCnt[i], 0, N * sizeof(uint8_t));\n    }\n\n    // Build primary Hilbert order (for queries)\n    const int HILBERT_BITS = 15; // 2^15 = 32768 > 10000\n    vector<pair<uint64_t,int>> hv(N);\n    for (int i = 0; i < N; ++i) {\n        uint64_t h = hilbert_order(cx[i], cy[i], HILBERT_BITS);\n        hv[i] = {h, i};\n    }\n    sort(hv.begin(), hv.end());\n    vector<int> hilbOrder(N);\n    for (int i = 0; i < N; ++i) hilbOrder[i] = hv[i].second;\n\n    // --------- Use queries on overlapping Hilbert windows ---------\n    vector<int> good_dists;            // squared distances of unique good edges\n    vector<pair<int,int>> goodEdges;   // list of unique good edges\n    good_dists.reserve(Q * L);\n    goodEdges.reserve(Q * L);\n\n    int qUsed = 0;\n\n    if (Q > 0 && L >= 2 && N > 1) {\n        if (N <= L) {\n            // One query on all cities\n            int len = N;\n            cout << \"? \" << len;\n            vector<int> subset(len);\n            for (int k = 0; k < len; ++k) {\n                subset[k] = hilbOrder[k];\n                cout << ' ' << subset[k];\n            }\n            cout << endl;\n\n            for (int t = 0; t < len - 1; ++t) {\n                int a, b;\n                cin >> a >> b;\n                if (goodCnt[a][b] < 255) {\n                    ++goodCnt[a][b];\n                    ++goodCnt[b][a];\n                    if (goodCnt[a][b] == 1) {\n                        good_dists.push_back(baseDist[a][b]);\n                        goodEdges.emplace_back(a, b);\n                    }\n                }\n            }\n            ++qUsed;\n        } else {\n            int maxQueries = Q;\n            int numerator = (N - L) + (maxQueries - 2);\n            int step = numerator / (maxQueries - 1);\n            if (step < 1) step = 1;\n\n            for (int start = 0; start < N && qUsed < Q; start += step) {\n                int len = min(L, N - start);\n                if (len < 2) break;\n                cout << \"? \" << len;\n                vector<int> subset(len);\n                for (int k = 0; k < len; ++k) {\n                    subset[k] = hilbOrder[start + k];\n                    cout << ' ' << subset[k];\n                }\n                cout << endl;\n\n                for (int t = 0; t < len - 1; ++t) {\n                    int a, b;\n                    cin >> a >> b;\n                    if (goodCnt[a][b] < 255) {\n                        ++goodCnt[a][b];\n                        ++goodCnt[b][a];\n                        if (goodCnt[a][b] == 1) {\n                            good_dists.push_back(baseDist[a][b]);\n                            goodEdges.emplace_back(a, b);\n                        }\n                    }\n                }\n                ++qUsed;\n            }\n        }\n    }\n\n    // Determine biases from collected good edge distances\n    if (!good_dists.empty()) {\n        sort(good_dists.begin(), good_dists.end());\n        int medDist = good_dists[good_dists.size() / 2]; // squared\n        if (medDist > 0) {\n            B_bias = max(1, medDist / 8); // squared units\n            int medSqrt = (int)floor(sqrt((double)medDist)); // approx median distance\n            CROSS_PEN = max(1, medSqrt / 2); // penalty in sqrt-distance units\n        } else {\n            B_bias = 0;\n            CROSS_PEN = 0;\n        }\n    } else {\n        B_bias = 0;\n        CROSS_PEN = 0;\n    }\n\n    // --------- Build multiple city orders ---------\n    vector<vector<int>> cityOrders;\n\n    // 1) Hilbert original (already computed)\n    cityOrders.push_back(hilbOrder);\n\n    // 2) Hilbert with flipped X\n    {\n        vector<pair<uint64_t,int>> v(N);\n        for (int i = 0; i < N; ++i) {\n            int fx = 10000 - cx[i];\n            int fy = cy[i];\n            uint64_t h = hilbert_order(fx, fy, HILBERT_BITS);\n            v[i] = {h, i};\n        }\n        sort(v.begin(), v.end());\n        vector<int> ord(N);\n        for (int i = 0; i < N; ++i) ord[i] = v[i].second;\n        cityOrders.push_back(std::move(ord));\n    }\n\n    // 3) Hilbert with flipped Y\n    {\n        vector<pair<uint64_t,int>> v(N);\n        for (int i = 0; i < N; ++i) {\n            int fx = cx[i];\n            int fy = 10000 - cy[i];\n            uint64_t h = hilbert_order(fx, fy, HILBERT_BITS);\n            v[i] = {h, i};\n        }\n        sort(v.begin(), v.end());\n        vector<int> ord(N);\n        for (int i = 0; i < N; ++i) ord[i] = v[i].second;\n        cityOrders.push_back(std::move(ord));\n    }\n\n    // 4) Lexicographic by (x, y)\n    {\n        vector<pair<pair<int,int>,int>> v(N);\n        for (int i = 0; i < N; ++i) {\n            v[i] = {{cx[i], cy[i]}, i};\n        }\n        sort(v.begin(), v.end());\n        vector<int> ord(N);\n        for (int i = 0; i < N; ++i) ord[i] = v[i].second;\n        cityOrders.push_back(std::move(ord));\n    }\n\n    // 5) Lexicographic by (y, x)\n    {\n        vector<pair<pair<int,int>,int>> v(N);\n        for (int i = 0; i < N; ++i) {\n            v[i] = {{cy[i], cx[i]}, i};\n        }\n        sort(v.begin(), v.end());\n        vector<int> ord(N);\n        for (int i = 0; i < N; ++i) ord[i] = v[i].second;\n        cityOrders.push_back(std::move(ord));\n    }\n\n    // --------- Precompute size orders ---------\n    vector<pair<int,int>> sizeDesc, sizeAsc, sizeOrig;\n    sizeDesc.reserve(M);\n    sizeAsc.reserve(M);\n    sizeOrig.reserve(M);\n    for (int i = 0; i < M; ++i) {\n        sizeDesc.emplace_back(G_in[i], i);\n        sizeAsc.emplace_back(G_in[i], i);\n        sizeOrig.emplace_back(G_in[i], i);\n    }\n    sort(sizeDesc.begin(), sizeDesc.end(),\n         [](const auto &a, const auto &b) {\n             if (a.first != b.first) return a.first > b.first; // larger first\n             return a.second < b.second;\n         });\n    sort(sizeAsc.begin(), sizeAsc.end(),\n         [](const auto &a, const auto &b) {\n             if (a.first != b.first) return a.first < b.first; // smaller first\n             return a.second < b.second;\n         });\n    // sizeOrig: original order\n\n    vector<vector<pair<int,int>>> sizeOrders = {sizeDesc, sizeAsc, sizeOrig};\n\n    // --------- Build candidate solutions ---------\n    vector<Solution> candidates;\n    candidates.reserve(cityOrders.size() * sizeOrders.size());\n\n    auto build_solution = [&](const vector<int> &cityOrder,\n                              const vector<pair<int,int>> &sizeOrder) {\n        Solution sol;\n        sol.groups.assign(M, {});\n        int ptr = 0;\n        for (auto &p : sizeOrder) {\n            int sz = p.first;\n            int gid = p.second;\n            sol.groups[gid].reserve(sz);\n            for (int k = 0; k < sz; ++k) {\n                sol.groups[gid].push_back(cityOrder[ptr++]);\n            }\n        }\n        sol.edges.assign(M, {});\n        // Build MST edges for each group\n        for (int g = 0; g < M; ++g) {\n            buildMSTForGroup(sol.groups[g], sol.edges[g]);\n        }\n\n        // Approximate cost: sum of floor(sqrt(baseDist)) over all group MST edges\n        long long cost = 0;\n        for (int g = 0; g < M; ++g) {\n            for (auto &e : sol.edges[g]) {\n                int u = e.first;\n                int v = e.second;\n                int d2 = baseDist[u][v];\n                double d = std::sqrt((double)d2);\n                cost += (long long)std::floor(d);\n            }\n        }\n\n        // Penalty for good edges that are cut across groups (weighted by count)\n        if (!goodEdges.empty() && CROSS_PEN > 0) {\n            vector<int> cityGroup(N, -1);\n            for (int g = 0; g < M; ++g) {\n                for (int c : sol.groups[g]) {\n                    cityGroup[c] = g;\n                }\n            }\n            long long pen = 0;\n            for (auto &e : goodEdges) {\n                int u = e.first, v = e.second;\n                if (cityGroup[u] != cityGroup[v]) {\n                    uint8_t cnt = goodCnt[u][v];\n                    int cnti = (int)cnt;\n                    if (cnti > 3) cnti = 3;\n                    pen += (long long)CROSS_PEN * cnti;\n                }\n            }\n            cost += pen;\n        }\n\n        sol.cost = cost;\n        candidates.push_back(std::move(sol));\n    };\n\n    for (const auto &ord : cityOrders) {\n        for (const auto &szOrd : sizeOrders) {\n            build_solution(ord, szOrd);\n        }\n    }\n\n    // --------- Choose best candidate ---------\n    int bestIdx = 0;\n    long long bestCost = candidates[0].cost;\n    for (int i = 1; i < (int)candidates.size(); ++i) {\n        if (candidates[i].cost < bestCost) {\n            bestCost = candidates[i].cost;\n            bestIdx = i;\n        }\n    }\n    Solution &bestSol = candidates[bestIdx];\n\n    // --------- Output final answer ---------\n    cout << \"!\\n\";\n    for (int g = 0; g < M; ++g) {\n        const auto &nodes = bestSol.groups[g];\n        int sz = (int)nodes.size();\n        for (int i = 0; i < sz; ++i) {\n            if (i) cout << ' ';\n            cout << nodes[i];\n        }\n        cout << '\\n';\n        const auto &edges = bestSol.edges[g];\n        for (auto &e : edges) {\n            cout << e.first << ' ' << e.second << '\\n';\n        }\n    }\n\n    return 0;\n}","ahc046":"#include <bits/stdc++.h>\nusing namespace std;\n\n// Directions: Up, Down, Left, Right\nconst int DX[4] = {-1, 1,  0, 0};\nconst int DY[4] = { 0, 0, -1, 1};\nconst char DCH[4] = {'U', 'D', 'L', 'R'};\n\n// Problem constants (N=20, M=40 in all tests, but read anyway)\nint N, M;\n\n// Precomputed slide destinations with NO internal blocks.\n// slideDest0[v][d] = destination cell index when sliding from v in direction d.\nint slideDest0[400][4];\n\ninline int idx(int x, int y) { return x * 20 + y; } // N=20 fixed\n\nconst int INF = 1e9;\n\n// Number of special candidate block cells\nconst int B = 6;\nconst int MASKN = 1 << B;\n\n// Max states: (M+1) * N * N * (1<<B) = 41 * 400 * 64 = 1,049,600\nconst int MAX_STATES = 1100000;\n\n// BFS arrays for global BFS\nstatic int distArr[MAX_STATES];\nstatic int parentArr[MAX_STATES];\nstatic char parentAct[MAX_STATES];\nstatic char parentDir[MAX_STATES];\nstatic int qArr[MAX_STATES];\n\n// Candidate block cells and mapping from cell -> candidate index\nint candX[B], candY[B];\nint candId[20][20];\n\n// Precompute slideDest0 for empty grid (no blocks)\nvoid init_slide_dest0() {\n    for (int x = 0; x < 20; ++x) {\n        for (int y = 0; y < 20; ++y) {\n            int v = idx(x, y);\n            for (int d = 0; d < 4; ++d) {\n                int nx = x, ny = y;\n                while (true) {\n                    int tx = nx + DX[d];\n                    int ty = ny + DY[d];\n                    if (tx < 0 || tx >= 20 || ty < 0 || ty >= 20) break;\n                    nx = tx;\n                    ny = ty;\n                }\n                slideDest0[v][d] = idx(nx, ny);\n            }\n        }\n    }\n}\n\n// Compute slide destination from (x,y) in direction d, given mask of active blocks.\ninline int slide_with_mask(int x, int y, int d, int mask) {\n    int v = idx(x, y);\n    int dest0 = slideDest0[v][d];\n    if (mask == 0) {\n        return dest0;\n    }\n    int ex = dest0 / 20;\n    int ey = dest0 % 20;\n\n    int bestx = ex, besty = ey; // default: border destination\n\n    // Look for the closest block along the ray in direction d.\n    for (int i = 0; i < B; ++i) {\n        if (!(mask & (1 << i))) continue;\n        int bx = candX[i];\n        int by = candY[i];\n\n        if (d == 0) { // Up\n            if (by == y && bx < x) {\n                // closer if bx is larger\n                if (bx > bestx) {\n                    bestx = bx;\n                    besty = by;\n                }\n            }\n        } else if (d == 1) { // Down\n            if (by == y && bx > x && bx <= ex) {\n                // closer if bx is smaller\n                if (bx < bestx) {\n                    bestx = bx;\n                    besty = by;\n                }\n            }\n        } else if (d == 2) { // Left\n            if (bx == x && by < y) {\n                if (by > besty) {\n                    besty = by;\n                    bestx = bx;\n                }\n            }\n        } else { // Right\n            if (bx == x && by > y && by <= ey) {\n                if (by < besty) {\n                    besty = by;\n                    bestx = bx;\n                }\n            }\n        }\n    }\n\n    // If we found a block (bestx,besty) closer than border, stop just before it.\n    if (bestx != ex || besty != ey) {\n        if (d == 0) bestx = bestx + 1;       // stop one cell below the block\n        else if (d == 1) bestx = bestx - 1;  // stop one cell above\n        else if (d == 2) besty = besty + 1;  // stop one cell to the right\n        else besty = besty - 1;              // stop one cell to the left\n    }\n    return idx(bestx, besty);\n}\n\n// Encode/decode state: (ti, x, y, mask) -> integer\n// ti in [0..M], x,y in [0..19], mask in [0..(1<<B)-1]\ninline int encode(int ti, int x, int y, int mask) {\n    // Layout: (((ti * 20 + x) * 20 + y) << B) | mask\n    return ((((ti * 20 + x) * 20 + y) << B) | mask);\n}\n\ninline void decode(int id, int &ti, int &x, int &y, int &mask) {\n    mask = id & (MASKN - 1);\n    int tmp = id >> B;\n    y = tmp % 20;\n    tmp /= 20;\n    x = tmp % 20;\n    tmp /= 20;\n    ti = tmp;\n}\n\n// Compute baseline no-block path (per-segment BFS) and its total cost.\nvoid compute_baseline(const vector<pair<int,int>> &points,\n                      vector<char> &baseActs,\n                      vector<char> &baseDirs,\n                      int &baseCost) {\n    static int dist0[400];\n    static int prev0[400];\n    static char act0[400], dir0[400];\n\n    baseActs.clear();\n    baseDirs.clear();\n    baseCost = 0;\n\n    for (int seg = 1; seg < (int)points.size(); ++seg) {\n        int sx = points[seg - 1].first;\n        int sy = points[seg - 1].second;\n        int gx = points[seg].first;\n        int gy = points[seg].second;\n        int sIdx = idx(sx, sy);\n        int gIdx = idx(gx, gy);\n\n        // BFS on empty grid with slideDest0\n        for (int i = 0; i < 400; ++i) {\n            dist0[i] = INF;\n            prev0[i] = -1;\n        }\n        queue<int> q;\n        dist0[sIdx] = 0;\n        q.push(sIdx);\n\n        while (!q.empty()) {\n            int v = q.front(); q.pop();\n            if (v == gIdx) break;\n            int dv = dist0[v];\n            int x = v / 20;\n            int y = v % 20;\n            for (int k = 0; k < 4; ++k) {\n                // Move\n                {\n                    int nx = x + DX[k];\n                    int ny = y + DY[k];\n                    if (0 <= nx && nx < 20 && 0 <= ny && ny < 20) {\n                        int to = idx(nx, ny);\n                        if (dist0[to] > dv + 1) {\n                            dist0[to] = dv + 1;\n                            prev0[to] = v;\n                            act0[to] = 'M';\n                            dir0[to] = DCH[k];\n                            q.push(to);\n                        }\n                    }\n                }\n                // Slide\n                {\n                    int to = slideDest0[v][k];\n                    if (to != v && dist0[to] > dv + 1) {\n                        dist0[to] = dv + 1;\n                        prev0[to] = v;\n                        act0[to] = 'S';\n                        dir0[to] = DCH[k];\n                        q.push(to);\n                    }\n                }\n            }\n        }\n\n        int segCost = dist0[gIdx];\n        if (segCost >= INF) {\n            // Should not happen; but if it does, stop here.\n            baseCost = 2 * 20 * M;\n            return;\n        }\n        baseCost += segCost;\n\n        // Reconstruct segment path\n        vector<char> ra, rd;\n        int cur = gIdx;\n        while (cur != sIdx) {\n            int p = prev0[cur];\n            if (p == -1) { ra.clear(); rd.clear(); break; }\n            ra.push_back(act0[cur]);\n            rd.push_back(dir0[cur]);\n            cur = p;\n        }\n        for (int i = (int)ra.size() - 1; i >= 0; --i) {\n            baseActs.push_back(ra[i]);\n            baseDirs.push_back(rd[i]);\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> M; // N=20, M=40\n    vector<pair<int,int>> points(M);\n    for (int i = 0; i < M; ++i) {\n        cin >> points[i].first >> points[i].second;\n    }\n\n    init_slide_dest0();\n\n    // Baseline no-block solution\n    vector<char> baseActs, baseDirs;\n    int baselineCost;\n    compute_baseline(points, baseActs, baseDirs, baselineCost);\n    if (baselineCost > 2 * 20 * M) {\n        // Path should always be <= 2NM, but just in case, cap it.\n        baselineCost = 2 * 20 * M;\n    }\n\n    // Initialize candidate block positions (a slightly extended cross around center)\n    // We use fixed coordinates; they are known to be inside [0,19].\n    candX[0] = 10; candY[0] = 10;\n    candX[1] =  6; candY[1] = 10;\n    candX[2] = 14; candY[2] = 10;\n    candX[3] = 10; candY[3] =  6;\n    candX[4] = 10; candY[4] = 14;\n    candX[5] = 10; candY[5] =  2; // extra stopper nearer to left side\n\n    // Map from cell to candidate index\n    for (int i = 0; i < 20; ++i)\n        for (int j = 0; j < 20; ++j)\n            candId[i][j] = -1;\n    for (int i = 0; i < B; ++i) {\n        int x = candX[i];\n        int y = candY[i];\n        if (0 <= x && x < 20 && 0 <= y && y < 20) {\n            candId[x][y] = i;\n        }\n    }\n\n    // Total possible states for this problem instance\n    int TOT = (M + 1) * 20 * 20 * MASKN; // 41 * 400 * 64 = 1,049,600\n    if (TOT > MAX_STATES) TOT = MAX_STATES; // safety\n\n    // Initialize BFS arrays\n    for (int i = 0; i < TOT; ++i) {\n        distArr[i] = INF;\n        parentArr[i] = -1;\n    }\n\n    int sx = points[0].first;\n    int sy = points[0].second;\n\n    int startTi = 1;   // next target index to visit is 1\n    int startMask = 0; // no blocks initially\n    int startId = encode(startTi, sx, sy, startMask);\n\n    distArr[startId] = 0;\n    int qh = 0, qt = 0;\n    qArr[qt++] = startId;\n\n    int goalId = -1;\n    int lastTx = points[M-1].first;\n    int lastTy = points[M-1].second;\n\n    // We only care about improvements over baselineCost.\n    const int LIMIT = baselineCost; // search only states with dist < LIMIT\n\n    while (qh < qt) {\n        int id = qArr[qh++];\n        int dcur = distArr[id];\n        if (dcur >= LIMIT) continue; // cannot improve\n\n        int ti, x, y, mask;\n        decode(id, ti, x, y, mask);\n\n        if (ti == M && x == lastTx && y == lastTy) {\n            // First state that reaches last target with dcur < LIMIT => improved solution\n            goalId = id;\n            break;\n        }\n\n        // Moves and Slides\n        for (int k = 0; k < 4; ++k) {\n            // Move\n            {\n                int nx = x + DX[k];\n                int ny = y + DY[k];\n                if (0 <= nx && nx < 20 && 0 <= ny && ny < 20) {\n                    // Check if destination cell is blocked\n                    int cid = candId[nx][ny];\n                    bool blocked = (cid >= 0) && (mask & (1 << cid));\n                    if (!blocked) {\n                        int nti = ti;\n                        if (ti < M &&\n                            nx == points[ti].first &&\n                            ny == points[ti].second) {\n                            nti++;\n                        }\n                        int nid = encode(nti, nx, ny, mask);\n                        int nd = dcur + 1;\n                        if (nd < LIMIT && distArr[nid] > nd) {\n                            distArr[nid] = nd;\n                            parentArr[nid] = id;\n                            parentAct[nid] = 'M';\n                            parentDir[nid] = DCH[k];\n                            qArr[qt++] = nid;\n                        }\n                    }\n                }\n            }\n\n            // Slide\n            {\n                int dest = slide_with_mask(x, y, k, mask);\n                if (dest != idx(x, y)) {\n                    int nx = dest / 20;\n                    int ny = dest % 20;\n                    int nti = ti;\n                    if (ti < M &&\n                        nx == points[ti].first &&\n                        ny == points[ti].second) {\n                        nti++;\n                    }\n                    int nid = encode(nti, nx, ny, mask);\n                    int nd = dcur + 1;\n                    if (nd < LIMIT && distArr[nid] > nd) {\n                        distArr[nid] = nd;\n                        parentArr[nid] = id;\n                        parentAct[nid] = 'S';\n                        parentDir[nid] = DCH[k];\n                        qArr[qt++] = nid;\n                    }\n                }\n            }\n        }\n\n        // Alter (toggle block at adjacent candidate cells)\n        for (int k = 0; k < 4; ++k) {\n            int ax = x + DX[k];\n            int ay = y + DY[k];\n            if (0 <= ax && ax < 20 && 0 <= ay && ay < 20) {\n                int cid = candId[ax][ay];\n                if (cid >= 0) {\n                    int nmask = mask ^ (1 << cid);\n                    int nid = encode(ti, x, y, nmask);\n                    int nd = dcur + 1;\n                    if (nd < LIMIT && distArr[nid] > nd) {\n                        distArr[nid] = nd;\n                        parentArr[nid] = id;\n                        parentAct[nid] = 'A';\n                        parentDir[nid] = DCH[k];\n                        qArr[qt++] = nid;\n                    }\n                }\n            }\n        }\n    }\n\n    vector<char> actions;\n    vector<char> dirs;\n\n    if (goalId == -1) {\n        // No improved path found; use baseline\n        actions = baseActs;\n        dirs    = baseDirs;\n    } else {\n        // Reconstruct improved global path from goalId to startId\n        vector<char> ra, rd;\n        int cur = goalId;\n        while (cur != startId) {\n            ra.push_back(parentAct[cur]);\n            rd.push_back(parentDir[cur]);\n            cur = parentArr[cur];\n            if (cur == -1) { ra.clear(); rd.clear(); break; } // safety\n        }\n        for (int i = (int)ra.size() - 1; i >= 0; --i) {\n            actions.push_back(ra[i]);\n            dirs.push_back(rd[i]);\n        }\n    }\n\n    // Output action sequence\n    for (size_t i = 0; i < actions.size(); ++i) {\n        cout << actions[i] << ' ' << dirs[i] << '\\n';\n    }\n\n    return 0;\n}"},"16":{"ahc001":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Rect {\n    int a, b, c, d; // [a,c) x [b,d)\n};\n\nint n;\nvector<int> xs, ys;\nvector<long long> rs;\n\n// Satisfaction for s <= r\ninline double satisfaction(long long s, long long r) {\n    if (s <= 0) return 0.0;\n    double q = (double)s / (double)r; // q in (0,1]\n    double t = 1.0 - q;\n    return 1.0 - t * t; // = 2q - q^2\n}\n\n// Positive-area overlap?\ninline bool overlap(const Rect &x, const Rect &y) {\n    return (x.a < y.c && y.a < x.c && x.b < y.d && y.b < x.d);\n}\n\n// Greedy growth for a given order. Fills rect and area, returns total score.\ndouble run_order(const vector<int> &order, vector<Rect> &rect, vector<long long> &area) {\n    rect.assign(n, Rect());\n    area.assign(n, 1);\n\n    // Initialize as 1x1 cells at seeds\n    for (int i = 0; i < n; ++i) {\n        rect[i].a = xs[i];\n        rect[i].c = xs[i] + 1;\n        rect[i].b = ys[i];\n        rect[i].d = ys[i] + 1;\n        area[i] = 1;\n    }\n\n    for (int pos = 0; pos < n; ++pos) {\n        int i = order[pos];\n        long long target = rs[i];\n        if (target <= 1) continue;\n\n        while (area[i] < target) {\n            Rect &cur = rect[i];\n            int w = cur.c - cur.a;\n            int h = cur.d - cur.b;\n            if (w <= 0 || h <= 0) break;\n            long long remaining = target - area[i];\n\n            int bestDir = -1;\n            int bestL = 0;\n            long long bestDelta = 0;\n\n            // 0: up (increase d)\n            if (cur.d < 10000 && remaining >= w) {\n                long long L_area = remaining / w;\n                if (L_area > 0) {\n                    int limit = 10000 - cur.d;\n                    if (limit > 0) {\n                        for (int j = 0; j < n; ++j) {\n                            if (j == i) continue;\n                            const Rect &s = rect[j];\n                            // x-overlap?\n                            if (s.a >= cur.c || s.c <= cur.a) continue;\n                            if (cur.d >= s.d) continue; // s below or touching\n                            if (s.b <= cur.d) {\n                                // s.b <= d < s.d, any extension hits s\n                                limit = 0;\n                                break;\n                            } else {\n                                int cand = s.b - cur.d;\n                                if (cand < limit) {\n                                    limit = cand;\n                                    if (limit <= 0) {\n                                        limit = 0;\n                                        break;\n                                    }\n                                }\n                            }\n                        }\n                        if (limit > 0) {\n                            int L = (int)min<long long>(limit, L_area);\n                            if (L > 0) {\n                                long long delta = 1LL * L * w;\n                                if (delta > bestDelta) {\n                                    bestDelta = delta;\n                                    bestDir = 0;\n                                    bestL = L;\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n\n            // 1: down (decrease b)\n            if (cur.b > 0 && remaining >= w) {\n                long long L_area = remaining / w;\n                if (L_area > 0) {\n                    int limit = cur.b;\n                    if (limit > 0) {\n                        for (int j = 0; j < n; ++j) {\n                            if (j == i) continue;\n                            const Rect &s = rect[j];\n                            // x-overlap?\n                            if (s.a >= cur.c || s.c <= cur.a) continue;\n                            if (s.b >= cur.b) continue; // s above or touching\n                            if (s.d > cur.b) {\n                                // s.b < b < s.d\n                                limit = 0;\n                                break;\n                            } else {\n                                int cand = cur.b - s.d;\n                                if (cand < limit) {\n                                    limit = cand;\n                                    if (limit <= 0) {\n                                        limit = 0;\n                                        break;\n                                    }\n                                }\n                            }\n                        }\n                        if (limit > 0) {\n                            int L = (int)min<long long>(limit, L_area);\n                            if (L > 0) {\n                                long long delta = 1LL * L * w;\n                                if (delta > bestDelta) {\n                                    bestDelta = delta;\n                                    bestDir = 1;\n                                    bestL = L;\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n\n            // 2: left (decrease a)\n            if (cur.a > 0 && remaining >= h) {\n                long long L_area = remaining / h;\n                if (L_area > 0) {\n                    int limit = cur.a;\n                    if (limit > 0) {\n                        for (int j = 0; j < n; ++j) {\n                            if (j == i) continue;\n                            const Rect &s = rect[j];\n                            // y-overlap?\n                            if (s.d <= cur.b || cur.d <= s.b) continue;\n                            if (s.a >= cur.a) {\n                                // s to the right or touching\n                                continue;\n                            } else {\n                                if (s.c > cur.a) {\n                                    // s crosses x = cur.a\n                                    limit = 0;\n                                    break;\n                                } else {\n                                    int cand = cur.a - s.c;\n                                    if (cand < limit) {\n                                        limit = cand;\n                                        if (limit <= 0) {\n                                            limit = 0;\n                                            break;\n                                        }\n                                    }\n                                }\n                            }\n                        }\n                        if (limit > 0) {\n                            int L = (int)min<long long>(limit, L_area);\n                            if (L > 0) {\n                                long long delta = 1LL * L * h;\n                                if (delta > bestDelta) {\n                                    bestDelta = delta;\n                                    bestDir = 2;\n                                    bestL = L;\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n\n            // 3: right (increase c)\n            if (cur.c < 10000 && remaining >= h) {\n                long long L_area = remaining / h;\n                if (L_area > 0) {\n                    int limit = 10000 - cur.c;\n                    if (limit > 0) {\n                        for (int j = 0; j < n; ++j) {\n                            if (j == i) continue;\n                            const Rect &s = rect[j];\n                            // y-overlap?\n                            if (s.d <= cur.b || cur.d <= s.b) continue;\n                            if (cur.c >= s.c) {\n                                // s to the left or touching\n                                continue;\n                            } else {\n                                if (s.a <= cur.c) {\n                                    // s crosses x = cur.c\n                                    limit = 0;\n                                    break;\n                                } else {\n                                    int cand = s.a - cur.c;\n                                    if (cand < limit) {\n                                        limit = cand;\n                                        if (limit <= 0) {\n                                            limit = 0;\n                                            break;\n                                        }\n                                    }\n                                }\n                            }\n                        }\n                        if (limit > 0) {\n                            int L = (int)min<long long>(limit, L_area);\n                            if (L > 0) {\n                                long long delta = 1LL * L * h;\n                                if (delta > bestDelta) {\n                                    bestDelta = delta;\n                                    bestDir = 3;\n                                    bestL = L;\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n\n            if (bestDir == -1 || bestL <= 0 || bestDelta <= 0) break;\n\n            switch (bestDir) {\n                case 0: cur.d += bestL; break;\n                case 1: cur.b -= bestL; break;\n                case 2: cur.a -= bestL; break;\n                case 3: cur.c += bestL; break;\n            }\n            area[i] += bestDelta;\n        }\n    }\n\n    double score = 0.0;\n    for (int i = 0; i < n; ++i) {\n        score += satisfaction(area[i], rs[i]);\n    }\n    return score;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> n;\n    xs.resize(n);\n    ys.resize(n);\n    rs.resize(n);\n    for (int i = 0; i < n; ++i) {\n        cin >> xs[i] >> ys[i] >> rs[i];\n    }\n\n    // Time management\n    const double ORDER_PHASE_END = 2.0; // seconds\n    const double SA_PHASE_END    = 4.6; // seconds\n\n    auto time_start = chrono::steady_clock::now();\n    auto elapsed = [&]() -> double {\n        return chrono::duration<double>(chrono::steady_clock::now() - time_start).count();\n    };\n\n    // RNG: deterministic based on input (stability)\n    uint64_t seed = 88172645463325252ULL;\n    seed ^= (uint64_t)n * 1000003ULL;\n    for (int i = 0; i < n; ++i) {\n        uint64_t v = ((uint64_t)xs[i] << 17) ^ ((uint64_t)ys[i] << 3) ^ (uint64_t)rs[i];\n        seed ^= std::rotl(v, i % 47);\n        seed *= 1000003ULL;\n        seed += 1234567ULL;\n    }\n    std::mt19937_64 rng(seed);\n\n    vector<int> base(n);\n    iota(base.begin(), base.end(), 0);\n\n    vector<Rect> rect, bestRect;\n    vector<long long> area, bestArea;\n    double bestScore = -1.0;\n\n    auto try_order = [&](const vector<int> &order) {\n        double sc = run_order(order, rect, area);\n        if (sc > bestScore) {\n            bestScore = sc;\n            bestRect = rect;\n            bestArea = area;\n        }\n    };\n\n    // Deterministic orders\n\n    // 1) increasing r\n    {\n        vector<int> ord = base;\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            if (rs[a] != rs[b]) return rs[a] < rs[b];\n            return a < b;\n        });\n        try_order(ord);\n    }\n    // 2) decreasing r\n    {\n        vector<int> ord = base;\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            if (rs[a] != rs[b]) return rs[a] > rs[b];\n            return a < b;\n        });\n        try_order(ord);\n    }\n    // 3) increasing x\n    {\n        vector<int> ord = base;\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            if (xs[a] != xs[b]) return xs[a] < xs[b];\n            return a < b;\n        });\n        try_order(ord);\n    }\n    // 4) increasing y\n    {\n        vector<int> ord = base;\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            if (ys[a] != ys[b]) return ys[a] < ys[b];\n            return a < b;\n        });\n        try_order(ord);\n    }\n\n    // Random permutations until ORDER_PHASE_END\n    {\n        vector<int> ord = base;\n        while (elapsed() < ORDER_PHASE_END) {\n            shuffle(ord.begin(), ord.end(), rng);\n            try_order(ord);\n        }\n    }\n\n    // Local search (simulated annealing) starting from bestRect\n    vector<Rect> curRect = bestRect;\n    vector<long long> curArea = bestArea;\n    vector<double> curP(n);\n    double curScore = 0.0;\n    for (int i = 0; i < n; ++i) {\n        curP[i] = satisfaction(curArea[i], rs[i]);\n        curScore += curP[i];\n    }\n    bestScore = curScore;\n    bestRect = curRect;\n    bestArea = curArea;\n\n    double sa_start_time = elapsed();\n    double sa_total = SA_PHASE_END - sa_start_time;\n    if (sa_total > 0.0) {\n        uniform_int_distribution<int> distRect(0, n - 1);\n        uniform_real_distribution<double> dist01(0.0, 1.0);\n\n        const double T0 = 1e-3;\n        const double T1 = 1e-5;\n        const double P_PAIR = 0.25;\n\n        while (true) {\n            double tnow = elapsed();\n            if (tnow >= SA_PHASE_END) break;\n            double sa_elapsed = tnow - sa_start_time;\n            double progress = sa_elapsed / sa_total;\n            if (progress > 1.0) progress = 1.0;\n            double T = T0 + (T1 - T0) * progress; // linear cooling\n\n            bool moved = false;\n\n            // Try pair move with some probability\n            double choosePair = dist01(rng);\n            if (choosePair < P_PAIR) {\n                for (int attempt = 0; attempt < 2 && !moved; ++attempt) {\n                    int i = distRect(rng);\n                    int dir = (int)(rng() % 4); // 0:left,1:right,2:down,3:up\n                    const Rect &ri = curRect[i];\n                    int j = -1;\n\n                    // find full-side neighbor j\n                    for (int k = 0; k < n; ++k) if (k != i) {\n                        const Rect &rj = curRect[k];\n                        if (dir == 0) { // left\n                            if (rj.c == ri.a && rj.b == ri.b && rj.d == ri.d) { j = k; break; }\n                        } else if (dir == 1) { // right\n                            if (rj.a == ri.c && rj.b == ri.b && rj.d == ri.d) { j = k; break; }\n                        } else if (dir == 2) { // down\n                            if (rj.d == ri.b && rj.a == ri.a && rj.c == ri.c) { j = k; break; }\n                        } else { // up\n                            if (rj.b == ri.d && rj.a == ri.a && rj.c == ri.c) { j = k; break; }\n                        }\n                    }\n\n                    if (j == -1) continue;\n\n                    Rect riOld = ri;\n                    Rect rjOld = curRect[j];\n                    long long Ai = curArea[i];\n                    long long Aj = curArea[j];\n                    double Pi = curP[i];\n                    double Pj = curP[j];\n\n                    Rect ri1 = riOld, rj1 = rjOld, ri2 = riOld, rj2 = rjOld;\n                    long long Ai1 = Ai, Aj1 = Aj, Ai2 = Ai, Aj2 = Aj;\n                    double newPi1 = Pi, newPj1 = Pj, newPi2 = Pi, newPj2 = Pj;\n                    double bestDelta = -1e100;\n                    int bestCase = -1;\n\n                    // stripe area (amount of area transferred by 1-unit border move)\n                    long long stripe = 0;\n                    if (dir == 0 || dir == 1) {\n                        stripe = (long long)(riOld.d - riOld.b); // vertical adjacency\n                    } else {\n                        stripe = (long long)(riOld.c - riOld.a); // horizontal adjacency\n                    }\n                    if (stripe <= 0) continue;\n\n                    // Case A: shrink j, expand i\n                    {\n                        bool ok = true;\n                        Rect riA = riOld, rjA = rjOld;\n                        long long AiA = Ai, AjA = Aj;\n\n                        if (dir == 0) { // j left, shrink j right, expand i left\n                            int wj = rjOld.c - rjOld.a;\n                            if (wj <= 1) ok = false;\n                            if (ok && xs[j] == rjOld.c - 1) ok = false; // seed at shrinking side\n                            if (ok && Ai + stripe > rs[i]) ok = false;\n                            if (ok) {\n                                riA.a = riOld.a - 1;\n                                rjA.c = rjOld.c - 1;\n                                AiA = Ai + stripe;\n                                AjA = Aj - stripe;\n                            }\n                        } else if (dir == 1) { // j right, shrink j left, expand i right\n                            int wj = rjOld.c - rjOld.a;\n                            if (wj <= 1) ok = false;\n                            if (ok && xs[j] == rjOld.a) ok = false;\n                            if (ok && Ai + stripe > rs[i]) ok = false;\n                            if (ok) {\n                                rjA.a = rjOld.a + 1;\n                                riA.c = riOld.c + 1;\n                                AiA = Ai + stripe;\n                                AjA = Aj - stripe;\n                            }\n                        } else if (dir == 2) { // j below, shrink j top, expand i down\n                            int hj = rjOld.d - rjOld.b;\n                            if (hj <= 1) ok = false;\n                            if (ok && ys[j] == rjOld.d - 1) ok = false;\n                            if (ok && Ai + stripe > rs[i]) ok = false;\n                            if (ok) {\n                                rjA.d = rjOld.d - 1;\n                                riA.b = riOld.b - 1;\n                                AiA = Ai + stripe;\n                                AjA = Aj - stripe;\n                            }\n                        } else { // dir == 3, j above, shrink j bottom, expand i up\n                            int hj = rjOld.d - rjOld.b;\n                            if (hj <= 1) ok = false;\n                            if (ok && ys[j] == rjOld.b) ok = false;\n                            if (ok && Ai + stripe > rs[i]) ok = false;\n                            if (ok) {\n                                rjA.b = rjOld.b + 1;\n                                riA.d = riOld.d + 1;\n                                AiA = Ai + stripe;\n                                AjA = Aj - stripe;\n                            }\n                        }\n\n                        if (ok && AiA > 0 && AjA > 0) {\n                            double PiA = satisfaction(AiA, rs[i]);\n                            double PjA = satisfaction(AjA, rs[j]);\n                            double delta = (PiA - Pi) + (PjA - Pj);\n                            if (delta > bestDelta) {\n                                bestDelta = delta;\n                                bestCase = 0;\n                                ri1 = riA;\n                                rj1 = rjA;\n                                Ai1 = AiA;\n                                Aj1 = AjA;\n                                newPi1 = PiA;\n                                newPj1 = PjA;\n                            }\n                        }\n                    }\n\n                    // Case B: shrink i, expand j\n                    {\n                        bool ok = true;\n                        Rect riB = riOld, rjB = rjOld;\n                        long long AiB = Ai, AjB = Aj;\n\n                        if (dir == 0) { // j left, shrink i left, expand j right\n                            int wi = riOld.c - riOld.a;\n                            if (wi <= 1) ok = false;\n                            if (ok && xs[i] == riOld.a) ok = false;\n                            if (ok && Aj + stripe > rs[j]) ok = false;\n                            if (ok) {\n                                riB.a = riOld.a + 1;\n                                rjB.c = rjOld.c + 1;\n                                AiB = Ai - stripe;\n                                AjB = Aj + stripe;\n                            }\n                        } else if (dir == 1) { // j right, shrink i right, expand j left\n                            int wi = riOld.c - riOld.a;\n                            if (wi <= 1) ok = false;\n                            if (ok && xs[i] == riOld.c - 1) ok = false;\n                            if (ok && Aj + stripe > rs[j]) ok = false;\n                            if (ok) {\n                                riB.c = riOld.c - 1;\n                                rjB.a = rjOld.a - 1;\n                                AiB = Ai - stripe;\n                                AjB = Aj + stripe;\n                            }\n                        } else if (dir == 2) { // j below, shrink i down, expand j up\n                            int hi = riOld.d - riOld.b;\n                            if (hi <= 1) ok = false;\n                            if (ok && ys[i] == riOld.b) ok = false;\n                            if (ok && Aj + stripe > rs[j]) ok = false;\n                            if (ok) {\n                                riB.b = riOld.b + 1;\n                                rjB.d = rjOld.d + 1;\n                                AiB = Ai - stripe;\n                                AjB = Aj + stripe;\n                            }\n                        } else { // dir == 3, j above, shrink i up, expand j down\n                            int hi = riOld.d - riOld.b;\n                            if (hi <= 1) ok = false;\n                            if (ok && ys[i] == riOld.d - 1) ok = false;\n                            if (ok && Aj + stripe > rs[j]) ok = false;\n                            if (ok) {\n                                riB.d = riOld.d - 1;\n                                rjB.b = rjOld.b - 1;\n                                AiB = Ai - stripe;\n                                AjB = Aj + stripe;\n                            }\n                        }\n\n                        if (ok && AiB > 0 && AjB > 0) {\n                            double PiB = satisfaction(AiB, rs[i]);\n                            double PjB = satisfaction(AjB, rs[j]);\n                            double delta = (PiB - Pi) + (PjB - Pj);\n                            if (delta > bestDelta) {\n                                bestDelta = delta;\n                                bestCase = 1;\n                                ri2 = riB;\n                                rj2 = rjB;\n                                Ai2 = AiB;\n                                Aj2 = AjB;\n                                newPi2 = PiB;\n                                newPj2 = PjB;\n                            }\n                        }\n                    }\n\n                    const double EPS = 1e-12;\n                    if (bestCase != -1 && bestDelta > EPS) {\n                        if (bestCase == 0) {\n                            curRect[i] = ri1;\n                            curRect[j] = rj1;\n                            curArea[i] = Ai1;\n                            curArea[j] = Aj1;\n                            curP[i] = newPi1;\n                            curP[j] = newPj1;\n                        } else {\n                            curRect[i] = ri2;\n                            curRect[j] = rj2;\n                            curArea[i] = Ai2;\n                            curArea[j] = Aj2;\n                            curP[i] = newPi2;\n                            curP[j] = newPj2;\n                        }\n                        curScore += bestDelta;\n                        if (curScore > bestScore) {\n                            bestScore = curScore;\n                            bestRect = curRect;\n                            bestArea = curArea;\n                        }\n                        moved = true;\n                    }\n                }\n            }\n\n            if (moved) continue;\n\n            // Single-rectangle SA move\n\n            // Choose a rectangle, biasing toward under-satisfied ones\n            int i = distRect(rng);\n            for (int tries = 0; tries < 4; ++tries) {\n                double fill0 = (double)curArea[i] / (double)rs[i];\n                if (fill0 < 0.99) break;\n                i = distRect(rng);\n            }\n\n            Rect old = curRect[i];\n            long long oldArea = curArea[i];\n            double oldPi = curP[i];\n\n            int w = old.c - old.a;\n            int h = old.d - old.b;\n            if (w <= 0 || h <= 0) continue;\n\n            double fill = (double)oldArea / (double)rs[i];\n\n            // Decide operation type (0..3 expand, 4..7 shrink, 8..11 shift)\n            int op;\n            if (fill < 0.98) {\n                // mostly expand and shift\n                uint64_t r = rng() % 10;\n                if (r < 6) {        // 60% expand\n                    op = (int)(rng() % 4); // 0..3\n                } else if (r < 9) { // 30% shift\n                    op = 8 + (int)(rng() % 4); // 8..11\n                } else {            // 10% shrink\n                    op = 4 + (int)(rng() % 4); // 4..7\n                }\n            } else {\n                // mostly shrink and shift\n                uint64_t r = rng() % 10;\n                if (r < 5) { // 50% shrink\n                    op = 4 + (int)(rng() % 4);\n                } else if (r < 8) { // 30% shift\n                    op = 8 + (int)(rng() % 4);\n                } else { // 20% expand\n                    op = (int)(rng() % 4);\n                }\n            }\n\n            Rect cand = old;\n            long long newArea = oldArea;\n            bool ok = true;\n            bool changed = false;\n\n            switch (op) {\n                case 0: { // expand left (a--)\n                    if (old.a == 0) { ok = false; break; }\n                    if (oldArea + h > rs[i]) { ok = false; break; }\n                    cand.a = old.a - 1;\n                    newArea = oldArea + h;\n                    // overlap check\n                    for (int j = 0; j < n; ++j) {\n                        if (j == i) continue;\n                        if (overlap(cand, curRect[j])) { ok = false; break; }\n                    }\n                    if (!ok) break;\n                    changed = true;\n                    break;\n                }\n                case 1: { // expand right (c++)\n                    if (old.c == 10000) { ok = false; break; }\n                    if (oldArea + h > rs[i]) { ok = false; break; }\n                    cand.c = old.c + 1;\n                    newArea = oldArea + h;\n                    for (int j = 0; j < n; ++j) {\n                        if (j == i) continue;\n                        if (overlap(cand, curRect[j])) { ok = false; break; }\n                    }\n                    if (!ok) break;\n                    changed = true;\n                    break;\n                }\n                case 2: { // expand down (b--)\n                    if (old.b == 0) { ok = false; break; }\n                    if (oldArea + w > rs[i]) { ok = false; break; }\n                    cand.b = old.b - 1;\n                    newArea = oldArea + w;\n                    for (int j = 0; j < n; ++j) {\n                        if (j == i) continue;\n                        if (overlap(cand, curRect[j])) { ok = false; break; }\n                    }\n                    if (!ok) break;\n                    changed = true;\n                    break;\n                }\n                case 3: { // expand up (d++)\n                    if (old.d == 10000) { ok = false; break; }\n                    if (oldArea + w > rs[i]) { ok = false; break; }\n                    cand.d = old.d + 1;\n                    newArea = oldArea + w;\n                    for (int j = 0; j < n; ++j) {\n                        if (j == i) continue;\n                        if (overlap(cand, curRect[j])) { ok = false; break; }\n                    }\n                    if (!ok) break;\n                    changed = true;\n                    break;\n                }\n                case 4: { // shrink left (a++)\n                    if (w <= 1) { ok = false; break; }\n                    // seed must stay inside: xs[i] != old.a\n                    if (xs[i] == old.a) { ok = false; break; }\n                    cand.a = old.a + 1;\n                    newArea = oldArea - h;\n                    changed = true;\n                    break;\n                }\n                case 5: { // shrink right (c--)\n                    if (w <= 1) { ok = false; break; }\n                    if (xs[i] == old.c - 1) { ok = false; break; }\n                    cand.c = old.c - 1;\n                    newArea = oldArea - h;\n                    changed = true;\n                    break;\n                }\n                case 6: { // shrink down (b++)\n                    if (h <= 1) { ok = false; break; }\n                    if (ys[i] == old.b) { ok = false; break; }\n                    cand.b = old.b + 1;\n                    newArea = oldArea - w;\n                    changed = true;\n                    break;\n                }\n                case 7: { // shrink up (d--)\n                    if (h <= 1) { ok = false; break; }\n                    if (ys[i] == old.d - 1) { ok = false; break; }\n                    cand.d = old.d - 1;\n                    newArea = oldArea - w;\n                    changed = true;\n                    break;\n                }\n                case 8: { // shift left (a--, c--)\n                    if (old.a == 0) { ok = false; break; }\n                    // seed must stay inside after shift\n                    if (xs[i] == old.c - 1) { ok = false; break; }\n                    cand.a = old.a - 1;\n                    cand.c = old.c - 1;\n                    // area unchanged\n                    for (int j = 0; j < n; ++j) {\n                        if (j == i) continue;\n                        if (overlap(cand, curRect[j])) { ok = false; break; }\n                    }\n                    if (!ok) break;\n                    changed = true;\n                    break;\n                }\n                case 9: { // shift right (a++, c++)\n                    if (old.c == 10000) { ok = false; break; }\n                    if (xs[i] == old.a) { ok = false; break; }\n                    cand.a = old.a + 1;\n                    cand.c = old.c + 1;\n                    for (int j = 0; j < n; ++j) {\n                        if (j == i) continue;\n                        if (overlap(cand, curRect[j])) { ok = false; break; }\n                    }\n                    if (!ok) break;\n                    changed = true;\n                    break;\n                }\n                case 10: { // shift down (b--, d--)\n                    if (old.b == 0) { ok = false; break; }\n                    if (ys[i] == old.d - 1) { ok = false; break; }\n                    cand.b = old.b - 1;\n                    cand.d = old.d - 1;\n                    for (int j = 0; j < n; ++j) {\n                        if (j == i) continue;\n                        if (overlap(cand, curRect[j])) { ok = false; break; }\n                    }\n                    if (!ok) break;\n                    changed = true;\n                    break;\n                }\n                case 11: { // shift up (b++, d++)\n                    if (old.d == 10000) { ok = false; break; }\n                    if (ys[i] == old.b) { ok = false; break; }\n                    cand.b = old.b + 1;\n                    cand.d = old.d + 1;\n                    for (int j = 0; j < n; ++j) {\n                        if (j == i) continue;\n                        if (overlap(cand, curRect[j])) { ok = false; break; }\n                    }\n                    if (!ok) break;\n                    changed = true;\n                    break;\n                }\n            }\n\n            if (!ok || !changed) continue;\n            if (!(cand.a < cand.c && cand.b < cand.d)) continue;\n\n            double newPi = satisfaction(newArea, rs[i]);\n            double delta = newPi - oldPi;\n            double newScore = curScore + delta;\n\n            if (delta >= 0.0) {\n                // Always accept non-worse moves\n                curRect[i] = cand;\n                curArea[i] = newArea;\n                curP[i] = newPi;\n                curScore = newScore;\n                if (curScore > bestScore) {\n                    bestScore = curScore;\n                    bestRect = curRect;\n                    bestArea = curArea;\n                }\n            } else {\n                double prob = exp(delta / T);\n                double r = dist01(rng);\n                if (r < prob) {\n                    // Accept worse move\n                    curRect[i] = cand;\n                    curArea[i] = newArea;\n                    curP[i] = newPi;\n                    curScore = newScore;\n                    if (curScore > bestScore) {\n                        bestScore = curScore;\n                        bestRect = curRect;\n                        bestArea = curArea;\n                    }\n                }\n                // else reject\n            }\n        }\n    }\n\n    // Final greedy fill on the best layout to exploit freed spaces\n    auto greedy_finalize = [&](vector<Rect> &rectRef, vector<long long> &areaRef) {\n        vector<int> ord(n);\n        iota(ord.begin(), ord.end(), 0);\n        // Process companies with larger shortage first\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            long long da = rs[a] - areaRef[a];\n            long long db = rs[b] - areaRef[b];\n            if (da != db) return da > db;\n            return a < b;\n        });\n\n        for (int idx = 0; idx < n; ++idx) {\n            if (elapsed() > 4.9) break; // safety margin\n            int i = ord[idx];\n            long long target = rs[i];\n            if (areaRef[i] >= target) continue;\n\n            while (areaRef[i] < target) {\n                if (elapsed() > 4.9) break;\n                Rect &cur = rectRef[i];\n                int w = cur.c - cur.a;\n                int h = cur.d - cur.b;\n                if (w <= 0 || h <= 0) break;\n                long long remaining = target - areaRef[i];\n\n                int bestDir = -1;\n                int bestL = 0;\n                long long bestDelta = 0;\n\n                // 0: up (increase d)\n                if (cur.d < 10000 && remaining >= w) {\n                    long long L_area = remaining / w;\n                    if (L_area > 0) {\n                        int limit = 10000 - cur.d;\n                        if (limit > 0) {\n                            for (int j = 0; j < n; ++j) {\n                                if (j == i) continue;\n                                const Rect &s = rectRef[j];\n                                // x-overlap?\n                                if (s.a >= cur.c || s.c <= cur.a) continue;\n                                if (cur.d >= s.d) continue; // s below or touching\n                                if (s.b <= cur.d) {\n                                    // s.b <= d < s.d, any extension hits s\n                                    limit = 0;\n                                    break;\n                                } else {\n                                    int cand = s.b - cur.d;\n                                    if (cand < limit) {\n                                        limit = cand;\n                                        if (limit <= 0) {\n                                            limit = 0;\n                                            break;\n                                        }\n                                    }\n                                }\n                            }\n                            if (limit > 0) {\n                                int L = (int)min<long long>(limit, L_area);\n                                if (L > 0) {\n                                    long long delta = 1LL * L * w;\n                                    if (delta > bestDelta) {\n                                        bestDelta = delta;\n                                        bestDir = 0;\n                                        bestL = L;\n                                    }\n                                }\n                            }\n                        }\n                    }\n                }\n\n                // 1: down (decrease b)\n                if (cur.b > 0 && remaining >= w) {\n                    long long L_area = remaining / w;\n                    if (L_area > 0) {\n                        int limit = cur.b;\n                        if (limit > 0) {\n                            for (int j = 0; j < n; ++j) {\n                                if (j == i) continue;\n                                const Rect &s = rectRef[j];\n                                // x-overlap?\n                                if (s.a >= cur.c || s.c <= cur.a) continue;\n                                if (s.b >= cur.b) continue; // s above or touching\n                                if (s.d > cur.b) {\n                                    // s.b < b < s.d\n                                    limit = 0;\n                                    break;\n                                } else {\n                                    int cand = cur.b - s.d;\n                                    if (cand < limit) {\n                                        limit = cand;\n                                        if (limit <= 0) {\n                                            limit = 0;\n                                            break;\n                                        }\n                                    }\n                                }\n                            }\n                            if (limit > 0) {\n                                int L = (int)min<long long>(limit, L_area);\n                                if (L > 0) {\n                                    long long delta = 1LL * L * w;\n                                    if (delta > bestDelta) {\n                                        bestDelta = delta;\n                                        bestDir = 1;\n                                        bestL = L;\n                                    }\n                                }\n                            }\n                        }\n                    }\n                }\n\n                // 2: left (decrease a)\n                if (cur.a > 0 && remaining >= h) {\n                    long long L_area = remaining / h;\n                    if (L_area > 0) {\n                        int limit = cur.a;\n                        if (limit > 0) {\n                            for (int j = 0; j < n; ++j) {\n                                if (j == i) continue;\n                                const Rect &s = rectRef[j];\n                                // y-overlap?\n                                if (s.d <= cur.b || cur.d <= s.b) continue;\n                                if (s.a >= cur.a) {\n                                    // s to the right or touching\n                                    continue;\n                                } else {\n                                    if (s.c > cur.a) {\n                                        // s crosses x = cur.a\n                                        limit = 0;\n                                        break;\n                                    } else {\n                                        int cand = cur.a - s.c;\n                                        if (cand < limit) {\n                                            limit = cand;\n                                            if (limit <= 0) {\n                                                limit = 0;\n                                                break;\n                                            }\n                                        }\n                                    }\n                                }\n                            }\n                            if (limit > 0) {\n                                int L = (int)min<long long>(limit, L_area);\n                                if (L > 0) {\n                                    long long delta = 1LL * L * h;\n                                    if (delta > bestDelta) {\n                                        bestDelta = delta;\n                                        bestDir = 2;\n                                        bestL = L;\n                                    }\n                                }\n                            }\n                        }\n                    }\n                }\n\n                // 3: right (increase c)\n                if (cur.c < 10000 && remaining >= h) {\n                    long long L_area = remaining / h;\n                    if (L_area > 0) {\n                        int limit = 10000 - cur.c;\n                        if (limit > 0) {\n                            for (int j = 0; j < n; ++j) {\n                                if (j == i) continue;\n                                const Rect &s = rectRef[j];\n                                // y-overlap?\n                                if (s.d <= cur.b || cur.d <= s.b) continue;\n                                if (cur.c >= s.c) {\n                                    // s to the left or touching\n                                    continue;\n                                } else {\n                                    if (s.a <= cur.c) {\n                                        // s crosses x = cur.c\n                                        limit = 0;\n                                        break;\n                                    } else {\n                                        int cand = s.a - cur.c;\n                                        if (cand < limit) {\n                                            limit = cand;\n                                            if (limit <= 0) {\n                                                limit = 0;\n                                                break;\n                                            }\n                                        }\n                                    }\n                                }\n                            }\n                            if (limit > 0) {\n                                int L = (int)min<long long>(limit, L_area);\n                                if (L > 0) {\n                                    long long delta = 1LL * L * h;\n                                    if (delta > bestDelta) {\n                                        bestDelta = delta;\n                                        bestDir = 3;\n                                        bestL = L;\n                                    }\n                                }\n                            }\n                        }\n                    }\n                }\n\n                if (bestDir == -1 || bestL <= 0 || bestDelta <= 0) break;\n\n                switch (bestDir) {\n                    case 0: cur.d += bestL; break;\n                    case 1: cur.b -= bestL; break;\n                    case 2: cur.a -= bestL; break;\n                    case 3: cur.c += bestL; break;\n                }\n                areaRef[i] += bestDelta;\n            }\n        }\n    };\n\n    greedy_finalize(bestRect, bestArea);\n\n    // Output best layout\n    for (int i = 0; i < n; ++i) {\n        cout << bestRect[i].a << ' ' << bestRect[i].b << ' '\n             << bestRect[i].c << ' ' << bestRect[i].d << '\\n';\n    }\n\n    return 0;\n}","ahc002":"#include <bits/stdc++.h>\nusing namespace std;\n\n// Fast xorshift RNG\nstruct XorShift64 {\n    uint64_t x;\n    XorShift64() {\n        uint64_t seed = chrono::steady_clock::now().time_since_epoch().count();\n        x = seed ^ (seed << 13);\n    }\n    inline uint64_t next() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return x;\n    }\n    inline uint32_t next_u32() {\n        return static_cast<uint32_t>(next());\n    }\n};\n\nstruct Path {\n    int score;\n    vector<int> seq;\n};\n\nconstexpr int H = 50;\nconstexpr int W = 50;\nconstexpr int N = H * W;\nconstexpr int MAX_TILES = 2500;\nconstexpr int ELITE_K = 3;\n\nint tileID[N];                 // tile index for each cell\nint valCell[N];                // score of each cell\nint nei[N][4];                 // neighbors (cell indices)\nint neiCnt[N];                 // number of neighbors for each cell\nint visitedTime[MAX_TILES];    // last iteration stamp when tile was visited\nint startCell;                 // starting cell index\nint maxTileId;                 // maximum tile id in input\n\nint iterStamp = 0;\nXorShift64 rng;\n\nvector<Path> elites; // top-K best paths\n\n// Check if tile t is visited in current walk\ninline bool isVisitedTile(int t) {\n    return visitedTime[t] == iterStamp;\n}\n\n// Compare paths: longer is better; if same length, higher score is better\ninline bool better_path(const Path &a, const Path &b) {\n    if (a.seq.size() != b.seq.size()) return a.seq.size() > b.seq.size();\n    return a.score > b.score;\n}\n\n// Maintain top-K elite paths\nvoid update_elites(const Path &cur) {\n    if (elites.empty()) {\n        elites.push_back(cur);\n        return;\n    }\n    int pos = (int)elites.size();\n    while (pos > 0 && better_path(cur, elites[pos - 1])) pos--;\n    if (pos >= ELITE_K) return; // not better than any current elite within K\n    elites.insert(elites.begin() + pos, cur);\n    if ((int)elites.size() > ELITE_K) elites.pop_back();\n}\n\n// Common extension logic used from any starting state (start or prefix)\nvoid extend_path(Path &path, int cur, int mode) {\n    while (true) {\n        int cand[4];\n        int candCount = 0;\n\n        // Collect candidate neighbors: adjacent cells whose tile is not yet visited\n        for (int k = 0; k < neiCnt[cur]; ++k) {\n            int v = nei[cur][k];\n            int t = tileID[v];\n            if (isVisitedTile(t)) continue; // tile already visited\n            cand[candCount++] = v;\n        }\n\n        if (candCount == 0) break;\n\n        int deg[4];\n\n        // Compute \"forward degree\" for each candidate: how many moves are possible after stepping there\n        for (int i = 0; i < candCount; ++i) {\n            int v = cand[i];\n            int tv = tileID[v];\n            int d = 0;\n            for (int k = 0; k < neiCnt[v]; ++k) {\n                int w = nei[v][k];\n                int tw = tileID[w];\n                if (tw == tv) continue;          // same tile (other cell)\n                if (isVisitedTile(tw)) continue; // tile already used\n                ++d;\n            }\n            deg[i] = d;\n        }\n\n        int chosenIdx = 0;\n\n        if (mode == 0) {\n            // Mode 0: balanced\n            // Prefer class 0 (deg>=2), then 1 (deg==1), then 2 (deg==0)\n            // Within class: smaller deg first, then higher value\n            int bestClass = 3;\n            int bestDeg = 1000;\n            int bestVal = -1;\n            for (int i = 0; i < candCount; ++i) {\n                int d = deg[i];\n                int cls = (d >= 2 ? 0 : (d == 1 ? 1 : 2));\n                int v = cand[i];\n                int pv = valCell[v];\n                bool better = false;\n\n                if (cls < bestClass) {\n                    better = true;\n                } else if (cls == bestClass) {\n                    if (d < bestDeg) {\n                        better = true;\n                    } else if (d == bestDeg) {\n                        if (pv > bestVal) {\n                            better = true;\n                        } else if (pv == bestVal) {\n                            // random tie-break\n                            if (rng.next_u32() & 1u) better = true;\n                        }\n                    }\n                }\n\n                if (better) {\n                    bestClass = cls;\n                    bestDeg = d;\n                    bestVal = pv;\n                    chosenIdx = i;\n                }\n            }\n        } else if (mode == 1) {\n            // Mode 1: Warnsdorff-like (minimize deg), but avoid deg=0 if possible.\n            bool hasPositive = false;\n            for (int i = 0; i < candCount; ++i) {\n                if (deg[i] > 0) { hasPositive = true; break; }\n            }\n\n            int bestDeg = 1000;\n            int bestVal = -1;\n            for (int i = 0; i < candCount; ++i) {\n                int d = deg[i];\n                if (hasPositive && d == 0) continue; // skip dead-ends if any extension exists\n                int v = cand[i];\n                int pv = valCell[v];\n                bool better = false;\n\n                if (d < bestDeg) {\n                    better = true;\n                } else if (d == bestDeg) {\n                    if (pv > bestVal) {\n                        better = true;\n                    } else if (pv == bestVal) {\n                        if (rng.next_u32() & 1u) better = true;\n                    }\n                }\n\n                if (better) {\n                    bestDeg = d;\n                    bestVal = pv;\n                    chosenIdx = i;\n                }\n            }\n        } else {\n            // Mode 2: value-first, but avoid deg=0 if possible.\n            bool hasPositive = false;\n            for (int i = 0; i < candCount; ++i) {\n                if (deg[i] > 0) { hasPositive = true; break; }\n            }\n\n            int bestVal = -1;\n            int bestDeg = -1;\n            for (int i = 0; i < candCount; ++i) {\n                int d = deg[i];\n                if (hasPositive && d == 0) continue; // skip dead-ends if any extension exists\n                int v = cand[i];\n                int pv = valCell[v];\n                bool better = false;\n\n                if (pv > bestVal) {\n                    better = true;\n                } else if (pv == bestVal) {\n                    if (d > bestDeg) {\n                        better = true;\n                    } else if (d == bestDeg) {\n                        if (rng.next_u32() & 1u) better = true;\n                    }\n                }\n\n                if (better) {\n                    bestVal = pv;\n                    bestDeg = d;\n                    chosenIdx = i;\n                }\n            }\n        }\n\n        // Small random exploration: 5% chance choose totally random candidate\n        if (candCount > 1 && (rng.next_u32() % 20u == 0u)) {\n            chosenIdx = rng.next_u32() % candCount;\n        }\n\n        int nextCell = cand[chosenIdx];\n        cur = nextCell;\n        path.seq.push_back(cur);\n        path.score += valCell[cur];\n        visitedTime[tileID[cur]] = iterStamp;\n    }\n}\n\n// Build a path starting from the fixed starting cell\nPath build_path(int mode) {\n    ++iterStamp;\n    Path path;\n    path.seq.reserve(N);\n    path.score = 0;\n\n    int cur = startCell;\n    path.seq.push_back(cur);\n    path.score += valCell[cur];\n    visitedTime[tileID[cur]] = iterStamp;\n\n    extend_path(path, cur, mode);\n    return path;\n}\n\n// Build a path starting from a prefix of an existing path\nPath build_path_from_prefix(const vector<int>& prefix, int pivot, int mode) {\n    ++iterStamp;\n    Path path;\n    path.seq.reserve(N);\n    path.score = 0;\n\n    // Mark tiles in prefix up to pivot as visited and copy to path\n    for (int i = 0; i <= pivot; ++i) {\n        int cell = prefix[i];\n        path.seq.push_back(cell);\n        path.score += valCell[cell];\n        visitedTime[tileID[cell]] = iterStamp;\n    }\n    int cur = prefix[pivot];\n\n    extend_path(path, cur, mode);\n    return path;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int si, sj;\n    if (!(cin >> si >> sj)) {\n        return 0;\n    }\n\n    maxTileId = -1;\n\n    // Read tiles\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            int t;\n            cin >> t;\n            int idx = i * W + j;\n            tileID[idx] = t;\n            if (t > maxTileId) maxTileId = t;\n        }\n    }\n\n    // Read cell values\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            int p;\n            cin >> p;\n            int idx = i * W + j;\n            valCell[idx] = p;\n        }\n    }\n\n    // Precompute neighbors on the grid (4-neighborhood)\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            int idx = i * W + j;\n            int cnt = 0;\n            if (i > 0)     nei[idx][cnt++] = (i - 1) * W + j;\n            if (i + 1 < H) nei[idx][cnt++] = (i + 1) * W + j;\n            if (j > 0)     nei[idx][cnt++] = i * W + (j - 1);\n            if (j + 1 < W) nei[idx][cnt++] = i * W + (j + 1);\n            neiCnt[idx] = cnt;\n        }\n    }\n\n    // Initialize visitedTime\n    for (int i = 0; i <= maxTileId; ++i) visitedTime[i] = 0;\n\n    startCell = si * W + sj;\n\n    auto startTime = chrono::steady_clock::now();\n    const double TIME_LIMIT = 1.97; // slightly under 2.0s for safety\n\n    Path best;\n    best.score = -1;\n    best.seq.clear();\n    elites.clear();\n\n    int iterations = 0;\n    while (true) {\n        int mode = static_cast<int>(rng.next_u32() % 3u); // 0,1,2 equally likely\n\n        Path cur;\n        bool useScratch;\n        size_t bestLen = best.seq.size();\n\n        if (bestLen < 200) {\n            // Early phase: build from scratch to get a decent initial path\n            useScratch = true;\n        } else if (bestLen < 400) {\n            // Mid phase: 50% scratch, 50% prefix-based refinement\n            useScratch = (rng.next_u32() & 1u);\n        } else {\n            // Late phase: intensify around best path, 20% scratch, 80% prefix\n            useScratch = (rng.next_u32() % 5u == 0u);\n        }\n\n        if (useScratch || elites.empty()) {\n            cur = build_path(mode);\n        } else {\n            // Choose which elite to restart from\n            int eSz = (int)elites.size();\n            int srcIdx = 0;\n            if (eSz == 1) {\n                srcIdx = 0;\n            } else if (eSz == 2) {\n                // 70% best, 30% second best\n                uint32_t r = rng.next_u32() % 10u;\n                srcIdx = (r < 7u ? 0 : 1);\n            } else {\n                // 60% best, 30% second, 10% third\n                uint32_t r = rng.next_u32() % 10u;\n                if (r < 6u) srcIdx = 0;\n                else if (r < 9u) srcIdx = 1;\n                else srcIdx = 2;\n            }\n\n            const vector<int> &pref = elites[srcIdx].seq;\n            int L = (int)pref.size();\n\n            // Choose pivot not too close to the start or the very end.\n            // 20% of the time allow early pivots, 80% focus on later part.\n            int left, right;\n            if (rng.next_u32() % 5u == 0u) {\n                // 20%: wide range, allow early pivot\n                left = 1;\n            } else {\n                // 80%: focus on later part of the path\n                left = L / 4;\n            }\n            right = L - 1 - 10; // leave room for extension\n            if (left < 1) left = 1;\n            if (right <= left) {\n                left = 1;\n                right = L - 2;\n            }\n            if (right <= left) {\n                // Degenerate: fall back to scratch\n                cur = build_path(mode);\n            } else {\n                int width = right - left + 1;\n                // Bias pivot towards the end of the prefix using max of two uniforms\n                uint32_t r0 = rng.next_u32() % (uint32_t)width;\n                uint32_t r1 = rng.next_u32() % (uint32_t)width;\n                int offset = (int)max(r0, r1); // skew to larger indices\n                int pivot = left + offset;\n                cur = build_path_from_prefix(pref, pivot, mode);\n            }\n        }\n\n        // Update global best\n        if (better_path(cur, best)) {\n            best = cur;\n        }\n        // Update elites (top-K)\n        update_elites(cur);\n\n        ++iterations;\n        if ((iterations & 7) == 0) { // check time every 8 iterations\n            auto now = chrono::steady_clock::now();\n            double elapsed = chrono::duration<double>(now - startTime).count();\n            if (elapsed > TIME_LIMIT) break;\n        }\n    }\n\n    // Use best of elites if for some reason it's better than 'best'\n    if (!elites.empty() && better_path(elites[0], best)) {\n        best = elites[0];\n    }\n\n    // Convert best.seq (cells) into moves string\n    string ans;\n    ans.reserve(best.seq.size());\n    for (size_t k = 1; k < best.seq.size(); ++k) {\n        int prev = best.seq[k - 1];\n        int cur = best.seq[k];\n        int pi = prev / W, pj = prev % W;\n        int ci = cur / W, cj = cur % W;\n        if (ci == pi) {\n            if (cj == pj + 1) ans.push_back('R');\n            else if (cj == pj - 1) ans.push_back('L');\n        } else if (cj == pj) {\n            if (ci == pi + 1) ans.push_back('D');\n            else if (ci == pi - 1) ans.push_back('U');\n        }\n        // No other case should occur because we only move to neighbors.\n    }\n\n    cout << ans << '\\n';\n    return 0;\n}","ahc003":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const int H = 30;\nstatic const int W = 30;\nstatic const int N = H * W;\nstatic const int EH = H * (W - 1); // number of horizontal edges\nstatic const int EV = (H - 1) * W; // number of vertical edges\nstatic const int E  = EH + EV;\nstatic const double INF = 1e100;\n\n// Edge indices for canonical orientations\nint h_id[H][W - 1]; // horizontal: (i,j)-(i,j+1) -> h_id[i][j]\nint v_id[H - 1][W]; // vertical:   (i,j)-(i+1,j) -> v_id[i][j]\n\n// Adjacency list: (to, edge_id)\nvector<pair<int,int>> adj[N];\n\n// Our edge weight estimates and temporary jittered weights\nvector<double> w(E), eff_w(E);\n\n// Dijkstra buffers\ndouble dist_arr[N];\nint prev_v_arr[N];\n\n// RNG for jitter\nmt19937_64 rng(71236782123ULL);\n\ninline double rand01() {\n    return std::generate_canonical<double, 53>(rng); // [0,1)\n}\n\ninline int vid(int i, int j) {\n    return i * W + j;\n}\n\n// Fallback: simple Manhattan path and its edges, with predicted cost under w[]\nvoid build_manhattan(int si, int sj, int ti, int tj,\n                     string &path, vector<int> &edges, double &pred_cost) {\n    path.clear();\n    int ci = si, cj = sj;\n    while (ci < ti) { path.push_back('D'); ++ci; }\n    while (ci > ti) { path.push_back('U'); --ci; }\n    while (cj < tj) { path.push_back('R'); ++cj; }\n    while (cj > tj) { path.push_back('L'); --cj; }\n\n    // Convert to edges and cost\n    edges.clear();\n    edges.reserve(path.size());\n    pred_cost = 0.0;\n    ci = si;\n    cj = sj;\n    for (char c : path) {\n        int eid = -1;\n        if (c == 'U') {\n            int ni = ci - 1;\n            eid = v_id[ni][cj];\n            ci = ni;\n        } else if (c == 'D') {\n            eid = v_id[ci][cj];\n            ci = ci + 1;\n        } else if (c == 'L') {\n            int nj = cj - 1;\n            eid = h_id[ci][nj];\n            cj = nj;\n        } else if (c == 'R') {\n            eid = h_id[ci][cj];\n            cj = cj + 1;\n        }\n        edges.push_back(eid);\n        pred_cost += w[eid];\n    }\n}\n\n// Run one Dijkstra with jittered weights, build a candidate path, its edges, and predicted cost\nvoid build_candidate(int si, int sj, int ti, int tj, double jitter,\n                     string &path, vector<int> &edges, double &pred_cost) {\n    // Build jittered effective weights\n    for (int e = 0; e < E; ++e) {\n        double u = 2.0 * rand01() - 1.0; // [-1,1)\n        double factor = 1.0 + jitter * u;\n        if (factor < 0.5) factor = 0.5; // safety\n        eff_w[e] = w[e] * factor;\n        if (eff_w[e] < 1.0) eff_w[e] = 1.0; // strictly positive\n    }\n\n    int s = vid(si, sj);\n    int t = vid(ti, tj);\n\n    // Initialize Dijkstra arrays\n    for (int i = 0; i < N; ++i) {\n        dist_arr[i] = INF;\n        prev_v_arr[i] = -1;\n    }\n    dist_arr[s] = 0.0;\n\n    using P = pair<double,int>;\n    priority_queue<P, vector<P>, greater<P>> pq;\n    pq.emplace(0.0, s);\n\n    while (!pq.empty()) {\n        auto [d, u] = pq.top();\n        pq.pop();\n        if (d != dist_arr[u]) continue;\n        if (u == t) break;\n        for (auto &pe : adj[u]) {\n            int v = pe.first;\n            int eid = pe.second;\n            double nd = d + eff_w[eid];\n            if (nd < dist_arr[v]) {\n                dist_arr[v] = nd;\n                prev_v_arr[v] = u;\n                pq.emplace(nd, v);\n            }\n        }\n    }\n\n    if (prev_v_arr[t] == -1) {\n        // Fallback: Manhattan path (should not happen in connected grid)\n        build_manhattan(si, sj, ti, tj, path, edges, pred_cost);\n        return;\n    }\n\n    // Reconstruct vertex sequence from s to t\n    vector<int> vs_rev;\n    vs_rev.reserve(64);\n    int cur = t;\n    while (cur != s) {\n        vs_rev.push_back(cur);\n        cur = prev_v_arr[cur];\n    }\n    vs_rev.push_back(s); // now vs_rev: [t, ..., s]\n\n    vector<int> vs;\n    vs.reserve(vs_rev.size());\n    for (int idx = (int)vs_rev.size() - 1; idx >= 0; --idx) {\n        vs.push_back(vs_rev[idx]);\n    }\n    int L = (int)vs.size() - 1; // number of edges\n\n    // Build move string and edges, and compute predicted cost under w\n    path.clear();\n    path.reserve(L);\n    edges.clear();\n    edges.reserve(L);\n    pred_cost = 0.0;\n\n    for (int k = 0; k < L; ++k) {\n        int u = vs[k];\n        int v = vs[k + 1];\n        int ui = u / W, uj = u % W;\n        int vi = v / W, vj = v % W;\n\n        char c;\n        int eid = -1;\n\n        if (vi == ui) {\n            if (vj == uj + 1) { // right\n                c = 'R';\n                eid = h_id[ui][uj];\n            } else { // vj == uj - 1, left\n                c = 'L';\n                eid = h_id[ui][vj];\n            }\n        } else { // vj == uj\n            if (vi == ui + 1) { // down\n                c = 'D';\n                eid = v_id[ui][uj];\n            } else { // vi == ui - 1, up\n                c = 'U';\n                eid = v_id[vi][uj];\n            }\n        }\n\n        path.push_back(c);\n        edges.push_back(eid);\n        pred_cost += w[eid];\n    }\n}\n\n// Convert move string into edge list (used only for fallback if needed elsewhere)\nvoid path_to_edges(int si, int sj, const string &path, vector<int> &edges) {\n    edges.clear();\n    edges.reserve(path.size());\n    int i = si, j = sj;\n    for (char c : path) {\n        int eid = -1;\n        if (c == 'U') {\n            int ni = i - 1;\n            eid = v_id[ni][j];\n            i = ni;\n        } else if (c == 'D') {\n            eid = v_id[i][j];\n            i = i + 1;\n        } else if (c == 'L') {\n            int nj = j - 1;\n            eid = h_id[i][nj];\n            j = nj;\n        } else if (c == 'R') {\n            eid = h_id[i][j];\n            j = j + 1;\n        }\n        edges.push_back(eid);\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // Build graph and edge indexing\n    int eid = 0;\n    // Horizontal edges\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W - 1; ++j) {\n            h_id[i][j] = eid;\n            int u = vid(i, j);\n            int v = vid(i, j + 1);\n            adj[u].emplace_back(v, eid);\n            adj[v].emplace_back(u, eid);\n            ++eid;\n        }\n    }\n    // Vertical edges\n    for (int i = 0; i < H - 1; ++i) {\n        for (int j = 0; j < W; ++j) {\n            v_id[i][j] = eid;\n            int u = vid(i, j);\n            int v = vid(i + 1, j);\n            adj[u].emplace_back(v, eid);\n            adj[v].emplace_back(u, eid);\n            ++eid;\n        }\n    }\n\n    // Initialize weights\n    w.assign(E, 5000.0);\n    eff_w.assign(E, 5000.0);\n\n    const double ETA = 0.5; // learning rate multiplier\n\n    vector<int> best_edges, tmp_edges;\n    string best_path, tmp_path;\n\n    for (int q = 0; q < 1000; ++q) {\n        int si, sj, ti, tj;\n        if (!(cin >> si >> sj >> ti >> tj)) {\n            return 0; // EOF / error\n        }\n\n        // Jitter amplitude for this query (same as baseline)\n        const double JITTER0 = 0.03;\n        double jitter = JITTER0 * max(0.0, 1.0 - (double)q / 800.0);\n        if (jitter < 0.0) jitter = 0.0;\n\n        int num_candidates = (jitter > 1e-12 ? 4 : 1);\n\n        double best_cost = INF;\n        best_path.clear();\n        best_edges.clear();\n\n        for (int it = 0; it < num_candidates; ++it) {\n            double pred_cost = 0.0;\n            build_candidate(si, sj, ti, tj, jitter, tmp_path, tmp_edges, pred_cost);\n            if (pred_cost < best_cost) {\n                best_cost = pred_cost;\n                best_path = tmp_path;\n                best_edges = tmp_edges;\n            }\n        }\n\n        // Output chosen path\n        cout << best_path << '\\n';\n        cout.flush();\n\n        long long y_ll;\n        if (!(cin >> y_ll)) {\n            return 0; // EOF / error\n        }\n        double y = (double)y_ll;\n\n        int L = (int)best_edges.size();\n        if (L == 0) continue; // should not happen (Manhattan distance >= 10)\n\n        double pred = best_cost; // predicted cost under w for chosen path\n        double error = y - pred;\n\n        double lr = ETA / (double)L;\n        for (int e : best_edges) {\n            w[e] += lr * error;\n            if (w[e] < 1000.0) w[e] = 1000.0;\n            else if (w[e] > 9000.0) w[e] = 9000.0;\n        }\n    }\n\n    return 0;\n}","ahc004":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const int MAX_N = 20;\nstatic const int MAX_M = 800;\nstatic const int ALPHA = 8;\nstatic const int MAXW  = (MAX_M + 63) / 64;\n\nint N, M;\nint WORDS; // number of 64-bit words used for bitsets\nvector<string> patterns;\n\n// bitset over up to MAX_M bits\nstruct BS {\n    uint64_t w[MAXW];\n};\n\n// bitset helpers\ninline void bs_clear(BS &b) {\n    memset(b.w, 0, sizeof(b.w));\n}\ninline void bs_or_inplace(BS &a, const BS &b) {\n    for (int i = 0; i < WORDS; ++i) a.w[i] |= b.w[i];\n}\ninline void bs_xor(BS &res, const BS &a, const BS &b) {\n    for (int i = 0; i < WORDS; ++i) res.w[i] = a.w[i] ^ b.w[i];\n}\ninline void bs_or(BS &res, const BS &a, const BS &b) {\n    for (int i = 0; i < WORDS; ++i) res.w[i] = a.w[i] | b.w[i];\n}\ninline bool bs_test(const BS &b, int idx) {\n    return (b.w[idx >> 6] >> (idx & 63)) & 1ULL;\n}\ninline void bs_set(BS &b, int idx) {\n    b.w[idx >> 6] |= 1ULL << (idx & 63);\n}\ninline void bs_reset(BS &b, int idx) {\n    b.w[idx >> 6] &= ~(1ULL << (idx & 63));\n}\n\n// iterate over set bits of b, calling f(idx) for each\ntemplate <class F>\ninline void bs_for_each(const BS &b, F f) {\n    for (int w = 0; w < WORDS; ++w) {\n        uint64_t x = b.w[w];\n        while (x) {\n            int lsb = __builtin_ctzll(x);\n            int idx = (w << 6) + lsb;\n            if (idx >= M) return; // safety; bits >= M are not used\n            f(idx);\n            x &= x - 1; // clear lowest set bit\n        }\n    }\n}\n\n// Aho\u2013Corasick automaton\nstruct Node {\n    int next[ALPHA];\n    int link;\n    BS out; // bitset of patterns that end at this state (including via failure)\n    Node() {\n        fill(next, next + ALPHA, -1);\n        link = 0;\n        bs_clear(out);\n    }\n};\nvector<Node> ac;\n\n// grid and evaluation structures\nchar grid[MAX_N][MAX_N];\nBS row_bs[MAX_N], col_bs[MAX_N];\nint pattern_cov_count[MAX_M];\nint current_c = 0;\n\n// RNG\nmt19937_64 rng;\n\ninline int ch_idx(char c) {\n    return c - 'A'; // 'A'..'H' -> 0..7\n}\n\nvoid build_automaton() {\n    ac.clear();\n    ac.emplace_back(); // root\n\n    // build trie and set pattern bits\n    for (int i = 0; i < M; ++i) {\n        const string &s = patterns[i];\n        int v = 0;\n        for (char ch : s) {\n            int c = ch_idx(ch);\n            if (ac[v].next[c] == -1) {\n                ac[v].next[c] = (int)ac.size();\n                ac.emplace_back();\n            }\n            v = ac[v].next[c];\n        }\n        bs_set(ac[v].out, i);\n    }\n\n    // build failure links\n    queue<int> q;\n\n    for (int c = 0; c < ALPHA; ++c) {\n        int u = ac[0].next[c];\n        if (u != -1) {\n            ac[u].link = 0;\n            q.push(u);\n        } else {\n            ac[0].next[c] = 0;\n        }\n    }\n\n    while (!q.empty()) {\n        int v = q.front(); q.pop();\n        int link = ac[v].link;\n\n        // propagate pattern bits from failure link\n        bs_or_inplace(ac[v].out, ac[link].out);\n\n        for (int c = 0; c < ALPHA; ++c) {\n            int u = ac[v].next[c];\n            if (u != -1) {\n                ac[u].link = ac[link].next[c];\n                q.push(u);\n            } else {\n                ac[v].next[c] = ac[link].next[c];\n            }\n        }\n    }\n}\n\n// scan a line through AC, return bitset of patterns appearing\ninline BS scan_line(const char *s, int len) {\n    BS res;\n    bs_clear(res);\n    int v = 0;\n    for (int i = 0; i < len; ++i) {\n        int c = ch_idx(s[i]);\n        v = ac[v].next[c];\n        bs_or_inplace(res, ac[v].out);\n    }\n    return res;\n}\n\n// recompute one row r and update global counts\nvoid recalc_row(int r) {\n    char line[2 * MAX_N];\n    for (int j = 0; j < N; ++j) line[j] = grid[r][j];\n    for (int j = 0; j < N; ++j) line[N + j] = line[j];\n\n    BS mark = scan_line(line, 2 * N);\n    BS changed;\n    bs_xor(changed, row_bs[r], mark);\n\n    bs_for_each(changed, [&](int i) {\n        bool oldFlag = bs_test(row_bs[r], i);\n        bool newFlag = bs_test(mark, i);\n        if (oldFlag == newFlag) return;\n\n        if (newFlag) {\n            bs_set(row_bs[r], i);\n            if (pattern_cov_count[i] == 0) current_c++;\n            pattern_cov_count[i]++;\n        } else {\n            bs_reset(row_bs[r], i);\n            pattern_cov_count[i]--;\n            if (pattern_cov_count[i] == 0) current_c--;\n        }\n    });\n}\n\n// recompute one column c and update global counts\nvoid recalc_col(int c) {\n    char line[2 * MAX_N];\n    for (int i = 0; i < N; ++i) line[i] = grid[i][c];\n    for (int i = 0; i < N; ++i) line[N + i] = line[i];\n\n    BS mark = scan_line(line, 2 * N);\n    BS changed;\n    bs_xor(changed, col_bs[c], mark);\n\n    bs_for_each(changed, [&](int i) {\n        bool oldFlag = bs_test(col_bs[c], i);\n        bool newFlag = bs_test(mark, i);\n        if (oldFlag == newFlag) return;\n\n        if (newFlag) {\n            bs_set(col_bs[c], i);\n            if (pattern_cov_count[i] == 0) current_c++;\n            pattern_cov_count[i]++;\n        } else {\n            bs_reset(col_bs[c], i);\n            pattern_cov_count[i]--;\n            if (pattern_cov_count[i] == 0) current_c--;\n        }\n    });\n}\n\n// targeted pattern \"kick\": prefer patterns with low coverage and place them greedily\nvoid apply_pattern_kick() {\n    if (M == 0) return;\n\n    uniform_int_distribution<int> base_dist(0, M - 1);\n    int base = base_dist(rng);\n    int pid = -1;\n\n    // coverage == 0 preferred\n    for (int j = 0; j < M; ++j) {\n        int id = (base + j) % M;\n        if (pattern_cov_count[id] == 0) {\n            pid = id;\n            break;\n        }\n    }\n    // then coverage == 1\n    if (pid == -1) {\n        for (int j = 0; j < M; ++j) {\n            int id = (base + j) % M;\n            if (pattern_cov_count[id] == 1) {\n                pid = id;\n                break;\n            }\n        }\n    }\n    // fallback to base\n    if (pid == -1) pid = base;\n\n    const string &s = patterns[pid];\n    int len = (int)s.size();\n\n    int bestScore = -1;\n    int bestDir = 0; // 0: horizontal, 1: vertical\n    int bestR = 0, bestC = 0;\n\n    // horizontal placements\n    for (int r = 0; r < N; ++r) {\n        for (int c0 = 0; c0 < N; ++c0) {\n            int score = 0;\n            int c = c0;\n            for (int t = 0; t < len; ++t) {\n                if (grid[r][c] == s[t]) score++;\n                c++;\n                if (c == N) c = 0;\n            }\n            if (score > bestScore) {\n                bestScore = score;\n                bestDir = 0;\n                bestR = r;\n                bestC = c0;\n            } else if (score == bestScore && (rng() & 1)) {\n                bestScore = score;\n                bestDir = 0;\n                bestR = r;\n                bestC = c0;\n            }\n        }\n    }\n\n    // vertical placements\n    for (int c = 0; c < N; ++c) {\n        for (int r0 = 0; r0 < N; ++r0) {\n            int score = 0;\n            int r = r0;\n            for (int t = 0; t < len; ++t) {\n                if (grid[r][c] == s[t]) score++;\n                r++;\n                if (r == N) r = 0;\n            }\n            if (score > bestScore) {\n                bestScore = score;\n                bestDir = 1;\n                bestR = r0;\n                bestC = c;\n            } else if (score == bestScore && (rng() & 1)) {\n                bestScore = score;\n                bestDir = 1;\n                bestR = r0;\n                bestC = c;\n            }\n        }\n    }\n\n    bool rowChanged[MAX_N] = {false};\n    bool colChanged[MAX_N] = {false};\n\n    // apply best placement\n    if (bestDir == 0) {\n        int r = bestR;\n        int c = bestC;\n        for (int t = 0; t < len; ++t) {\n            if (grid[r][c] != s[t]) {\n                grid[r][c] = s[t];\n                rowChanged[r] = true;\n                colChanged[c] = true;\n            }\n            c++;\n            if (c == N) c = 0;\n        }\n    } else {\n        int c = bestC;\n        int r = bestR;\n        for (int t = 0; t < len; ++t) {\n            if (grid[r][c] != s[t]) {\n                grid[r][c] = s[t];\n                rowChanged[r] = true;\n                colChanged[c] = true;\n            }\n            r++;\n            if (r == N) r = 0;\n        }\n    }\n\n    // recompute affected rows/columns\n    for (int r = 0; r < N; ++r) if (rowChanged[r]) recalc_row(r);\n    for (int c = 0; c < N; ++c) if (colChanged[c]) recalc_col(c);\n}\n\ndouble my_rand_double() {\n    // 53-bit mantissa random double in [0,1)\n    return (rng() >> 11) * (1.0 / (1ULL << 53));\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> M;\n    patterns.resize(M);\n    for (int i = 0; i < M; ++i) cin >> patterns[i];\n\n    WORDS = (M + 63) / 64;\n\n    // init RNG\n    uint64_t seed = chrono::high_resolution_clock::now().time_since_epoch().count();\n    rng.seed(seed);\n\n    build_automaton();\n\n    uniform_int_distribution<int> letter_dist(0, ALPHA - 1);\n\n    // initial grid: random letters (uniform)\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            grid[i][j] = char('A' + letter_dist(rng));\n\n    // constructive pass:\n    //  - shuffle to randomize\n    //  - then sort by descending length so longer patterns are placed first\n    vector<int> order(M);\n    iota(order.begin(), order.end(), 0);\n    shuffle(order.begin(), order.end(), rng);\n    stable_sort(order.begin(), order.end(), [&](int a, int b) {\n        return patterns[a].size() > patterns[b].size();\n    });\n\n    for (int idx = 0; idx < M; ++idx) {\n        int pid = order[idx];\n        const string &s = patterns[pid];\n        int len = (int)s.size();\n\n        int bestScore = -1;\n        int bestDir = 0;\n        int bestR = 0, bestC = 0;\n\n        // horizontal candidates\n        for (int r = 0; r < N; ++r) {\n            for (int c0 = 0; c0 < N; ++c0) {\n                int score = 0;\n                int c = c0;\n                for (int t = 0; t < len; ++t) {\n                    if (grid[r][c] == s[t]) score++;\n                    c++;\n                    if (c == N) c = 0;\n                }\n                if (score > bestScore) {\n                    bestScore = score;\n                    bestDir = 0;\n                    bestR = r;\n                    bestC = c0;\n                } else if (score == bestScore && my_rand_double() < 0.5) {\n                    bestScore = score;\n                    bestDir = 0;\n                    bestR = r;\n                    bestC = c0;\n                }\n            }\n        }\n\n        // vertical candidates\n        for (int c = 0; c < N; ++c) {\n            for (int r0 = 0; r0 < N; ++r0) {\n                int score = 0;\n                int r = r0;\n                for (int t = 0; t < len; ++t) {\n                    if (grid[r][c] == s[t]) score++;\n                    r++;\n                    if (r == N) r = 0;\n                }\n                if (score > bestScore) {\n                    bestScore = score;\n                    bestDir = 1;\n                    bestR = r0;\n                    bestC = c;\n                } else if (score == bestScore && my_rand_double() < 0.5) {\n                    bestScore = score;\n                    bestDir = 1;\n                    bestR = r0;\n                    bestC = c;\n                }\n            }\n        }\n\n        // apply best placement\n        if (bestDir == 0) {\n            int r = bestR;\n            int c = bestC;\n            for (int t = 0; t < len; ++t) {\n                grid[r][c] = s[t];\n                c++;\n                if (c == N) c = 0;\n            }\n        } else {\n            int c = bestC;\n            int r = bestR;\n            for (int t = 0; t < len; ++t) {\n                grid[r][c] = s[t];\n                r++;\n                if (r == N) r = 0;\n            }\n        }\n    }\n\n    // Initialize evaluation\n    for (int r = 0; r < N; ++r) bs_clear(row_bs[r]);\n    for (int c = 0; c < N; ++c) bs_clear(col_bs[c]);\n    fill(pattern_cov_count, pattern_cov_count + M, 0);\n    current_c = 0;\n\n    for (int r = 0; r < N; ++r) recalc_row(r);\n    for (int c = 0; c < N; ++c) recalc_col(c);\n\n    // SA parameters\n    const double TIME_LIMIT = 2.78; // seconds for SA part\n    auto start_time = chrono::high_resolution_clock::now();\n    double T0 = 1.5;\n    double T1 = 0.05;\n\n    // keep best grid\n    char best_grid[MAX_N][MAX_N];\n    int best_c = current_c;\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            best_grid[i][j] = grid[i][j];\n\n    int iter = 0;\n    int stagnation = 0; // iterations since last improvement of best_c\n    uniform_int_distribution<int> row_dist(0, N - 1);\n    uniform_int_distribution<int> col_dist(0, N - 1);\n\n    double progress = 0.0;\n    double T = T0;\n\n    while (true) {\n        ++iter;\n        if ((iter & 511) == 0) {\n            auto now = chrono::high_resolution_clock::now();\n            double elapsed = chrono::duration<double>(now - start_time).count();\n            if (elapsed > TIME_LIMIT) break;\n            progress = elapsed / TIME_LIMIT;\n            if (progress > 1.0) progress = 1.0;\n            T = T0 + (T1 - T0) * progress;\n        }\n\n        // periodic targeted kicks early\n        if ((iter % 2000 == 0) && (progress < 0.5)) {\n            apply_pattern_kick();\n            if (current_c > best_c) {\n                best_c = current_c;\n                stagnation = 0;\n                for (int i = 0; i < N; ++i)\n                    for (int j = 0; j < N; ++j)\n                        best_grid[i][j] = grid[i][j];\n            }\n        }\n\n        // stagnation-based stronger kicks\n        if (stagnation > 25000 && progress < 0.7) {\n            for (int t = 0; t < 3; ++t) apply_pattern_kick();\n            stagnation = 0;\n            if (current_c > best_c) {\n                best_c = current_c;\n                for (int i = 0; i < N; ++i)\n                    for (int j = 0; j < N; ++j)\n                        best_grid[i][j] = grid[i][j];\n            }\n        }\n\n        int r = row_dist(rng);\n        int c = col_dist(rng);\n        char oldCh = grid[r][c];\n\n        char newCh;\n        do {\n            newCh = char('A' + letter_dist(rng));\n        } while (newCh == oldCh);\n\n        // candidate row\n        char row_line[2 * MAX_N];\n        for (int j = 0; j < N; ++j)\n            row_line[j] = (j == c) ? newCh : grid[r][j];\n        for (int j = 0; j < N; ++j)\n            row_line[N + j] = row_line[j];\n\n        BS mark_row = scan_line(row_line, 2 * N);\n\n        // candidate column\n        char col_line[2 * MAX_N];\n        for (int i = 0; i < N; ++i)\n            col_line[i] = (i == r) ? newCh : grid[i][c];\n        for (int i = 0; i < N; ++i)\n            col_line[N + i] = col_line[i];\n\n        BS mark_col = scan_line(col_line, 2 * N);\n\n        // changed patterns on row and column\n        BS changed_row, changed_col, changed_union;\n        bs_xor(changed_row, row_bs[r], mark_row);\n        bs_xor(changed_col, col_bs[c], mark_col);\n        bs_or(changed_union, changed_row, changed_col);\n\n        int new_c = current_c;\n\n        // compute new_c considering only changed patterns\n        bs_for_each(changed_union, [&](int i) {\n            int oldCov = pattern_cov_count[i];\n            int newCov = oldCov;\n\n            bool oldRow = bs_test(row_bs[r], i);\n            bool newRow = bs_test(mark_row, i);\n            newCov += (int)newRow - (int)oldRow;\n\n            bool oldCol = bs_test(col_bs[c], i);\n            bool newCol = bs_test(mark_col, i);\n            newCov += (int)newCol - (int)oldCol;\n\n            if (oldCov == 0 && newCov > 0) new_c++;\n            else if (oldCov > 0 && newCov == 0) new_c--;\n        });\n\n        int delta = new_c - current_c;\n        bool accept = false;\n        if (delta >= 0) {\n            accept = true;\n        } else {\n            double prob = exp((double)delta / T);\n            if (prob > my_rand_double()) accept = true;\n        }\n\n        if (accept) {\n            // commit the change\n            grid[r][c] = newCh;\n            bs_for_each(changed_union, [&](int i) {\n                int oldCov = pattern_cov_count[i];\n                int newCov = oldCov;\n\n                bool oldRow = bs_test(row_bs[r], i);\n                bool newRow = bs_test(mark_row, i);\n                newCov += (int)newRow - (int)oldRow;\n\n                bool oldCol = bs_test(col_bs[c], i);\n                bool newCol = bs_test(mark_col, i);\n                newCov += (int)newCol - (int)oldCol;\n\n                pattern_cov_count[i] = newCov;\n\n                if (newRow) bs_set(row_bs[r], i);\n                else bs_reset(row_bs[r], i);\n                if (newCol) bs_set(col_bs[c], i);\n                else bs_reset(col_bs[c], i);\n            });\n            current_c = new_c;\n\n            if (current_c > best_c) {\n                best_c = current_c;\n                stagnation = 0;\n                for (int i = 0; i < N; ++i)\n                    for (int j = 0; j < N; ++j)\n                        best_grid[i][j] = grid[i][j];\n            } else {\n                stagnation++;\n            }\n        } else {\n            stagnation++;\n        }\n    }\n\n    // Output best grid\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) cout << best_grid[i][j];\n        cout << '\\n';\n    }\n\n    return 0;\n}","ahc005":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Edge {\n    int to;\n    int w;\n};\n\nconst int INF = 1e9;\n\n// Compute travel time of a route (sequence of cell IDs).\n// Cost to move into cell v is cost[v].\nlong long computeTravelTime(const vector<int> &route, const vector<int> &cost) {\n    long long t = 0;\n    for (int i = 1; i < (int)route.size(); ++i) {\n        t += cost[route[i]];\n    }\n    return t;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, si, sj;\n    if (!(cin >> N >> si >> sj)) return 0;\n    vector<string> grid(N);\n    for (int i = 0; i < N; ++i) cin >> grid[i];\n\n    // Map each road cell to an ID\n    static int idOf[70][70];\n    int r = 0;\n    vector<pair<int,int>> pos;   // id -> (i,j)\n    vector<int> cost;            // id -> cell cost (5-9)\n    pos.reserve(N * N);\n    cost.reserve(N * N);\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (grid[i][j] != '#') {\n                idOf[i][j] = r++;\n                pos.emplace_back(i, j);\n                cost.push_back(grid[i][j] - '0');\n            } else {\n                idOf[i][j] = -1;\n            }\n        }\n    }\n\n    if (r == 0) {\n        cout << \"\\n\";\n        return 0;\n    }\n\n    int startId = idOf[si][sj];\n\n    // Build graph of road cells\n    vector<vector<Edge>> G(r);\n    int di[4] = {-1, 1, 0, 0};\n    int dj[4] = {0, 0, -1, 1};\n    for (int id = 0; id < r; ++id) {\n        auto [i, j] = pos[id];\n        for (int d = 0; d < 4; ++d) {\n            int ni = i + di[d], nj = j + dj[d];\n            if (0 <= ni && ni < N && 0 <= nj && nj < N && idOf[ni][nj] != -1) {\n                int v = idOf[ni][nj];\n                G[id].push_back({v, cost[v]});\n            }\n        }\n    }\n\n    // ---------- Build horizontal and vertical segments ----------\n    vector<vector<int>> rowSegCells;\n    vector<int> rowSegIdOfCell(r, -1);\n    for (int i = 0; i < N; ++i) {\n        int j = 0;\n        while (j < N) {\n            if (grid[i][j] == '#') {\n                ++j;\n                continue;\n            }\n            int segIdx = (int)rowSegCells.size();\n            rowSegCells.emplace_back();\n            while (j < N && grid[i][j] != '#') {\n                int id = idOf[i][j];\n                rowSegIdOfCell[id] = segIdx;\n                rowSegCells.back().push_back(id);\n                ++j;\n            }\n        }\n    }\n\n    vector<vector<int>> colSegCells;\n    vector<int> colSegIdOfCell(r, -1);\n    for (int j = 0; j < N; ++j) {\n        int i = 0;\n        while (i < N) {\n            if (grid[i][j] == '#') {\n                ++i;\n                continue;\n            }\n            int segIdx = (int)colSegCells.size();\n            colSegCells.emplace_back();\n            while (i < N && grid[i][j] != '#') {\n                int id = idOf[i][j];\n                colSegIdOfCell[id] = segIdx;\n                colSegCells.back().push_back(id);\n                ++i;\n            }\n        }\n    }\n\n    // ---------- Precompute visibility (coverage) for all cells ----------\n    vector<vector<int>> coverageAll(r);\n    for (int id = 0; id < r; ++id) {\n        auto &v = coverageAll[id];\n        auto &rowV = rowSegCells[rowSegIdOfCell[id]];\n        auto &colV = colSegCells[colSegIdOfCell[id]];\n        v.reserve(rowV.size() + colV.size());\n        for (int x : rowV) v.push_back(x);\n        // avoid counting the same cell twice (self) from row & col\n        for (int x : colV) if (x != id) v.push_back(x);\n    }\n\n    // ---------- Build candidate vantage cells (mostly intersections) ----------\n    vector<char> isIntersection(r, 0);\n    vector<char> hasInterRow(rowSegCells.size(), 0);\n    vector<char> hasInterCol(colSegCells.size(), 0);\n\n    for (int id = 0; id < r; ++id) {\n        auto [i, j] = pos[id];\n        bool hor = false, ver = false;\n        if (j > 0 && idOf[i][j-1] != -1) hor = true;\n        if (j+1 < N && idOf[i][j+1] != -1) hor = true;\n        if (i > 0 && idOf[i-1][j] != -1) ver = true;\n        if (i+1 < N && idOf[i+1][j] != -1) ver = true;\n        if (hor && ver) {\n            isIntersection[id] = 1;\n            hasInterRow[rowSegIdOfCell[id]] = 1;\n            hasInterCol[colSegIdOfCell[id]] = 1;\n        }\n    }\n\n    vector<char> isCandidate(r, 0);\n    vector<int> candidateCells;\n    candidateCells.reserve(r);\n\n    // Intersections\n    for (int id = 0; id < r; ++id) {\n        if (isIntersection[id]) {\n            isCandidate[id] = 1;\n            candidateCells.push_back(id);\n        }\n    }\n    // Midpoints of segments without intersections\n    for (int s = 0; s < (int)rowSegCells.size(); ++s) {\n        if (!hasInterRow[s]) {\n            int mid = rowSegCells[s][rowSegCells[s].size() / 2];\n            if (!isCandidate[mid]) {\n                isCandidate[mid] = 1;\n                candidateCells.push_back(mid);\n            }\n        }\n    }\n    for (int s = 0; s < (int)colSegCells.size(); ++s) {\n        if (!hasInterCol[s]) {\n            int mid = colSegCells[s][colSegCells[s].size() / 2];\n            if (!isCandidate[mid]) {\n                isCandidate[mid] = 1;\n                candidateCells.push_back(mid);\n            }\n        }\n    }\n    // Ensure start cell is candidate\n    if (!isCandidate[startId]) {\n        isCandidate[startId] = 1;\n        candidateCells.push_back(startId);\n    }\n\n    // Coverage of candidates, and which cells are coverable by some candidate\n    int C = (int)candidateCells.size();\n    vector<vector<int>> candCover;\n    candCover.reserve(C);\n    vector<char> cellCovered(r, 0);\n    for (int idx = 0; idx < C; ++idx) {\n        int cell = candidateCells[idx];\n        candCover.push_back(coverageAll[cell]);\n        for (int x : candCover.back()) cellCovered[x] = 1;\n    }\n\n    // Patch: if some cell is not covered by any candidate, add it itself as candidate\n    for (int id = 0; id < r; ++id) {\n        if (!cellCovered[id]) {\n            candidateCells.push_back(id);\n            candCover.push_back(coverageAll[id]);\n            for (int x : coverageAll[id]) cellCovered[x] = 1;\n        }\n    }\n    C = (int)candidateCells.size();\n\n    // ---------- Greedy set cover on candidates (cell-based) ----------\n    vector<int> vantageCells;        // resulting vantage cell IDs\n    vantageCells.reserve(C);\n\n    vector<char> coveredCells(r, 0);\n    int coveredCount = 0;\n    vector<char> candSelected(C, 0);\n\n    auto selectCandidate = [&](int idx) {\n        if (candSelected[idx]) return;\n        candSelected[idx] = 1;\n        int cell = candidateCells[idx];\n        vantageCells.push_back(cell);\n        for (int x : candCover[idx]) {\n            if (!coveredCells[x]) {\n                coveredCells[x] = 1;\n                ++coveredCount;\n            }\n        }\n    };\n\n    // Use start cell as the first vantage\n    int startCandIdx = -1;\n    for (int idx = 0; idx < C; ++idx) {\n        if (candidateCells[idx] == startId) {\n            startCandIdx = idx;\n            break;\n        }\n    }\n    if (startCandIdx == -1) {\n        // Safeguard (shouldn't happen)\n        vantageCells.push_back(startId);\n        for (int x : coverageAll[startId]) {\n            if (!coveredCells[x]) {\n                coveredCells[x] = 1;\n                ++coveredCount;\n            }\n        }\n    } else {\n        selectCandidate(startCandIdx);\n    }\n\n    while (coveredCount < r) {\n        int bestIdx = -1;\n        int bestGain = -1;\n        for (int idx = 0; idx < C; ++idx) {\n            if (candSelected[idx]) continue;\n            int gain = 0;\n            for (int x : candCover[idx]) {\n                if (!coveredCells[x]) ++gain;\n            }\n            if (gain > bestGain) {\n                bestGain = gain;\n                bestIdx = idx;\n            } else if (gain == bestGain && gain > 0 && bestIdx != -1) {\n                int cellNew = candidateCells[idx];\n                int cellBest = candidateCells[bestIdx];\n                if (cost[cellNew] < cost[cellBest]) {\n                    bestIdx = idx;\n                } else if (cost[cellNew] == cost[cellBest]) {\n                    auto [ni, nj] = pos[cellNew];\n                    auto [bi, bj] = pos[cellBest];\n                    int manNew = abs(ni - si) + abs(nj - sj);\n                    int manBest = abs(bi - si) + abs(bj - sj);\n                    if (manNew < manBest) bestIdx = idx;\n                }\n            }\n        }\n\n        if (bestIdx == -1 || bestGain <= 0) {\n            // Safeguard: directly add some uncovered cell as vantage\n            int uncoveredId = -1;\n            for (int id = 0; id < r; ++id) {\n                if (!coveredCells[id]) {\n                    uncoveredId = id;\n                    break;\n                }\n            }\n            if (uncoveredId == -1) break; // should not happen\n            vantageCells.push_back(uncoveredId);\n            for (int x : coverageAll[uncoveredId]) {\n                if (!coveredCells[x]) {\n                    coveredCells[x] = 1;\n                    ++coveredCount;\n                }\n            }\n        } else {\n            selectCandidate(bestIdx);\n        }\n    }\n\n    // Deduplicate vantages (just in case)\n    sort(vantageCells.begin(), vantageCells.end());\n    vantageCells.erase(unique(vantageCells.begin(), vantageCells.end()), vantageCells.end());\n\n    // ---------- Eliminate redundant vantages using coverage frequencies (cost-biased) ----------\n    {\n        int V = (int)vantageCells.size();\n        if (V > 0) {\n            vector<int> freq(r, 0);\n\n            // Base coverage from starting cell\n            for (int c : coverageAll[startId]) freq[c]++;\n\n            // Add contributions from all vantages\n            for (int v : vantageCells) {\n                for (int c : coverageAll[v]) freq[c]++;\n            }\n\n            // Try to remove expensive vantages first\n            vector<int> orderIdx(V);\n            iota(orderIdx.begin(), orderIdx.end(), 0);\n            sort(orderIdx.begin(), orderIdx.end(), [&](int a, int b) {\n                int va = vantageCells[a], vb = vantageCells[b];\n                if (cost[va] != cost[vb]) return cost[va] > cost[vb]; // remove high-cost first\n                return coverageAll[va].size() < coverageAll[vb].size();\n            });\n\n            vector<char> removed(V, 0);\n            for (int idx : orderIdx) {\n                int v = vantageCells[idx];\n                bool canRemove = true;\n                for (int c : coverageAll[v]) {\n                    if (freq[c] <= 1) { // would leave some cell uncovered\n                        canRemove = false;\n                        break;\n                    }\n                }\n                if (!canRemove) continue;\n                removed[idx] = 1;\n                for (int c : coverageAll[v]) {\n                    --freq[c];\n                }\n            }\n\n            vector<int> reduced;\n            reduced.reserve(V);\n            for (int i = 0; i < V; ++i) {\n                if (!removed[i]) reduced.push_back(vantageCells[i]);\n            }\n            vantageCells.swap(reduced);\n        }\n    }\n\n    // ---------- Second elimination pass (coverage-size-biased) ----------\n    {\n        int V = (int)vantageCells.size();\n        if (V > 0) {\n            vector<int> freq(r, 0);\n            for (int c : coverageAll[startId]) freq[c]++;\n            for (int v : vantageCells) {\n                for (int c : coverageAll[v]) freq[c]++;\n            }\n\n            vector<int> orderIdx(V);\n            iota(orderIdx.begin(), orderIdx.end(), 0);\n            sort(orderIdx.begin(), orderIdx.end(), [&](int a, int b) {\n                int va = vantageCells[a], vb = vantageCells[b];\n                if (coverageAll[va].size() != coverageAll[vb].size())\n                    return coverageAll[va].size() < coverageAll[vb].size(); // remove small-coverage first\n                return cost[va] > cost[vb]; // then remove more expensive\n            });\n\n            vector<char> removed(V, 0);\n            for (int idx : orderIdx) {\n                int v = vantageCells[idx];\n                bool canRemove = true;\n                for (int c : coverageAll[v]) {\n                    if (freq[c] <= 1) {\n                        canRemove = false;\n                        break;\n                    }\n                }\n                if (!canRemove) continue;\n                removed[idx] = 1;\n                for (int c : coverageAll[v]) {\n                    --freq[c];\n                }\n            }\n\n            vector<int> reduced;\n            reduced.reserve(V);\n            for (int i = 0; i < V; ++i) {\n                if (!removed[i]) reduced.push_back(vantageCells[i]);\n            }\n            vantageCells.swap(reduced);\n        }\n    }\n\n    // ---------- Dijkstra helpers ----------\n    vector<int> dist(r), prevv(r);\n\n    auto dijkstraToDest = [&](int src, int dest) {\n        fill(dist.begin(), dist.end(), INF);\n        fill(prevv.begin(), prevv.end(), -1);\n        priority_queue<pair<int,int>, vector<pair<int,int>>, greater<pair<int,int>>> pq;\n        dist[src] = 0;\n        pq.push({0, src});\n        while (!pq.empty()) {\n            auto [d, u] = pq.top();\n            pq.pop();\n            if (d != dist[u]) continue;\n            if (u == dest) break;\n            for (auto &e : G[u]) {\n                int v = e.to;\n                int nd = d + e.w;\n                if (nd < dist[v]) {\n                    dist[v] = nd;\n                    prevv[v] = u;\n                    pq.push({nd, v});\n                }\n            }\n        }\n    };\n\n    auto appendPath = [&](vector<int> &route, int src, int dest) {\n        if (src == dest) return;\n        dijkstraToDest(src, dest);\n        vector<int> tmp;\n        int x = dest;\n        while (x != src && x != -1) {\n            tmp.push_back(x);\n            x = prevv[x];\n        }\n        for (int i = (int)tmp.size() - 1; i >= 0; --i) {\n            route.push_back(tmp[i]);\n        }\n    };\n\n    auto dijkstraNearestTarget = [&](int src,\n                                     const vector<char> &isTarget,\n                                     const vector<char> &visitedTarget) -> int {\n        fill(dist.begin(), dist.end(), INF);\n        fill(prevv.begin(), prevv.end(), -1);\n        priority_queue<pair<int,int>, vector<pair<int,int>>, greater<pair<int,int>>> pq;\n        dist[src] = 0;\n        pq.push({0, src});\n        int target = -1;\n        while (!pq.empty()) {\n            auto [d, u] = pq.top();\n            pq.pop();\n            if (d != dist[u]) continue;\n            if (isTarget[u] && !visitedTarget[u]) {\n                target = u;\n                break;\n            }\n            for (auto &e : G[u]) {\n                int v = e.to;\n                int nd = d + e.w;\n                if (nd < dist[v]) {\n                    dist[v] = nd;\n                    prevv[v] = u;\n                    pq.push({nd, v});\n                }\n            }\n        }\n        return target;\n    };\n\n    // ---------- Greedy NN route builder (used only when needed) ----------\n    auto buildRouteGreedyNN = [&](const vector<int> &vantages) -> vector<int> {\n        vector<int> route;\n        route.reserve(2 * r + 5);\n\n        vector<char> isTarget(r, 0), visitedTarget(r, 0);\n        for (int id : vantages) isTarget[id] = 1;\n\n        int remainingTargets = 0;\n        for (int id : vantages) {\n            if (id == startId) {\n                visitedTarget[id] = 1;\n            } else {\n                ++remainingTargets;\n            }\n        }\n\n        route.push_back(startId);\n        int curr = startId;\n\n        while (remainingTargets > 0) {\n            int target = dijkstraNearestTarget(curr, isTarget, visitedTarget);\n            if (target == -1) break; // should not happen (connected)\n\n            vector<int> tmp;\n            int x = target;\n            while (x != curr && x != -1) {\n                tmp.push_back(x);\n                x = prevv[x];\n            }\n            for (int i = (int)tmp.size() - 1; i >= 0; --i) {\n                int node = tmp[i];\n                route.push_back(node);\n                if (isTarget[node] && !visitedTarget[node]) {\n                    visitedTarget[node] = 1;\n                    --remainingTargets;\n                }\n            }\n            curr = target;\n        }\n\n        if (curr != startId) {\n            appendPath(route, curr, startId);\n        }\n        return route;\n    };\n\n    // RNG seeded from input to diversify per-instance local search\n    uint64_t seed = 88172645463393265ULL;\n    seed ^= (uint64_t)N * 10007;\n    seed ^= (uint64_t)si * 1000003;\n    seed ^= (uint64_t)sj * 1000000007ULL;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            unsigned char c = grid[i][j];\n            seed = seed * 19260817ULL + c + 1;\n        }\n    }\n    mt19937_64 rng(seed);\n\n    // ---------- Route 2: TSP over vantages ----------\n    vector<int> routeTSP;\n    long long timeTSP = (1LL << 60);\n    bool builtTSP = false;\n    bool useRealDist = false;\n\n    if (!vantageCells.empty()) {\n        // Build node list: start + all vantages (without duplicating start)\n        vector<int> nodes;\n        nodes.reserve(vantageCells.size() + 1);\n        nodes.push_back(startId);\n        for (int v : vantageCells) {\n            if (v != startId) nodes.push_back(v);\n        }\n        int K = (int)nodes.size();\n\n        if (K >= 2) {\n            const int MAX_TSP_REAL_DIST_NODES = 480;\n            useRealDist = (K <= MAX_TSP_REAL_DIST_NODES);\n\n            vector<vector<int>> distNode(K, vector<int>(K, 0));\n            vector<int> nodeIndex;\n            vector<vector<int>> parentAll;\n\n            if (useRealDist) {\n                nodeIndex.assign(r, -1);\n                for (int i = 0; i < K; ++i) nodeIndex[nodes[i]] = i;\n\n                parentAll.assign(K, vector<int>(r, -1));\n\n                // Dijkstra from each node to compute distances to all others, storing parents\n                for (int i = 0; i < K; ++i) {\n                    int src = nodes[i];\n                    auto &parent = parentAll[i];\n\n                    fill(dist.begin(), dist.end(), INF);\n                    fill(parent.begin(), parent.end(), -1);\n                    dist[src] = 0;\n                    priority_queue<pair<int,int>, vector<pair<int,int>>, greater<pair<int,int>>> pq;\n                    pq.push({0, src});\n                    int remaining = K;\n                    while (!pq.empty() && remaining > 0) {\n                        auto [d, u] = pq.top();\n                        pq.pop();\n                        if (d != dist[u]) continue;\n                        int idxU = nodeIndex[u];\n                        if (idxU != -1) {\n                            distNode[i][idxU] = d;\n                            --remaining;\n                        }\n                        for (auto &e : G[u]) {\n                            int v = e.to;\n                            int nd = d + e.w;\n                            if (nd < dist[v]) {\n                                dist[v] = nd;\n                                parent[v] = u;\n                                pq.push({nd, v});\n                            }\n                        }\n                    }\n                }\n            } else {\n                // Approximate distances by Manhattan\n                for (int i = 0; i < K; ++i) {\n                    auto [xi, yi] = pos[nodes[i]];\n                    for (int j = i + 1; j < K; ++j) {\n                        auto [xj, yj] = pos[nodes[j]];\n                        int d = abs(xi - xj) + abs(yi - yj);\n                        distNode[i][j] = distNode[j][i] = d;\n                    }\n                }\n            }\n\n            // Initial route: nearest neighbor on distNode\n            vector<int> order(K);\n            vector<char> usedNode(K, 0);\n            order[0] = 0;\n            usedNode[0] = 1;\n            for (int t = 1; t < K; ++t) {\n                int prevIdx = order[t - 1];\n                int best = -1;\n                int bestD = INT_MAX;\n                for (int j = 0; j < K; ++j) {\n                    if (usedNode[j]) continue;\n                    int d = distNode[prevIdx][j];\n                    if (d < bestD) {\n                        bestD = d;\n                        best = j;\n                    }\n                }\n                if (best == -1) best = 0; // safety\n                order[t] = best;\n                usedNode[best] = 1;\n            }\n\n            // Local search: 2-opt + Or-opt, with multi-start kicks\n            auto tourLen = [&](const vector<int> &ord) -> long long {\n                long long len = 0;\n                for (int i = 0; i < K; ++i) {\n                    int a = ord[i];\n                    int b = ord[(i + 1) % K];\n                    len += distNode[a][b];\n                }\n                return len;\n            };\n\n            auto twoOptImprove = [&](vector<int> &ord) {\n                if (K < 3) return;\n                bool improved = true;\n                while (improved) {\n                    improved = false;\n                    for (int i = 1; i < K - 1 && !improved; ++i) {\n                        int a = ord[i - 1];\n                        int b = ord[i];\n                        for (int j = i + 1; j < K; ++j) {\n                            int c = ord[j];\n                            int d = (j + 1 < K ? ord[j + 1] : ord[0]);\n                            int curCost = distNode[a][b] + distNode[c][d];\n                            int newCost = distNode[a][c] + distNode[b][d];\n                            if (newCost < curCost) {\n                                reverse(ord.begin() + i, ord.begin() + j + 1);\n                                improved = true;\n                                break;\n                            }\n                        }\n                    }\n                }\n            };\n\n            auto orOptImprove = [&](vector<int> &ord) {\n                if (K < 3) return;\n                int maxIter;\n                if (K <= 60) maxIter = 8;\n                else if (K <= 120) maxIter = 6;\n                else if (K <= 200) maxIter = 4;\n                else if (K <= 400) maxIter = 3;\n                else maxIter = 2;\n\n                for (int iter = 0; iter < maxIter; ++iter) {\n                    bool anyImproved = false;\n                    for (int i = 1; i < K; ++i) {\n                        int prev = ord[i - 1];\n                        int cur = ord[i];\n                        int next = (i == K - 1 ? ord[0] : ord[i + 1]);\n                        for (int j = 0; j < K; ++j) {\n                            if (j == i || j == i - 1) continue;\n                            int a = ord[j];\n                            int b = (j == K - 1 ? ord[0] : ord[j + 1]);\n                            if (a == cur || b == cur) continue;\n\n                            int delta = 0;\n                            // Remove cur from between prev and next\n                            delta -= distNode[prev][cur] + distNode[cur][next] - distNode[prev][next];\n                            // Insert cur between a and b\n                            delta += distNode[a][cur] + distNode[cur][b] - distNode[a][b];\n\n                            if (delta < 0) {\n                                int node = cur;\n                                if (j < i) {\n                                    for (int k = i; k < K - 1; ++k) ord[k] = ord[k + 1];\n                                    for (int k = K - 1; k > j + 1; --k) ord[k] = ord[k - 1];\n                                    ord[j + 1] = node;\n                                } else { // j > i\n                                    for (int k = i; k < K - 1; ++k) ord[k] = ord[k + 1];\n                                    int newJ = j - 1;\n                                    for (int k = K - 1; k > newJ + 1; --k) ord[k] = ord[k - 1];\n                                    ord[newJ + 1] = node;\n                                }\n                                anyImproved = true;\n                                goto NEXT_OR_ITER;\n                            }\n                        }\n                    }\n                NEXT_OR_ITER:\n                    if (!anyImproved) break;\n                }\n\n                twoOptImprove(ord);\n            };\n\n            auto localImprove = [&](vector<int> &ord) {\n                twoOptImprove(ord);\n                orOptImprove(ord);\n            };\n\n            localImprove(order);\n\n            long long bestLen = tourLen(order);\n            vector<int> bestOrder = order;\n\n            // Multi-start with random \"kicks\" (more kicks for small K where it is cheap)\n            if (K >= 4) {\n                int kicks;\n                if (K <= 40) kicks = 8;\n                else if (K <= 80) kicks = 6;\n                else if (K <= 160) kicks = 4;\n                else if (K <= 320) kicks = 3;\n                else kicks = 2;\n\n                auto randomKick = [&](vector<int> &ord) {\n                    if (K < 4) return;\n                    int a = 1 + (int)(rng() % (K - 3));\n                    int b = a + 1 + (int)(rng() % (K - 2 - a));\n                    int c = b + 1 + (int)(rng() % (K - 1 - b));\n                    vector<int> newOrd;\n                    newOrd.reserve(K);\n                    for (int i = 0; i < a; ++i) newOrd.push_back(ord[i]);      // S1\n                    for (int i = b; i < c; ++i) newOrd.push_back(ord[i]);      // S3\n                    for (int i = a; i < b; ++i) newOrd.push_back(ord[i]);      // S2\n                    for (int i = c; i < K; ++i) newOrd.push_back(ord[i]);      // S4\n                    ord.swap(newOrd);\n                };\n\n                for (int it = 0; it < kicks; ++it) {\n                    vector<int> tmp = bestOrder;\n                    randomKick(tmp);\n                    localImprove(tmp);\n                    long long len = tourLen(tmp);\n                    if (len < bestLen) {\n                        bestLen = len;\n                        bestOrder.swap(tmp);\n                    }\n                }\n                order.swap(bestOrder);\n            }\n\n            // Build actual route following this order (0..K-1), starting at startId\n            routeTSP.reserve(2 * r + 5);\n            routeTSP.push_back(startId);\n            int curr = startId;\n\n            if (useRealDist) {\n                // Use stored parents (no extra Dijkstra)\n                for (int idxPos = 1; idxPos < K; ++idxPos) {\n                    int dest = nodes[order[idxPos]];\n                    if (dest == curr) continue;\n                    int srcIdx = nodeIndex[curr];\n                    auto &parent = parentAll[srcIdx];\n                    vector<int> tmp;\n                    int v = dest;\n                    while (v != curr && v != -1) {\n                        tmp.push_back(v);\n                        v = parent[v];\n                    }\n                    for (int i = (int)tmp.size() - 1; i >= 0; --i) {\n                        routeTSP.push_back(tmp[i]);\n                    }\n                    curr = dest;\n                }\n                if (curr != startId) {\n                    int srcIdx = nodeIndex[curr];\n                    auto &parent = parentAll[srcIdx];\n                    vector<int> tmp;\n                    int v = startId;\n                    while (v != curr && v != -1) {\n                        tmp.push_back(v);\n                        v = parent[v];\n                    }\n                    for (int i = (int)tmp.size() - 1; i >= 0; --i) {\n                        routeTSP.push_back(tmp[i]);\n                    }\n                }\n            } else {\n                // Manhattan-based TSP: still need Dijkstra to realize actual paths\n                for (int idxPos = 1; idxPos < K; ++idxPos) {\n                    int dest = nodes[order[idxPos]];\n                    if (dest == curr) continue;\n                    appendPath(routeTSP, curr, dest);\n                    curr = dest;\n                }\n                if (curr != startId) {\n                    appendPath(routeTSP, curr, startId);\n                }\n            }\n\n            timeTSP = computeTravelTime(routeTSP, cost);\n            builtTSP = true;\n        }\n    }\n\n    // ---------- Route 1: Greedy nearest neighbor (only when needed) ----------\n    vector<int> routeNN;\n    long long timeNN = (1LL << 60);\n\n    bool needNN = true;\n    if (builtTSP && useRealDist) needNN = false;\n\n    if (needNN) {\n        routeNN = buildRouteGreedyNN(vantageCells);\n        if (!routeNN.empty()) timeNN = computeTravelTime(routeNN, cost);\n    }\n\n    // ---------- Choose the best route ----------\n    vector<int> bestRoute;\n    long long bestTime = (1LL << 60);\n\n    if (!routeNN.empty()) {\n        bestTime = timeNN;\n        bestRoute = std::move(routeNN);\n    }\n    if (builtTSP && !routeTSP.empty() && timeTSP < bestTime) {\n        bestTime = timeTSP;\n        bestRoute = std::move(routeTSP);\n    }\n\n    // As a last resort (should not happen), if nothing was built, stay at start\n    if (bestRoute.empty()) {\n        bestRoute.push_back(startId);\n    }\n\n    // If route has no movement, add a tiny loop to avoid t=0\n    if ((int)bestRoute.size() == 1) {\n        int u = startId;\n        int v = -1;\n        for (auto &e : G[u]) {\n            v = e.to;\n            break;\n        }\n        if (v != -1) {\n            bestRoute.push_back(v);\n            bestRoute.push_back(u);\n        }\n    }\n\n    // ---------- Convert node sequence to direction string ----------\n    string ans;\n    ans.reserve(bestRoute.size());\n    for (int i = 1; i < (int)bestRoute.size(); ++i) {\n        auto [i1, j1] = pos[bestRoute[i-1]];\n        auto [i2, j2] = pos[bestRoute[i]];\n        if (i2 == i1 - 1 && j2 == j1) ans.push_back('U');\n        else if (i2 == i1 + 1 && j2 == j1) ans.push_back('D');\n        else if (j2 == j1 - 1 && i2 == i1) ans.push_back('L');\n        else if (j2 == j1 + 1 && i2 == i1) ans.push_back('R');\n        else {\n            // Should not happen with valid shortest paths\n        }\n    }\n\n    cout << ans << '\\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    if (!(cin >> N >> M >> K >> R)) return 0;\n\n    // Task requirements d[i][k]\n    vector<vector<int>> d(N, vector<int>(K));\n    for (int i = 0; i < N; ++i) {\n        for (int k = 0; k < K; ++k) cin >> d[i][k];\n    }\n\n    // Dependencies: u -> v\n    vector<vector<int>> out(N);\n    vector<int> indeg(N, 0);\n    for (int e = 0; e < R; ++e) {\n        int u, v;\n        cin >> u >> v;\n        --u; --v;\n        out[u].push_back(v);\n        indeg[v]++;\n    }\n\n    // Precompute depth-from-end (longest path length to any sink)\n    vector<int> depth(N, 0);\n    for (int i = N - 1; i >= 0; --i) {\n        int best = 0;\n        for (int v : out[i]) {\n            best = max(best, depth[v] + 1);\n        }\n        depth[i] = best;\n    }\n\n    // Precompute simple difficulty measure (L1 norm)\n    vector<int> diffL1(N, 0);\n    for (int i = 0; i < N; ++i) {\n        int s = 0;\n        for (int k = 0; k < K; ++k) s += d[i][k];\n        diffL1[i] = s;\n    }\n\n    // Task states\n    const int NOT_STARTED = 0;\n    const int IN_PROGRESS = 1;\n    const int DONE = 2;\n    vector<int> state(N, NOT_STARTED);\n    vector<int> degRem = indeg;\n    int tasksDone = 0;\n\n    // Worker states\n    vector<int> curTask(M, -1);\n    vector<int> startDay(M, -1);\n\n    // Worker skill vectors s_j[k]\n    vector<vector<double>> skill(M, vector<double>(K, 0.0));\n    // History of (task, w_obs) per worker for fitting\n    vector<vector<int>> histTasks(M);\n    vector<vector<double>> histW(M);\n\n    const int    FIT_ITERS = 5;\n    const double LR        = 0.05;\n    const double SKILL_MAX = 100.0;\n\n    // Fitting function for one worker (small batch GD over its history)\n    auto fitWorker = [&](int j) {\n        auto &s  = skill[j];\n        auto &ht = histTasks[j];\n        auto &hw = histW[j];\n        int S = (int)ht.size();\n        if (S == 0) return;\n        for (int it = 0; it < FIT_ITERS; ++it) {\n            for (int idx = 0; idx < S; ++idx) {\n                int ti = ht[idx];\n                double w_obs = hw[idx];\n\n                // Compute w_pred = sum_k max(0, d[ti][k] - s[k])\n                const auto &dv = d[ti];\n                double w_pred = 0.0;\n                for (int k = 0; k < K; ++k) {\n                    double diff = (double)dv[k] - s[k];\n                    if (diff > 0.0) w_pred += diff;\n                }\n\n                double e = w_pred - w_obs;\n                if (e == 0.0) continue;\n                double step = LR * e;\n\n                // Gradient: for dims where d > s, s[k] += step\n                for (int k = 0; k < K; ++k) {\n                    if ((double)dv[k] > s[k]) {\n                        s[k] += step;\n                        if (s[k] < 0.0) s[k] = 0.0;\n                        if (s[k] > SKILL_MAX) s[k] = SKILL_MAX;\n                    }\n                }\n            }\n        }\n    };\n\n    int day = 0;\n    const int MAX_CAND = 400;  // number of candidate tasks per day to consider\n\n    while (true) {\n        day++;\n\n        // Compute available tasks (not started and all prerequisites done)\n        vector<int> available;\n        if (tasksDone < N) {\n            available.reserve(N);\n            for (int i = 0; i < N; ++i) {\n                if (state[i] == NOT_STARTED && degRem[i] == 0) {\n                    available.push_back(i);\n                }\n            }\n        }\n\n        // Collect free workers\n        vector<int> freeWorkers;\n        freeWorkers.reserve(M);\n        for (int j = 0; j < M; ++j) {\n            if (curTask[j] == -1) freeWorkers.push_back(j);\n        }\n\n        vector<pair<int,int>> assigns; // (worker, task)\n\n        if (!freeWorkers.empty() && !available.empty()) {\n            // Sort available tasks by priority: depth desc, diffL1 desc, id asc\n            auto cmpTask = [&](int x, int y) {\n                if (depth[x] != depth[y]) return depth[x] > depth[y];\n                if (diffL1[x] != diffL1[y]) return diffL1[x] > diffL1[y];\n                return x < y;\n            };\n\n            int sz = (int)available.size();\n            if (sz > MAX_CAND) {\n                int limit = MAX_CAND;\n                partial_sort(available.begin(), available.begin() + limit,\n                             available.end(), cmpTask);\n                available.resize(limit);\n                sz = limit;\n            } else {\n                sort(available.begin(), available.end(), cmpTask);\n            }\n\n            // Build all (worker, task) options with predicted cost = t_pred\n            struct Option {\n                double cost;\n                int w;\n                int task;\n            };\n            vector<Option> options;\n            options.reserve(freeWorkers.size() * sz);\n\n            for (int widx = 0; widx < (int)freeWorkers.size(); ++widx) {\n                int j = freeWorkers[widx];\n                const auto &sj = skill[j];\n                for (int tidx = 0; tidx < sz; ++tidx) {\n                    int ti = available[tidx];\n                    const auto &dv = d[ti];\n                    double w_pred = 0.0;\n                    for (int k = 0; k < K; ++k) {\n                        double diff = (double)dv[k] - sj[k];\n                        if (diff > 0.0) w_pred += diff;\n                    }\n                    if (w_pred < 0.0) w_pred = 0.0;\n                    double t_pred = (w_pred < 1.0 ? 1.0 : w_pred);\n                    options.push_back(Option{t_pred, j, ti});\n                }\n            }\n\n            sort(options.begin(), options.end(),\n                 [](const Option &a, const Option &b) {\n                     if (a.cost != b.cost) return a.cost < b.cost;\n                     if (a.w != b.w) return a.w < b.w;\n                     return a.task < b.task;\n                 });\n\n            vector<char> workerUsed(M, 0);\n            vector<char> taskUsed(N, 0);\n            assigns.reserve(freeWorkers.size());\n\n            for (const auto &opt : options) {\n                if ((int)assigns.size() == (int)freeWorkers.size()) break;\n                int j  = opt.w;\n                int ti = opt.task;\n                if (workerUsed[j] || taskUsed[ti]) continue;\n                workerUsed[j] = 1;\n                taskUsed[ti]  = 1;\n                assigns.emplace_back(j, ti);\n            }\n        }\n\n        // Output assignments and update worker/task states\n        int m = (int)assigns.size();\n        cout << m;\n        for (auto &p : assigns) {\n            int j  = p.first;\n            int ti = p.second;\n            cout << ' ' << (j + 1) << ' ' << (ti + 1);\n            curTask[j] = ti;\n            startDay[j] = day;\n            state[ti] = IN_PROGRESS;\n        }\n        cout << '\\n' << flush;\n\n        // Read feedback: list of finished workers\n        int n;\n        if (!(cin >> n)) return 0;\n        if (n == -1) break;\n\n        vector<int> finishedWorkers;\n        finishedWorkers.reserve(n);\n        for (int i = 0; i < n; ++i) {\n            int f;\n            cin >> f;\n            finishedWorkers.push_back(f - 1); // zero-based\n        }\n\n        // Process completions\n        for (int idx = 0; idx < n; ++idx) {\n            int j = finishedWorkers[idx];\n            int ti = (j >= 0 && j < M) ? curTask[j] : -1;\n            if (ti < 0) continue;\n\n            int st = startDay[j];\n            if (st < 1) st = day;  // safety\n            int t_obs = day - st + 1;\n            if (t_obs < 1) t_obs = 1;\n            int w_obs_int = t_obs - 1;\n            if (w_obs_int < 0) w_obs_int = 0;\n            double w_obs = (double)w_obs_int;\n\n            // Record sample for worker j\n            histTasks[j].push_back(ti);\n            histW[j].push_back(w_obs);\n            // Re-fit worker j's skill vector\n            fitWorker(j);\n\n            // Mark task completion\n            state[ti] = DONE;\n            tasksDone++;\n            curTask[j] = -1;\n            startDay[j] = -1;\n\n            // Update indegrees of children\n            for (int v : out[ti]) {\n                degRem[v]--;\n            }\n        }\n    }\n\n    return 0;\n}","ahc006":"#include <bits/stdc++.h>\nusing namespace std;\n\n// ---------------------------------------------------------------\n// Types and globals\n// ---------------------------------------------------------------\n\nstruct TourResult {\n    vector<int> tour; // sequence of node indices, starts and ends with 0 (office)\n    int cost;\n};\n\nstatic int distMat[52][52];   // for TSP up to 51 nodes (0..50)\nstatic int nodeX[52], nodeY[52];\n\nconst int OFFICE_X = 400;\nconst int OFFICE_Y = 400;\n\n// RNG: simple xorshift\nstruct XorShift {\n    uint64_t x;\n    XorShift(uint64_t seed = 88172645463393265ULL) { x = seed; }\n    uint64_t next_u64() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return x;\n    }\n    uint32_t next_u32() { return (uint32_t)next_u64(); }\n    uint32_t next_uint(uint32_t mod) { return (uint32_t)(next_u64() % mod); }\n    double next_double() {\n        return (next_u64() >> 11) * (1.0 / (1ULL << 53));\n    }\n};\n\n// Manhattan distance\ninline int manhattan(int x1, int y1, int x2, int y2) {\n    return abs(x1 - x2) + abs(y1 - y2);\n}\n\n// ---------------------------------------------------------------\n// TSP solver: nearest neighbor + 2-opt\n// Points: X[i], Y[i] for i=0..m-1 correspond to nodes 1..m.\n// Node 0 is the office at (400,400).\n// ---------------------------------------------------------------\nTourResult solve_tsp_points(const vector<int>& X, const vector<int>& Y) {\n    int m = (int)X.size();       // number of non-office nodes (<=50)\n    int nNodes = m + 1;          // nodes 0..m\n\n    // Build node coordinates (0: office)\n    nodeX[0] = OFFICE_X;\n    nodeY[0] = OFFICE_Y;\n    for (int i = 1; i <= m; ++i) {\n        nodeX[i] = X[i - 1];\n        nodeY[i] = Y[i - 1];\n    }\n\n    // Distance matrix\n    for (int i = 0; i <= m; ++i) {\n        for (int j = 0; j <= m; ++j) {\n            distMat[i][j] = manhattan(nodeX[i], nodeY[i], nodeX[j], nodeY[j]);\n        }\n    }\n\n    // Nearest neighbor construction, start at office (0)\n    vector<int> tour;\n    tour.reserve(nNodes + 1);\n    vector<char> used(nNodes, 0);\n    int cur = 0;\n    used[0] = 1;\n    tour.push_back(0);\n    for (int step = 0; step < m; ++step) {\n        int best = -1;\n        int bestDist = INT_MAX;\n        for (int v = 1; v <= m; ++v) {\n            if (!used[v]) {\n                int d = distMat[cur][v];\n                if (d < bestDist) {\n                    bestDist = d;\n                    best = v;\n                }\n            }\n        }\n        used[best] = 1;\n        tour.push_back(best);\n        cur = best;\n    }\n    tour.push_back(0); // return to office\n\n    // 2-opt improvement with fixed endpoints at office\n    int M = (int)tour.size(); // should be m+2\n    bool improved = true;\n    while (improved) {\n        improved = false;\n        for (int i = 1; i <= M - 3; ++i) {\n            int a = tour[i - 1];\n            int b = tour[i];\n            for (int k = i + 1; k <= M - 2; ++k) {\n                int c = tour[k];\n                int d = tour[k + 1];\n                int delta = distMat[a][c] + distMat[b][d]\n                          - distMat[a][b] - distMat[c][d];\n                if (delta < 0) {\n                    reverse(tour.begin() + i, tour.begin() + k + 1);\n                    improved = true;\n                    goto next_iteration;\n                }\n            }\n        }\n        next_iteration:;\n    }\n\n    int cost = 0;\n    for (int i = 0; i < M - 1; ++i) {\n        cost += distMat[tour[i]][tour[i + 1]];\n    }\n\n    TourResult res;\n    res.tour = move(tour);\n    res.cost = cost;\n    return res;\n}\n\n// ---------------------------------------------------------------\n// Evaluate a selection of orders:\n//   selection: vector of indices (0-based) of orders.\n//   Returns total cost of 0->restaurants->0 + 0->destinations->0,\n//   and stores the restaurant and destination tours.\n// ---------------------------------------------------------------\nint evaluate_selection(\n    const vector<int>& selection,\n    const vector<int>& a, const vector<int>& b,\n    const vector<int>& c, const vector<int>& d,\n    vector<int>& outRtour,\n    vector<int>& outDtour\n) {\n    int m = (int)selection.size(); // 50\n    vector<int> XR(m), YR(m), XD(m), YD(m);\n    for (int i = 0; i < m; ++i) {\n        int idx = selection[i];\n        XR[i] = a[idx];\n        YR[i] = b[idx];\n        XD[i] = c[idx];\n        YD[i] = d[idx];\n    }\n\n    TourResult rRes = solve_tsp_points(XR, YR);\n    TourResult dRes = solve_tsp_points(XD, YD);\n\n    outRtour = rRes.tour;\n    outDtour = dRes.tour;\n\n    return rRes.cost + dRes.cost;\n}\n\n// ---------------------------------------------------------------\n// Compute cost of a pickup-delivery route:\n// kind[pos]: 0=pickup, 1=delivery, 2=office (for pos=0 and last)\n// oid[pos]: local order id (0..M-1) if kind is 0 or 1\n// ---------------------------------------------------------------\nint compute_route_cost(\n    int M,\n    const vector<int>& kind,\n    const vector<int>& oid,\n    const vector<int>& rx,\n    const vector<int>& ry,\n    const vector<int>& dx,\n    const vector<int>& dy\n) {\n    int routeSize = 2 * M + 2; // positions 0..routeSize-1\n    auto getCoord = [&](int pos, int &x, int &y) {\n        if (pos == 0 || pos == routeSize - 1) {\n            x = OFFICE_X; y = OFFICE_Y;\n        } else if (kind[pos] == 0) { // pickup -> restaurant\n            int id = oid[pos];\n            x = rx[id]; y = ry[id];\n        } else { // delivery\n            int id = oid[pos];\n            x = dx[id]; y = dy[id];\n        }\n    };\n\n    int total = 0;\n    int px, py;\n    getCoord(0, px, py);\n    for (int pos = 1; pos < routeSize; ++pos) {\n        int cx, cy;\n        getCoord(pos, cx, cy);\n        total += manhattan(px, py, cx, cy);\n        px = cx; py = cy;\n    }\n    return total;\n}\n\n// ---------------------------------------------------------------\n// Main\n// ---------------------------------------------------------------\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    const int N = 1000;\n    vector<int> a(N), b(N), c(N), d(N);\n    for (int i = 0; i < N; ++i) {\n        if (!(cin >> a[i] >> b[i] >> c[i] >> d[i])) {\n            return 0;\n        }\n    }\n\n    auto globalStart = chrono::steady_clock::now();\n    const double TOTAL_LIMIT = 1.95;      // total time limit for safety\n    const double SELECTION_LIMIT = 1.75;  // selection phase time\n\n    XorShift rng(\n        (uint64_t)chrono::high_resolution_clock::now()\n            .time_since_epoch().count()\n    );\n\n    // -----------------------------------------------------------\n    // Initial selection by single-trip heuristic\n    // -----------------------------------------------------------\n    vector<int> single_trip(N);\n    for (int i = 0; i < N; ++i) {\n        int d0R = manhattan(OFFICE_X, OFFICE_Y, a[i], b[i]);\n        int dRD = manhattan(a[i], b[i], c[i], d[i]);\n        int dD0 = manhattan(c[i], d[i], OFFICE_X, OFFICE_Y);\n        single_trip[i] = d0R + dRD + dD0;\n    }\n\n    vector<int> idx(N);\n    iota(idx.begin(), idx.end(), 0);\n    sort(idx.begin(), idx.end(), [&](int i, int j) {\n        return single_trip[i] < single_trip[j];\n    });\n\n    const int M = 50;\n\n    // Candidate pool: only consider best POOL orders by single_trip\n    const int POOL = 400;\n    vector<int> pool(min(POOL, N));\n    for (int i = 0; i < (int)pool.size(); ++i) {\n        pool[i] = idx[i];\n    }\n\n    // Initial selection: best 50 by single_trip (subset of pool)\n    vector<int> currentSel(M);\n    for (int i = 0; i < M; ++i) currentSel[i] = idx[i];\n\n    vector<char> inCurrent(N, 0);\n    for (int i = 0; i < M; ++i) inCurrent[currentSel[i]] = 1;\n\n    // Evaluate initial selection\n    vector<int> bestRtour, bestDtour;\n    vector<int> tmpRtour, tmpDtour;\n    int currentCost = evaluate_selection(currentSel, a, b, c, d, tmpRtour, tmpDtour);\n\n    vector<int> bestSel = currentSel;\n    bestRtour = tmpRtour;\n    bestDtour = tmpDtour;\n    int bestCost = currentCost;\n\n    // -----------------------------------------------------------\n    // Selection phase: greedy hill-climbing on the set of 50 orders\n    // Only swap with orders from 'pool' to avoid obviously bad ones.\n    // -----------------------------------------------------------\n    int poolSize = (int)pool.size();\n    while (true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - globalStart).count();\n        if (elapsed > SELECTION_LIMIT) break;\n\n        // Pick a random order to remove\n        int posOut = (int)rng.next_uint(M);\n        int outIdx = currentSel[posOut];\n\n        // Pick a random order to insert (not currently selected), from pool\n        int inIdx;\n        do {\n            int pid = (int)rng.next_uint(poolSize);\n            inIdx = pool[pid];\n        } while (inCurrent[inIdx]);\n\n        vector<int> candidateSel = currentSel;\n        candidateSel[posOut] = inIdx;\n\n        int candCost = evaluate_selection(candidateSel, a, b, c, d, tmpRtour, tmpDtour);\n\n        // Greedy acceptance\n        if (candCost <= currentCost) {\n            currentSel.swap(candidateSel);\n            currentCost = candCost;\n            inCurrent[outIdx] = 0;\n            inCurrent[inIdx] = 1;\n        }\n\n        // Track global best\n        if (candCost < bestCost) {\n            bestCost = candCost;\n            bestSel = candidateSel;\n            bestRtour = tmpRtour;\n            bestDtour = tmpDtour;\n        }\n    }\n\n    // -----------------------------------------------------------\n    // Build local data for best selection\n    // -----------------------------------------------------------\n    vector<int> globalOfLocal(M);\n    for (int i = 0; i < M; ++i) {\n        globalOfLocal[i] = bestSel[i]; // map local id -> global order index\n    }\n\n    vector<int> rx(M), ry(M), dx(M), dy(M);\n    for (int i = 0; i < M; ++i) {\n        int gi = globalOfLocal[i];\n        rx[i] = a[gi];\n        ry[i] = b[gi];\n        dx[i] = c[gi];\n        dy[i] = d[gi];\n    }\n\n    // Extract sequences of local order ids from TSP tours\n    vector<int> seqP; seqP.reserve(M);\n    vector<int> seqD; seqD.reserve(M);\n\n    // Restaurants tour: [0, r1, ..., rM, 0]\n    for (int i = 1; i < (int)bestRtour.size() - 1; ++i) {\n        int node = bestRtour[i]; // 1..M\n        int local = node - 1;\n        seqP.push_back(local);\n    }\n    // Destinations tour: [0, d1, ..., dM, 0]\n    for (int i = 1; i < (int)bestDtour.size() - 1; ++i) {\n        int node = bestDtour[i];\n        int local = node - 1;\n        seqD.push_back(local);\n    }\n\n    if ((int)seqP.size() != M || (int)seqD.size() != M) {\n        // Fallback: trivial order 0..M-1 (should not normally happen)\n        seqP.clear(); seqD.clear();\n        for (int i = 0; i < M; ++i) {\n            seqP.push_back(i);\n            seqD.push_back(i);\n        }\n    }\n\n    // -----------------------------------------------------------\n    // Build baseline pickup-delivery route: 0, P..., D..., 0\n    // -----------------------------------------------------------\n    int routeSize = 2 * M + 2; // positions 0..routeSize-1\n    vector<int> kind(routeSize), oid(routeSize); // kind: 0=pickup,1=delivery,2=office\n    vector<int> posP(M), posD(M);\n\n    kind[0] = kind[routeSize - 1] = 2;\n    oid[0] = oid[routeSize - 1] = -1;\n\n    // pickups\n    for (int k = 0; k < M; ++k) {\n        int pos = 1 + k;\n        int local = seqP[k];\n        kind[pos] = 0;\n        oid[pos] = local;\n        posP[local] = pos;\n    }\n    // deliveries\n    for (int k = 0; k < M; ++k) {\n        int pos = 1 + M + k;\n        int local = seqD[k];\n        kind[pos] = 1;\n        oid[pos] = local;\n        posD[local] = pos;\n    }\n\n    // Baseline route cost: 0 -> all pickups -> all deliveries -> 0\n    int baselineCost = compute_route_cost(M, kind, oid, rx, ry, dx, dy);\n    vector<int> baselineKind = kind;\n    vector<int> baselineOid = oid;\n\n    // -----------------------------------------------------------\n    // Simulated Annealing on pickup-delivery sequence\n    // -----------------------------------------------------------\n    int currentRouteCost = baselineCost;\n    int bestRouteCost = baselineCost;\n    vector<int> bestKind = kind;\n    vector<int> bestOid = oid;\n\n    auto saStart = chrono::steady_clock::now();\n    double elapsed = chrono::duration<double>(saStart - globalStart).count();\n    double remaining = TOTAL_LIMIT - elapsed;\n\n    if (remaining > 0.05) {\n        const int MAX_ITER = 400000;\n        const int CHECK_INTERVAL = 2048;\n        const double T0 = 2000.0;\n        const double T1 = 2.0;\n        const double PAIR_MOVE_PROB = 0.15; // probability of trying pair swap\n\n        for (int it = 0; it < MAX_ITER; ++it) {\n            if ((it & (CHECK_INTERVAL - 1)) == 0) {\n                auto now = chrono::steady_clock::now();\n                double e = chrono::duration<double>(now - globalStart).count();\n                if (e > TOTAL_LIMIT) break;\n            }\n\n            double frac = (double)it / MAX_ITER;\n            if (frac > 1.0) frac = 1.0;\n            double T = T0 + (T1 - T0) * frac;\n\n            double rmove = rng.next_double();\n\n            // ---------------------------------------------------\n            // Branch 1: pair swap (swap two orders' pickups & deliveries)\n            // ---------------------------------------------------\n            if (rmove < PAIR_MOVE_PROB) {\n                int id1 = (int)rng.next_uint(M);\n                int id2 = (int)rng.next_uint(M);\n                if (id1 == id2) continue;\n\n                int p1 = posP[id1];\n                int d1 = posD[id1];\n                int p2 = posP[id2];\n                int d2 = posD[id2];\n\n                // Swap pickups and deliveries (kind remains same)\n                swap(oid[p1], oid[p2]);\n                swap(oid[d1], oid[d2]);\n\n                int newCost = compute_route_cost(M, kind, oid, rx, ry, dx, dy);\n                int deltaCost = newCost - currentRouteCost;\n\n                bool accept = false;\n                if (deltaCost <= 0) {\n                    accept = true;\n                } else {\n                    double prob = exp(-(double)deltaCost / T);\n                    if (rng.next_double() < prob) accept = true;\n                }\n\n                if (accept) {\n                    currentRouteCost = newCost;\n                    // Recompute posP, posD fully (cheap: 2*M positions)\n                    for (int pos = 1; pos <= 2 * M; ++pos) {\n                        if (kind[pos] == 0) posP[oid[pos]] = pos;\n                        else if (kind[pos] == 1) posD[oid[pos]] = pos;\n                    }\n                    if (currentRouteCost < bestRouteCost) {\n                        bestRouteCost = currentRouteCost;\n                        bestKind = kind;\n                        bestOid = oid;\n                    }\n                } else {\n                    // revert\n                    swap(oid[p1], oid[p2]);\n                    swap(oid[d1], oid[d2]);\n                }\n\n                continue;\n            }\n\n            // ---------------------------------------------------\n            // Branch 2: single-event swap (existing local delta move)\n            // ---------------------------------------------------\n            int x = 1 + (int)rng.next_uint(2 * M); // 1..2M\n            int y = 1 + (int)rng.next_uint(2 * M);\n            if (x == y) continue;\n            if (x > y) swap(x, y);\n\n            int kx = kind[x];\n            int ky = kind[y];\n            int oid1 = oid[x];\n            int oid2 = oid[y];\n\n            // never touch offices\n            if (kx == 2 || ky == 2) continue;\n\n            // don't swap pickup and delivery of the same order\n            if (oid1 == oid2) continue;\n\n            // Precedence check\n            bool ok = true;\n            // Order 1\n            int p1 = posP[oid1];\n            int d1 = posD[oid1];\n            if (kx == 0) { // pickup moves to y\n                if (y >= d1) ok = false;\n            } else { // delivery moves to y\n                if (p1 >= y) ok = false;\n            }\n            if (!ok) continue;\n\n            // Order 2\n            int p2 = posP[oid2];\n            int d2 = posD[oid2];\n            if (ky == 0) { // pickup moves to x\n                if (x >= d2) ok = false;\n            } else { // delivery moves to x\n                if (p2 >= x) ok = false;\n            }\n            if (!ok) continue;\n\n            // Helper to get coordinates at a given position (before swap)\n            auto getCoordPos = [&](int pos, int &X, int &Y) {\n                if (pos == 0 || pos == routeSize - 1) {\n                    X = OFFICE_X; Y = OFFICE_Y;\n                } else if (kind[pos] == 0) {\n                    int id = oid[pos];\n                    X = rx[id]; Y = ry[id];\n                } else { // delivery\n                    int id = oid[pos];\n                    X = dx[id]; Y = dy[id];\n                }\n            };\n\n            int deltaCost = 0;\n            if (y == x + 1) {\n                // Adjacent swap: positions x and y=x+1\n                int Ax, Ay, Bx, By, Cx, Cy, Dx_, Dy_;\n                int xPrev = x - 1;\n                int yNext = y + 1;\n\n                getCoordPos(xPrev, Ax, Ay);\n                getCoordPos(x, Bx, By);   // event1\n                getCoordPos(y, Cx, Cy);   // event2\n                getCoordPos(yNext, Dx_, Dy_);\n\n                int before = manhattan(Ax, Ay, Bx, By)\n                           + manhattan(Bx, By, Cx, Cy)\n                           + manhattan(Cx, Cy, Dx_, Dy_);\n\n                int B2x, B2y, C2x, C2y;\n                // New B (at x) is event2\n                if (ky == 0) {\n                    int id = oid2;\n                    B2x = rx[id]; B2y = ry[id];\n                } else {\n                    int id = oid2;\n                    B2x = dx[id]; B2y = dy[id];\n                }\n                // New C (at y) is event1\n                if (kx == 0) {\n                    int id = oid1;\n                    C2x = rx[id]; C2y = ry[id];\n                } else {\n                    int id = oid1;\n                    C2x = dx[id]; C2y = dy[id];\n                }\n\n                int after = manhattan(Ax, Ay, B2x, B2y)\n                          + manhattan(B2x, B2y, C2x, C2y)\n                          + manhattan(C2x, C2y, Dx_, Dy_);\n\n                deltaCost = after - before;\n            } else {\n                // Non-adjacent swap\n                int xPrev = x - 1;\n                int xNext = x + 1;\n                int yPrev = y - 1;\n                int yNext = y + 1;\n\n                int Ax, Ay, Bx, By, Cx, Cy;\n                int Dx_, Dy_, Ex, Ey, Fx, Fy;\n\n                getCoordPos(xPrev, Ax, Ay);\n                getCoordPos(x, Bx, By);\n                getCoordPos(xNext, Cx, Cy);\n\n                getCoordPos(yPrev, Dx_, Dy_);\n                getCoordPos(y, Ex, Ey);\n                getCoordPos(yNext, Fx, Fy);\n\n                int before = manhattan(Ax, Ay, Bx, By)\n                           + manhattan(Bx, By, Cx, Cy)\n                           + manhattan(Dx_, Dy_, Ex, Ey)\n                           + manhattan(Ex, Ey, Fx, Fy);\n\n                int B2x, B2y, E2x, E2y;\n                // New node at x (B2) is event2\n                if (ky == 0) {\n                    int id = oid2;\n                    B2x = rx[id]; B2y = ry[id];\n                } else {\n                    int id = oid2;\n                    B2x = dx[id]; B2y = dy[id];\n                }\n                // New node at y (E2) is event1\n                if (kx == 0) {\n                    int id = oid1;\n                    E2x = rx[id]; E2y = ry[id];\n                } else {\n                    int id = oid1;\n                    E2x = dx[id]; E2y = dy[id];\n                }\n\n                int after = manhattan(Ax, Ay, B2x, B2y)\n                          + manhattan(B2x, B2y, Cx, Cy)\n                          + manhattan(Dx_, Dy_, E2x, E2y)\n                          + manhattan(E2x, E2y, Fx, Fy);\n\n                deltaCost = after - before;\n            }\n\n            bool accept = false;\n            if (deltaCost <= 0) {\n                accept = true;\n            } else {\n                double prob = exp(- (double)deltaCost / T);\n                if (rng.next_double() < prob) accept = true;\n            }\n\n            if (!accept) continue;\n\n            // Accept move\n            currentRouteCost += deltaCost;\n\n            // Update positions and route\n            swap(kind[x], kind[y]);\n            swap(oid[x], oid[y]);\n\n            // Update posP/posD for affected orders using old kinds (kx, ky)\n            if (kx == 0) posP[oid1] = y; else posD[oid1] = y;\n            if (ky == 0) posP[oid2] = x; else posD[oid2] = x;\n\n            if (currentRouteCost < bestRouteCost) {\n                bestRouteCost = currentRouteCost;\n                bestKind = kind;\n                bestOid = oid;\n            }\n        }\n    }\n\n    // Recompute exact costs and choose the better of baseline vs SA\n    int saCost = compute_route_cost(M, bestKind, bestOid, rx, ry, dx, dy);\n    vector<int> finalKind, finalOid;\n    int finalCost;\n    if (saCost < baselineCost) {\n        finalKind = bestKind;\n        finalOid = bestOid;\n        finalCost = saCost;\n    } else {\n        finalKind = baselineKind;\n        finalOid = baselineOid;\n        finalCost = baselineCost;\n    }\n\n    // -----------------------------------------------------------\n    // Final greedy local improvement on the route (only improving swaps)\n    // -----------------------------------------------------------\n    {\n        // Recompute posP and posD for final route\n        vector<int> posP2(M), posD2(M);\n        for (int pos = 1; pos <= 2 * M; ++pos) {\n            if (finalKind[pos] == 0) {\n                posP2[finalOid[pos]] = pos;\n            } else if (finalKind[pos] == 1) {\n                posD2[finalOid[pos]] = pos;\n            }\n        }\n\n        int routeCost = finalCost;\n        bool improved = true;\n        while (improved) {\n            improved = false;\n            for (int x = 1; x <= 2 * M; ++x) {\n                auto now = chrono::steady_clock::now();\n                double e = chrono::duration<double>(now - globalStart).count();\n                if (e > TOTAL_LIMIT) goto end_greedy_improve;\n\n                for (int y = x + 1; y <= 2 * M; ++y) {\n                    int kx = finalKind[x];\n                    int ky = finalKind[y];\n                    int oid1 = finalOid[x];\n                    int oid2 = finalOid[y];\n\n                    // skip offices\n                    if (kx == 2 || ky == 2) continue;\n                    // same order\n                    if (oid1 == oid2) continue;\n\n                    // precedence check\n                    bool ok = true;\n                    // order 1\n                    int p1 = posP2[oid1];\n                    int d1 = posD2[oid1];\n                    if (kx == 0) { // pickup moves to y\n                        if (y >= d1) ok = false;\n                    } else { // delivery moves to y\n                        if (p1 >= y) ok = false;\n                    }\n                    if (!ok) continue;\n                    // order 2\n                    int p2 = posP2[oid2];\n                    int d2 = posD2[oid2];\n                    if (ky == 0) { // pickup moves to x\n                        if (x >= d2) ok = false;\n                    } else { // delivery moves to x\n                        if (p2 >= x) ok = false;\n                    }\n                    if (!ok) continue;\n\n                    // delta cost\n                    auto getCoordPosFinal = [&](int pos, int &X, int &Y) {\n                        if (pos == 0 || pos == routeSize - 1) {\n                            X = OFFICE_X; Y = OFFICE_Y;\n                        } else if (finalKind[pos] == 0) {\n                            int id = finalOid[pos];\n                            X = rx[id]; Y = ry[id];\n                        } else {\n                            int id = finalOid[pos];\n                            X = dx[id]; Y = dy[id];\n                        }\n                    };\n\n                    int deltaCost = 0;\n                    if (y == x + 1) {\n                        int Ax, Ay, Bx, By, Cx, Cy, Dx_, Dy_;\n                        int xPrev = x - 1;\n                        int yNext = y + 1;\n\n                        getCoordPosFinal(xPrev, Ax, Ay);\n                        getCoordPosFinal(x, Bx, By);\n                        getCoordPosFinal(y, Cx, Cy);\n                        getCoordPosFinal(yNext, Dx_, Dy_);\n\n                        int before = manhattan(Ax, Ay, Bx, By)\n                                   + manhattan(Bx, By, Cx, Cy)\n                                   + manhattan(Cx, Cy, Dx_, Dy_);\n\n                        int B2x, B2y, C2x, C2y;\n                        // new B at x is event2\n                        if (ky == 0) {\n                            int id = oid2;\n                            B2x = rx[id]; B2y = ry[id];\n                        } else {\n                            int id = oid2;\n                            B2x = dx[id]; B2y = dy[id];\n                        }\n                        // new C at y is event1\n                        if (kx == 0) {\n                            int id = oid1;\n                            C2x = rx[id]; C2y = ry[id];\n                        } else {\n                            int id = oid1;\n                            C2x = dx[id]; C2y = dy[id];\n                        }\n\n                        int after = manhattan(Ax, Ay, B2x, B2y)\n                                  + manhattan(B2x, B2y, C2x, C2y)\n                                  + manhattan(C2x, C2y, Dx_, Dy_);\n\n                        deltaCost = after - before;\n                    } else {\n                        int xPrev = x - 1;\n                        int xNext = x + 1;\n                        int yPrev = y - 1;\n                        int yNext = y + 1;\n\n                        int Ax, Ay, Bx, By, Cx, Cy;\n                        int Dx_, Dy_, Ex, Ey, Fx, Fy;\n\n                        getCoordPosFinal(xPrev, Ax, Ay);\n                        getCoordPosFinal(x, Bx, By);\n                        getCoordPosFinal(xNext, Cx, Cy);\n\n                        getCoordPosFinal(yPrev, Dx_, Dy_);\n                        getCoordPosFinal(y, Ex, Ey);\n                        getCoordPosFinal(yNext, Fx, Fy);\n\n                        int before = manhattan(Ax, Ay, Bx, By)\n                                   + manhattan(Bx, By, Cx, Cy)\n                                   + manhattan(Dx_, Dy_, Ex, Ey)\n                                   + manhattan(Ex, Ey, Fx, Fy);\n\n                        int B2x, B2y, E2x, E2y;\n                        // new B at x is event2\n                        if (ky == 0) {\n                            int id = oid2;\n                            B2x = rx[id]; B2y = ry[id];\n                        } else {\n                            int id = oid2;\n                            B2x = dx[id]; B2y = dy[id];\n                        }\n                        // new E at y is event1\n                        if (kx == 0) {\n                            int id = oid1;\n                            E2x = rx[id]; E2y = ry[id];\n                        } else {\n                            int id = oid1;\n                            E2x = dx[id]; E2y = dy[id];\n                        }\n\n                        int after = manhattan(Ax, Ay, B2x, B2y)\n                                  + manhattan(B2x, B2y, Cx, Cy)\n                                  + manhattan(Dx_, Dy_, E2x, E2y)\n                                  + manhattan(E2x, E2y, Fx, Fy);\n\n                        deltaCost = after - before;\n                    }\n\n                    if (deltaCost < 0) {\n                        // apply improving swap\n                        routeCost += deltaCost;\n                        swap(finalKind[x], finalKind[y]);\n                        swap(finalOid[x], finalOid[y]);\n                        // update positions\n                        if (kx == 0) posP2[oid1] = y; else posD2[oid1] = y;\n                        if (ky == 0) posP2[oid2] = x; else posD2[oid2] = x;\n                        improved = true;\n                        goto restart_greedy;\n                    }\n                }\n            }\n            break;\n        restart_greedy:;\n        }\n    }\nend_greedy_improve:;\n\n    // -----------------------------------------------------------\n    // Build final path coordinates from final route (kind, oid)\n    // -----------------------------------------------------------\n    vector<pair<int,int>> path;\n    path.reserve(routeSize);\n    for (int pos = 0; pos < routeSize; ++pos) {\n        if (pos == 0 || pos == routeSize - 1) {\n            path.emplace_back(OFFICE_X, OFFICE_Y);\n        } else if (finalKind[pos] == 0) {\n            int local = finalOid[pos];\n            int gi = globalOfLocal[local];\n            path.emplace_back(a[gi], b[gi]);\n        } else {\n            int local = finalOid[pos];\n            int gi = globalOfLocal[local];\n            path.emplace_back(c[gi], d[gi]);\n        }\n    }\n\n    // -----------------------------------------------------------\n    // Output\n    // -----------------------------------------------------------\n    // First line: m and chosen order indices (1-based)\n    cout << M;\n    for (int i = 0; i < M; ++i) {\n        cout << ' ' << (bestSel[i] + 1);\n    }\n    cout << '\\n';\n\n    // Second line: n and route coordinates\n    int n = (int)path.size();\n    cout << n;\n    for (int i = 0; i < n; ++i) {\n        cout << ' ' << path[i].first << ' ' << path[i].second;\n    }\n    cout << '\\n';\n\n    return 0;\n}","ahc007":"#include <bits/stdc++.h>\nusing namespace std;\n\n// ---------- DSU (Union-Find) ----------\nstruct DSU {\n    int n;\n    vector<int> p, r;\n    DSU() {}\n    DSU(int n_) { init(n_); }\n    void init(int n_) {\n        n = n_;\n        p.resize(n);\n        r.assign(n, 0);\n        iota(p.begin(), p.end(), 0);\n    }\n    int find(int x) {\n        if (p[x] == x) return x;\n        return p[x] = find(p[x]);\n    }\n    bool same(int a, int b) {\n        return find(a) == find(b);\n    }\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\n// ---------- XorShift RNG ----------\nstruct XorShift {\n    uint32_t x = 123456789u;\n    uint32_t y = 362436069u;\n    uint32_t z = 521288629u;\n    uint32_t w = 88675123u;\n    uint32_t next() {\n        uint32_t t = x ^ (x << 11);\n        x = y; y = z; z = w;\n        w = w ^ (w >> 19) ^ (t ^ (t >> 8));\n        return w;\n    }\n    uint32_t nextUInt(uint32_t bound) {\n        return next() % bound;\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    const int N = 400;\n    const int M = 1995;\n    const int LOG = 9; // 2^9 = 512 > 400\n\n    // ----- Read coordinates -----\n    vector<int> x(N), y(N);\n    for (int i = 0; i < N; i++) {\n        if (!(cin >> x[i] >> y[i])) return 0;\n    }\n\n    // ----- Read edges -----\n    vector<int> u(M), v(M);\n    for (int i = 0; i < M; i++) {\n        cin >> u[i] >> v[i];\n    }\n\n    // ----- Precompute geometric distances d_i -----\n    vector<int> d(M);\n    for (int i = 0; i < M; i++) {\n        int dx = x[u[i]] - x[v[i]];\n        int dy = y[u[i]] - y[v[i]];\n        double dist = sqrt((double)dx * dx + (double)dy * dy);\n        d[i] = (int)llround(dist);\n    }\n\n    // ----- Compute geometric MST (for connectivity) -----\n    vector<int> idx(M);\n    iota(idx.begin(), idx.end(), 0);\n    sort(idx.begin(), idx.end(), [&](int a, int b) {\n        if (d[a] != d[b]) return d[a] < d[b];\n        return a < b;\n    });\n\n    vector<char> inTree(M, false);\n    DSU dsu0(N);\n    int used = 0;\n    for (int id : idx) {\n        if (!dsu0.same(u[id], v[id])) {\n            dsu0.unite(u[id], v[id]);\n            inTree[id] = true;\n            used++;\n            if (used == N - 1) break;\n        }\n    }\n\n    // ----- Build adjacency of geometric MST -----\n    vector<vector<pair<int,int>>> adj(N);\n    adj.assign(N, {});\n    for (int i = 0; i < M; i++) {\n        if (!inTree[i]) continue;\n        adj[u[i]].push_back({v[i], d[i]});\n        adj[v[i]].push_back({u[i], d[i]});\n    }\n\n    // ----- LCA precomputation for max edge on path in MST -----\n    vector<int> depth(N, 0);\n    vector<vector<int>> par(LOG, vector<int>(N));\n    vector<vector<int>> mx(LOG, vector<int>(N));\n\n    {\n        queue<int> q;\n        vector<char> vis(N, false);\n        int root = 0;\n        vis[root] = true;\n        depth[root] = 0;\n        par[0][root] = root;\n        mx[0][root] = 0;\n        q.push(root);\n        while (!q.empty()) {\n            int cur = q.front(); q.pop();\n            for (auto [to, w] : adj[cur]) {\n                if (!vis[to]) {\n                    vis[to] = true;\n                    depth[to] = depth[cur] + 1;\n                    par[0][to] = cur;\n                    mx[0][to] = w;\n                    q.push(to);\n                }\n            }\n        }\n        for (int k = 1; k < LOG; k++) {\n            for (int vtx = 0; vtx < N; vtx++) {\n                int p = par[k-1][vtx];\n                par[k][vtx] = par[k-1][p];\n                mx[k][vtx] = max(mx[k-1][vtx], mx[k-1][p]);\n            }\n        }\n    }\n\n    auto getMaxOnPath = [&](int a, int b) -> int {\n        if (a == b) return 0;\n        int res = 0;\n        if (depth[a] < depth[b]) swap(a, b);\n        int diff = depth[a] - depth[b];\n        for (int k = 0; k < LOG; k++) {\n            if (diff & (1 << k)) {\n                res = max(res, mx[k][a]);\n                a = par[k][a];\n            }\n        }\n        if (a == b) return res;\n        for (int k = LOG - 1; k >= 0; k--) {\n            if (par[k][a] != par[k][b]) {\n                res = max(res, mx[k][a]);\n                res = max(res, mx[k][b]);\n                a = par[k][a];\n                b = par[k][b];\n            }\n        }\n        res = max(res, mx[0][a]);\n        res = max(res, mx[0][b]);\n        return res;\n    };\n\n    // ----- H[i] = max d on MST path between u[i], v[i] (for non-tree edges) -----\n    vector<int> H(M, 0);\n    for (int i = 0; i < M; i++) {\n        if (inTree[i]) continue;\n        int h = getMaxOnPath(u[i], v[i]);\n        if (h <= 0) h = d[i];\n        H[i] = h;\n    }\n\n    // ----- Monte Carlo to approximate MST distribution under true weights -----\n    XorShift rng;\n    const int S = 2000;  // number of simulations (increased from 1600)\n\n    vector<vector<int>> chosenLens(M);\n    int avgCap = (S * 400) / M + 8; // rough average per edge\n    for (int i = 0; i < M; i++) {\n        chosenLens[i].reserve(avgCap);\n    }\n\n    vector<int> sampleLen(M);\n    vector<int> perm(M);\n\n    for (int s = 0; s < S; s++) {\n        for (int i = 0; i < M; i++) {\n            uint32_t range = (uint32_t)(2 * d[i] + 1); // [d[i], 3*d[i]]\n            sampleLen[i] = d[i] + (int)rng.nextUInt(range);\n            perm[i] = i;\n        }\n        sort(perm.begin(), perm.end(), [&](int a, int b) {\n            if (sampleLen[a] != sampleLen[b]) return sampleLen[a] < sampleLen[b];\n            return a < b;\n        });\n        DSU dsu(N);\n        int cnt = 0;\n        for (int eid : perm) {\n            if (!dsu.same(u[eid], v[eid])) {\n                dsu.unite(u[eid], v[eid]);\n                chosenLens[eid].push_back(sampleLen[eid]);\n                cnt++;\n                if (cnt == N - 1) break;\n            }\n        }\n    }\n\n    // ----- Compute thresholds thr[i] for non-tree edges -----\n    vector<int> thr(M);\n    for (int i = 0; i < M; i++) thr[i] = d[i]; // default\n\n    for (int i = 0; i < M; i++) {\n        if (inTree[i]) continue; // MST edges: threshold unused\n        auto &vec = chosenLens[i];\n        if (vec.empty()) {\n            thr[i] = d[i];\n            continue;\n        }\n        sort(vec.begin(), vec.end());\n\n        int Hi = H[i];\n        if (Hi <= 0) Hi = d[i];\n        double r = (double)d[i] / (double)Hi;\n        if (r < 1.0) r = 1.0;\n        if (r > 3.0) r = 3.0;\n\n        // Base quantile factor from geometric ratio r\n        double baseQ;\n        if (r <= 1.02)      baseQ = 0.82;\n        else if (r <= 1.20) baseQ = 0.78;\n        else if (r <= 1.50) baseQ = 0.72;\n        else if (r <= 1.80) baseQ = 0.66;\n        else if (r <= 2.20) baseQ = 0.60;\n        else                baseQ = 0.54;\n\n        // Adjust by empirical selection probability p\n        double p = (double)vec.size() / (double)S;\n        double delta = 0.0;\n        if (p >= 0.45)      delta += 0.03;\n        else if (p >= 0.30) delta += 0.015;\n        else if (p <= 0.03) delta -= 0.05;\n        else if (p <= 0.08) delta -= 0.03;\n        else if (p <= 0.15) delta -= 0.015;\n\n        double qf = baseQ + delta;\n        if (qf < 0.50) qf = 0.50;\n        if (qf > 0.90) qf = 0.90;\n\n        int cnt = (int)vec.size();\n        int idxQ = (int)(qf * cnt);\n        if (idxQ >= cnt) idxQ = cnt - 1;\n        if (idxQ < 0) idxQ = 0;\n\n        int t = vec[idxQ];\n        if (t < d[i]) t = d[i];\n        int maxLen = 3 * d[i];\n        if (t > maxLen) t = maxLen;\n        thr[i] = t;\n    }\n\n    // ----- Online phase -----\n    DSU dsuCur(N);\n\n    for (int i = 0; i < M; i++) {\n        long long l;\n        if (!(cin >> l)) return 0;\n\n        bool take = false;\n\n        if (!dsuCur.same(u[i], v[i])) {\n            if (inTree[i]) {\n                // Geometric MST edge: always accept when it connects different components\n                take = true;\n            } else {\n                // Non-tree edge: accept only if length is not too large\n                if (l <= thr[i]) {\n                    take = true;\n                }\n            }\n        } else {\n            take = false; // would form a cycle\n        }\n\n        if (take) {\n            dsuCur.unite(u[i], v[i]);\n        }\n\n        cout << (take ? 1 : 0) << '\\n';\n        cout.flush();\n    }\n\n    return 0;\n}","ahc008":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Pet {\n    int x, y, t;\n};\n\nstruct Human {\n    int x, y;\n};\n\nstatic const int H = 30;\nstatic const int W = 30;\n\nbool inside(int x, int y) {\n    return 1 <= x && x <= H && 1 <= y && y <= W;\n}\n\n// Check whether we are allowed to place a wall at (x,y)\nbool canWallCell(int x, int y,\n                 const vector<Pet> &pets,\n                 const vector<Human> &humans) {\n    if (!inside(x, y)) return false;\n    // Cannot place on a human\n    for (const auto &h : humans) {\n        if (h.x == x && h.y == y) return false;\n    }\n    // Cannot place on or adjacent (4-neighbor) to a pet\n    for (const auto &p : pets) {\n        int dx = abs(p.x - x);\n        int dy = abs(p.y - y);\n        if (dx + dy == 0) return false; // same cell\n        if (dx + dy == 1) return false; // 4-neighbor\n    }\n    return true;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    if (!(cin >> N)) {\n        return 0;\n    }\n    vector<Pet> pets(N);\n    for (int i = 0; i < N; i++) {\n        cin >> pets[i].x >> pets[i].y >> pets[i].t;\n    }\n    int M;\n    cin >> M;\n    vector<Human> humans(M);\n    for (int i = 0; i < M; i++) {\n        cin >> humans[i].x >> humans[i].y;\n    }\n\n    // Grid of walls: true means impassable\n    static bool wall[H + 1][W + 1];\n    for (int i = 1; i <= H; i++) {\n        for (int j = 1; j <= W; j++) wall[i][j] = false;\n    }\n\n    // We will build a vertical wall at column WALL_COL\n    const int WALL_COL = 16; // 1-indexed\n    const int WALK_COL = 17; // walkway column for the builder (to the right of the wall)\n    const int builder = 0;   // index of the builder human\n\n    // Row completion tracking for the wall\n    vector<bool> rowWalled(H + 1, false);\n    int walledCount = 0;\n\n    const int T_PRE = 50; // preparation phase duration\n\n    for (int turn = 0; turn < 300; turn++) {\n        string actions(M, '.');\n\n        // Decide actions for humans\n        if (M > 0) {\n            Human &hb = humans[builder];\n            int hx = hb.x;\n            int hy = hb.y;\n\n            char act = '.';\n\n            if (turn < T_PRE) {\n                // Preparation: move builder horizontally to walkway column\n                if (hy < WALK_COL) act = 'R';\n                else if (hy > WALK_COL) act = 'L';\n                else act = '.';\n            } else {\n                // Building phase\n                if (hy != WALK_COL) {\n                    // Ensure builder is on walkway column\n                    if (hy < WALK_COL) act = 'R';\n                    else if (hy > WALK_COL) act = 'L';\n                } else {\n                    // On walkway column; move up/down and place walls\n                    if (walledCount >= H) {\n                        act = '.';\n                    } else {\n                        // Determine if we can wall at current row\n                        bool thisRowUnwalled = !rowWalled[hx];\n\n                        bool canWallHere = false;\n                        if (thisRowUnwalled && !wall[hx][WALL_COL]) {\n                            if (canWallCell(hx, WALL_COL, pets, humans)) {\n                                canWallHere = true;\n                            }\n                        }\n                        if (thisRowUnwalled && canWallHere) {\n                            // Place wall to the left from (hx, WALK_COL) to (hx, WALL_COL)\n                            act = (WALK_COL > WALL_COL ? 'l' : 'r');\n                            wall[hx][WALL_COL] = true;\n                            rowWalled[hx] = true;\n                            walledCount++;\n                        } else {\n                            // Move to nearest other row that still needs a wall\n                            int bestRow = -1;\n                            int bestDist = INT_MAX;\n                            for (int r = 1; r <= H; r++) {\n                                if (!rowWalled[r] && r != hx) {\n                                    int d = abs(r - hx);\n                                    if (d < bestDist) {\n                                        bestDist = d;\n                                        bestRow = r;\n                                    }\n                                }\n                            }\n                            if (bestRow != -1) {\n                                if (bestRow > hx) act = 'D';\n                                else act = 'U';\n                            } else {\n                                // This row is the only remaining one; wait until it becomes safe\n                                act = '.';\n                            }\n                        }\n                    }\n                }\n            }\n            actions[builder] = act;\n        }\n\n        // Other humans\n        for (int i = 0; i < M; i++) {\n            if (i == builder) continue;\n            Human &h = humans[i];\n            char act = '.';\n            if (turn < T_PRE) {\n                // Move off the wall column if initially on it\n                if (h.y == WALL_COL) {\n                    // Simple: move left (safe, because WALL_COL=16, so >=2)\n                    act = 'L';\n                }\n            } else {\n                act = '.';\n            }\n            actions[i] = act;\n        }\n\n        // Output actions and flush\n        cout << actions << '\\n' << flush;\n\n        // Apply wall placements\n        for (int i = 0; i < M; i++) {\n            char c = actions[i];\n            if (c == 'u' || c == 'd' || c == 'l' || c == 'r') {\n                int x = humans[i].x;\n                int y = humans[i].y;\n                int nx = x, ny = y;\n                if (c == 'u') nx = x - 1;\n                else if (c == 'd') nx = x + 1;\n                else if (c == 'l') ny = y - 1;\n                else if (c == 'r') ny = y + 1;\n                if (inside(nx, ny)) {\n                    wall[nx][ny] = true;\n                }\n            }\n        }\n\n        // Apply human moves\n        for (int i = 0; i < M; i++) {\n            char c = actions[i];\n            if (c == 'U' || c == 'D' || c == 'L' || c == 'R') {\n                int x = humans[i].x;\n                int y = humans[i].y;\n                int nx = x, ny = y;\n                if (c == 'U') nx = x - 1;\n                else if (c == 'D') nx = x + 1;\n                else if (c == 'L') ny = y - 1;\n                else if (c == 'R') ny = y + 1;\n                if (inside(nx, ny) && !wall[nx][ny]) {\n                    humans[i].x = nx;\n                    humans[i].y = ny;\n                }\n            }\n        }\n\n        // Read pets' moves\n        vector<string> pmoves(N);\n        for (int i = 0; i < N; i++) {\n            cin >> pmoves[i];\n        }\n\n        // Apply pets' moves\n        for (int i = 0; i < N; i++) {\n            for (char c : pmoves[i]) {\n                int x = pets[i].x;\n                int y = pets[i].y;\n                int nx = x, ny = y;\n                if (c == 'U') nx = x - 1;\n                else if (c == 'D') nx = x + 1;\n                else if (c == 'L') ny = y - 1;\n                else if (c == 'R') ny = y + 1;\n                if (inside(nx, ny) && !wall[nx][ny]) {\n                    pets[i].x = nx;\n                    pets[i].y = ny;\n                } else {\n                    // According to rules, pets won't try to move into walls,\n                    // but we keep this check for safety.\n                }\n            }\n        }\n    }\n\n    return 0;\n}","ahc009":"#include <bits/stdc++.h>\nusing namespace std;\n\n// Grid/DP constants\nstatic const int H = 20;\nstatic const int W = 20;\nstatic const int N = H * W;\nstatic const int MAXL = 200;\n\n// DP arrays\nstatic double alpha_dp[MAXL + 1][N];\nstatic double beta_dp [MAXL + 1][N];\nstatic double prefix_score[MAXL + 1];\n\n// Directions\nint  dirIdx[256];\nchar dirChar[4] = {'U', 'D', 'L', 'R'};\n\n// Precomputed next cell\nint nextCell[4][N];\n\n// Globals\nint start_id, goal_id;\nint start_r, start_c;\nint goal_r, goal_c;\nint L = MAXL;\ndouble forget_p;\n\n// RNG (fixed seed for determinism)\nmt19937 rng(1234567);\n\n// Common helpers\ninline char rev_dir(char c) {\n    if (c == 'U') return 'D';\n    if (c == 'D') return 'U';\n    if (c == 'L') return 'R';\n    return 'L'; // 'R'\n}\n\n// Build adjacency graph from wall info\nvector<vector<int>> build_graph(const vector<string> &h, const vector<string> &v) {\n    vector<vector<int>> g(N);\n    auto cell_id = [](int r, int c) { return r * W + c; };\n\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            int id = cell_id(i, j);\n            if (j + 1 < W && h[i][j] == '0') {\n                int nid = cell_id(i, j + 1);\n                g[id].push_back(nid);\n                g[nid].push_back(id);\n            }\n            if (i + 1 < H && v[i][j] == '0') {\n                int nid = cell_id(i + 1, j);\n                g[id].push_back(nid);\n                g[nid].push_back(id);\n            }\n        }\n    }\n    return g;\n}\n\n// Decode direction from \"from\" to \"to\"\nchar decode_dir(int from, int to) {\n    int r1 = from / W, c1 = from % W;\n    int r2 = to   / W, c2 = to   % W;\n    if (r2 == r1 && c2 == c1 + 1) return 'R';\n    if (r2 == r1 && c2 == c1 - 1) return 'L';\n    if (r2 == r1 + 1 && c2 == c1) return 'D';\n    if (r2 == r1 - 1 && c2 == c1) return 'U';\n    return 'U'; // fallback; should not occur\n}\n\n// Canonical BFS: predecessor tree from start to all nodes\nvector<int> bfs_prev_canonical(const vector<vector<int>> &g) {\n    vector<int> prev(N, -1);\n    queue<int> q;\n    q.push(start_id);\n    prev[start_id] = start_id;\n\n    while (!q.empty()) {\n        int vtx = q.front(); q.pop();\n        for (int to : g[vtx]) {\n            if (prev[to] == -1) {\n                prev[to] = vtx;\n                q.push(to);\n            }\n        }\n    }\n    return prev;\n}\n\n// Generic BFS from a given root: returns prev and dist\nvoid bfs_from_root(const vector<vector<int>> &g, int root,\n                   vector<int> &prev, vector<int> &dist) {\n    prev.assign(N, -1);\n    dist.assign(N, -1);\n    queue<int> q;\n    q.push(root);\n    prev[root] = root;\n    dist[root] = 0;\n    while (!q.empty()) {\n        int vtx = q.front(); q.pop();\n        for (int to : g[vtx]) {\n            if (prev[to] == -1) {\n                prev[to] = vtx;\n                dist[to] = dist[vtx] + 1;\n                q.push(to);\n            }\n        }\n    }\n}\n\n// Build path (as directions) from root to target using predecessor tree\nvector<char> path_from_prev_root(const vector<int> &prev, int root, int target) {\n    vector<char> path;\n    if (prev[target] == -1) {\n        path.push_back('R');\n        return path;\n    }\n    int cur = target;\n    while (cur != root) {\n        int p = prev[cur];\n        path.push_back(decode_dir(p, cur));\n        cur = p;\n    }\n    reverse(path.begin(), path.end());\n    if (path.empty()) path.push_back('R');\n    return path;\n}\n\n// Wrapper: path from global start_id using predecessor tree\nvector<char> path_from_prev(const vector<int> &prev, int target) {\n    return path_from_prev_root(prev, start_id, target);\n}\n\n// BFS shortest path with different neighbor-order modes\n// mode 1: neighbors sorted by Manhattan distance to goal (goal-directed)\n// mode 2: randomized neighbor order\nvector<char> bfs_shortest_path_any(const vector<vector<int>> &g, int mode) {\n    vector<vector<int>> g2 = g;\n\n    if (mode == 1) {\n        auto manh = [&](int id) {\n            int r = id / W, c = id % W;\n            return abs(r - goal_r) + abs(c - goal_c);\n        };\n        for (int u = 0; u < N; ++u) {\n            auto &adj = g2[u];\n            sort(adj.begin(), adj.end(),\n                 [&](int a, int b) { return manh(a) < manh(b); });\n        }\n    } else if (mode == 2) {\n        for (int u = 0; u < N; ++u) {\n            auto &adj = g2[u];\n            shuffle(adj.begin(), adj.end(), rng);\n        }\n    }\n\n    vector<int> prev(N, -1);\n    queue<int> q;\n    q.push(start_id);\n    prev[start_id] = start_id;\n\n    while (!q.empty()) {\n        int vtx = q.front(); q.pop();\n        if (vtx == goal_id) break;\n        for (int to : g2[vtx]) {\n            if (prev[to] == -1) {\n                prev[to] = vtx;\n                q.push(to);\n            }\n        }\n    }\n\n    vector<char> path;\n    if (prev[goal_id] == -1) {\n        path.push_back('R');\n        return path;\n    }\n    int cur = goal_id;\n    while (cur != start_id) {\n        int p = prev[cur];\n        path.push_back(decode_dir(p, cur));\n        cur = p;\n    }\n    reverse(path.begin(), path.end());\n    if (path.empty()) path.push_back('R');\n    return path;\n}\n\n// Build a simple goal-loop pattern: move to neighbors of goal and back\nvector<char> build_goal_loop_pattern() {\n    vector<char> pattern;\n    for (char c : {'U', 'D', 'L', 'R'}) {\n        int d = dirIdx[(unsigned char)c];\n        int dest = nextCell[d][goal_id];\n        if (dest != goal_id) {\n            pattern.push_back(c);\n            pattern.push_back(rev_dir(c));\n        }\n    }\n    if (pattern.empty()) {\n        pattern.push_back('U');\n        pattern.push_back('D');\n    }\n    return pattern;\n}\n\n// Build a \"goal sweep\" pattern: from goal, visit nearby cells and return\nvector<char> build_goal_sweep_pattern(const vector<vector<int>> &graph) {\n    vector<int> prevG, distG;\n    bfs_from_root(graph, goal_id, prevG, distG);\n\n    const int R = 3; // sweep radius around goal\n    vector<int> cells;\n    for (int id = 0; id < N; ++id) {\n        if (distG[id] >= 1 && distG[id] <= R) {\n            cells.push_back(id);\n        }\n    }\n    sort(cells.begin(), cells.end(), [&](int a, int b) {\n        if (distG[a] != distG[b]) return distG[a] < distG[b];\n        return a < b;\n    });\n\n    vector<char> pattern;\n    for (int id : cells) {\n        vector<char> path = path_from_prev_root(prevG, goal_id, id);\n        for (char c : path) pattern.push_back(c);\n        for (int i = (int)path.size() - 1; i >= 0; --i) {\n            pattern.push_back(rev_dir(path[i]));\n        }\n    }\n\n    if (pattern.empty()) {\n        pattern = build_goal_loop_pattern();\n    }\n    return pattern;\n}\n\n// Evaluate route s[1..L]; fills alpha_dp, beta_dp, prefix_score; returns E[S]\ndouble evaluate_route(const vector<char> &s) {\n    const double p = forget_p;\n    const double q = 1.0 - p;\n\n    memset(alpha_dp, 0, sizeof(alpha_dp));\n    alpha_dp[0][start_id] = 1.0;\n    prefix_score[0] = 0.0;\n\n    for (int t = 1; t <= L; ++t) {\n        memset(alpha_dp[t], 0, sizeof(alpha_dp[t]));\n        prefix_score[t] = prefix_score[t - 1];\n\n        int d = dirIdx[(unsigned char)s[t]];\n        double reward_weight = 401.0 - t;\n\n        for (int id = 0; id < N; ++id) {\n            double px = alpha_dp[t - 1][id];\n            if (px == 0.0) continue;\n\n            if (id == goal_id) {\n                alpha_dp[t][id] += px;\n                continue;\n            }\n\n            int dest = nextCell[d][id];\n\n            if (dest == id) {\n                alpha_dp[t][id] += px;\n            } else if (dest == goal_id) {\n                double moved = px * q;\n                prefix_score[t] += moved * reward_weight;\n                alpha_dp[t][goal_id] += moved;\n                alpha_dp[t][id] += px * p;\n            } else {\n                double moved = px * q;\n                alpha_dp[t][dest] += moved;\n                alpha_dp[t][id]   += px * p;\n            }\n        }\n    }\n\n    double total_score = prefix_score[L];\n\n    memset(beta_dp, 0, sizeof(beta_dp));\n    for (int id = 0; id < N; ++id) beta_dp[L][id] = 0.0;\n\n    for (int t = L - 1; t >= 0; --t) {\n        int d = dirIdx[(unsigned char)s[t + 1]];\n        double reward_weight = 401.0 - (t + 1);\n\n        for (int id = 0; id < N; ++id) {\n            if (id == goal_id) {\n                beta_dp[t][id] = 0.0;\n                continue;\n            }\n            int dest = nextCell[d][id];\n            double immediate = 0.0;\n            double future = 0.0;\n\n            if (dest == id) {\n                future = beta_dp[t + 1][id];\n            } else if (dest == goal_id) {\n                immediate = q * reward_weight;\n                future = p * beta_dp[t + 1][id];\n            } else {\n                future = q * beta_dp[t + 1][dest] + p * beta_dp[t + 1][id];\n            }\n            beta_dp[t][id] = immediate + future;\n        }\n    }\n\n    return total_score;\n}\n\n// Score if we change only s[k] to newDir, using current DP data\ndouble score_if_change_step(const vector<char> & /*s*/, int k, char newDir) {\n    const double p = forget_p;\n    const double q = 1.0 - p;\n\n    double res = prefix_score[k - 1];\n    int d = dirIdx[(unsigned char)newDir];\n\n    for (int id = 0; id < N; ++id) {\n        double px = alpha_dp[k - 1][id];\n        if (px == 0.0) continue;\n        if (id == goal_id) continue;\n\n        int dest = nextCell[d][id];\n        if (dest == id) {\n            res += px * beta_dp[k][id];\n        } else if (dest == goal_id) {\n            res += px * q * (401.0 - k);\n            res += px * p * beta_dp[k][id];\n        } else {\n            res += px * (q * beta_dp[k][dest] + p * beta_dp[k][id]);\n        }\n    }\n    return res;\n}\n\nstruct SeedRoute {\n    vector<char> route;\n    double score;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int si, sj, ti, tj;\n    if (!(cin >> si >> sj >> ti >> tj >> forget_p)) {\n        return 0;\n    }\n    vector<string> h(H), v(H - 1);\n    for (int i = 0; i < H; ++i) cin >> h[i];\n    for (int i = 0; i < H - 1; ++i) cin >> v[i];\n\n    start_id = si * W + sj;\n    goal_id  = ti * W + tj;\n    start_r = si; start_c = sj;\n    goal_r = ti; goal_c = tj;\n\n    // Direction indices\n    dirIdx['U'] = 0;\n    dirIdx['D'] = 1;\n    dirIdx['L'] = 2;\n    dirIdx['R'] = 3;\n\n    // Precompute nextCell\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            int id = i * W + j;\n            if (i == 0 || v[i - 1][j] == '1') nextCell[0][id] = id;\n            else                              nextCell[0][id] = (i - 1) * W + j;\n            if (i == H - 1 || v[i][j] == '1') nextCell[1][id] = id;\n            else                               nextCell[1][id] = (i + 1) * W + j;\n            if (j == 0 || h[i][j - 1] == '1') nextCell[2][id] = id;\n            else                              nextCell[2][id] = i * W + (j - 1);\n            if (j == W - 1 || h[i][j] == '1') nextCell[3][id] = id;\n            else                              nextCell[3][id] = i * W + (j + 1);\n        }\n    }\n\n    // Build graph and goal patterns\n    vector<vector<int>> graph = build_graph(h, v);\n    vector<char> goal_loop_pattern  = build_goal_loop_pattern();\n    int goal_loop_len = (int)goal_loop_pattern.size();\n    vector<char> goal_sweep_pattern = build_goal_sweep_pattern(graph);\n    int goal_sweep_len = (int)goal_sweep_pattern.size();\n\n    // Canonical BFS tree and canonical path to goal\n    vector<int> prevCanon = bfs_prev_canonical(graph);\n    vector<char> pathCanonGoal = path_from_prev(prevCanon, goal_id);\n\n    // Canonical paths to neighbors around goal\n    vector<vector<char>> canonicalNeighbors;\n    int gr = goal_r, gc = goal_c;\n    int drs[4] = {-1, 1, 0, 0};\n    int dcs[4] = {0, 0, -1, 1};\n    for (int k = 0; k < 4; ++k) {\n        int nr = gr + drs[k];\n        int nc = gc + dcs[k];\n        if (nr < 0 || nr >= H || nc < 0 || nc >= W) continue;\n        int nid = nr * W + nc;\n        if (prevCanon[nid] == -1) continue;\n        canonicalNeighbors.push_back(path_from_prev(prevCanon, nid));\n    }\n\n    // Goal-directed BFS path and two random BFS paths to goal\n    vector<char> pathGoalPref = bfs_shortest_path_any(graph, 1);\n    vector<char> pathRandom1  = bfs_shortest_path_any(graph, 2);\n    vector<char> pathRandom2  = bfs_shortest_path_any(graph, 2);\n\n    // Generic DR-based paths (ignoring walls)\n    vector<char> pathDR1, pathDR2;\n    {\n        int needD = max(0, goal_r - start_r);\n        int needR = max(0, goal_c - start_c);\n        for (int i = 0; i < needD; ++i) pathDR1.push_back('D');\n        for (int j = 0; j < needR; ++j) pathDR1.push_back('R');\n        if (pathDR1.empty()) pathDR1.push_back('R');\n\n        int dLeft = needD, rLeft = needR;\n        bool turnD = true;\n        while (dLeft > 0 || rLeft > 0) {\n            if (turnD && dLeft > 0) {\n                pathDR2.push_back('D');\n                dLeft--;\n            } else if (!turnD && rLeft > 0) {\n                pathDR2.push_back('R');\n                rLeft--;\n            } else if (dLeft > 0) {\n                pathDR2.push_back('D');\n                dLeft--;\n            } else if (rLeft > 0) {\n                pathDR2.push_back('R');\n                rLeft--;\n            }\n            turnD = !turnD;\n        }\n        if (pathDR2.empty()) pathDR2.push_back('R');\n    }\n\n    // Collect base paths\n    vector<vector<char>> basePaths;\n    basePaths.push_back(pathCanonGoal);\n    for (auto &p : canonicalNeighbors) basePaths.push_back(p);\n    basePaths.push_back(pathGoalPref);\n    basePaths.push_back(pathRandom1);\n    basePaths.push_back(pathRandom2);\n    basePaths.push_back(pathDR1);\n    basePaths.push_back(pathDR2);\n\n    // Add doubled, tripled, and quadrupled-step expansions for canonical and goal-directed\n    auto add_expansions = [&](const vector<char> &pathBase) {\n        // 2x\n        {\n            vector<char> exp;\n            exp.reserve(pathBase.size() * 2);\n            for (char c : pathBase) {\n                exp.push_back(c);\n                exp.push_back(c);\n            }\n            if (exp.empty()) exp.push_back('R');\n            basePaths.push_back(exp);\n        }\n        // 3x\n        {\n            vector<char> exp;\n            exp.reserve(pathBase.size() * 3);\n            for (char c : pathBase) {\n                exp.push_back(c);\n                exp.push_back(c);\n                exp.push_back(c);\n            }\n            if (exp.empty()) exp.push_back('R');\n            basePaths.push_back(exp);\n        }\n        // 4x\n        {\n            vector<char> exp;\n            exp.reserve(pathBase.size() * 4);\n            for (char c : pathBase) {\n                exp.push_back(c);\n                exp.push_back(c);\n                exp.push_back(c);\n                exp.push_back(c);\n            }\n            if (exp.empty()) exp.push_back('R');\n            basePaths.push_back(exp);\n        }\n    };\n    add_expansions(pathCanonGoal);\n    add_expansions(pathGoalPref);\n\n    // Build candidate seed routes and evaluate them\n    vector<SeedRoute> seeds;\n    seeds.reserve(basePaths.size() * 4);\n\n    for (const auto &path_raw : basePaths) {\n        vector<char> path = path_raw;\n        if (path.empty()) path.push_back('R');\n        int D = (int)path.size();\n        if (D > L) D = L;\n\n        // Template 0: repeat path for entire length\n        {\n            vector<char> route(L + 1);\n            for (int t = 1; t <= L; ++t) {\n                route[t] = path[(t - 1) % D];\n            }\n            double sc = evaluate_route(route);\n            seeds.push_back({route, sc});\n        }\n\n        // Template 1: path once, then simple goal loop pattern\n        {\n            vector<char> route(L + 1);\n            for (int t = 1; t <= L; ++t) {\n                if (t <= D) {\n                    route[t] = path[t - 1];\n                } else {\n                    route[t] = goal_loop_pattern[(t - D - 1) % goal_loop_len];\n                }\n            }\n            double sc = evaluate_route(route);\n            seeds.push_back({route, sc});\n        }\n\n        // Template 2: path twice (if room), then simple goal loop pattern\n        {\n            vector<char> route(L + 1);\n            int D2 = min(2 * D, L);\n            for (int t = 1; t <= L; ++t) {\n                if (t <= D) {\n                    route[t] = path[t - 1];\n                } else if (t <= D2) {\n                    route[t] = path[t - D - 1];\n                } else {\n                    int offset = t - D2 - 1;\n                    route[t] = goal_loop_pattern[offset % goal_loop_len];\n                }\n            }\n            double sc = evaluate_route(route);\n            seeds.push_back({route, sc});\n        }\n\n        // Template 3: path once, then goal sweep pattern\n        {\n            vector<char> route(L + 1);\n            for (int t = 1; t <= L; ++t) {\n                if (t <= D) {\n                    route[t] = path[t - 1];\n                } else {\n                    route[t] = goal_sweep_pattern[(t - D - 1) % goal_sweep_len];\n                }\n            }\n            double sc = evaluate_route(route);\n            seeds.push_back({route, sc});\n        }\n    }\n\n    // Sort seeds by base score descending\n    sort(seeds.begin(), seeds.end(),\n         [](const SeedRoute &a, const SeedRoute &b) {\n             return a.score > b.score;\n         });\n\n    // Hill-climb from top K seeds, keep best result\n    const int K = min<int>(6, seeds.size());\n    const int MAX_ITER = 6;\n    const double EPS = 1e-9;\n\n    vector<int> order(L);\n    for (int i = 0; i < L; ++i) order[i] = i + 1;\n\n    double globalBestScore = -1.0;\n    vector<char> globalBestRoute(L + 1);\n\n    for (int sIdx = 0; sIdx < K; ++sIdx) {\n        vector<char> route = seeds[sIdx].route;\n        double bestScore = evaluate_route(route);\n\n        for (int iter = 0; iter < MAX_ITER; ++iter) {\n            bool improved_any = false;\n            shuffle(order.begin(), order.end(), rng);\n\n            for (int idx = 0; idx < L; ++idx) {\n                int k = order[idx];\n                char orig = route[k];\n                char bestDir = orig;\n                double currScore = bestScore;\n\n                for (int di = 0; di < 4; ++di) {\n                    char c = dirChar[di];\n                    if (c == orig) continue;\n                    double newScore = score_if_change_step(route, k, c);\n                    if (newScore > currScore + EPS) {\n                        currScore = newScore;\n                        bestDir = c;\n                    }\n                }\n\n                if (bestDir != orig) {\n                    route[k] = bestDir;\n                    bestScore = evaluate_route(route);\n                    improved_any = true;\n                }\n            }\n            if (!improved_any) break;\n        }\n\n        if (bestScore > globalBestScore) {\n            globalBestScore = bestScore;\n            globalBestRoute = route;\n        }\n    }\n\n    // Output final route\n    string out;\n    out.reserve(L);\n    for (int t = 1; t <= L; ++t) out.push_back(globalBestRoute[t]);\n    cout << out << '\\n';\n\n    return 0;\n}","ahc010":"#include <bits/stdc++.h>\nusing namespace std;\n\nconstexpr int N = 30;\nconstexpr int M = 30;\nconstexpr int TOT_STATES = N * M * 4;\n\n// Input and current board\nint baseTile[N][M];   // initial tile types from input (0..7)\nint curTile[N][M];    // current effective tile type (0..7) after rotation\nint curRot[N][M];     // current rotation count (0..3) for each tile\n\n// Stage-1 best (local score)\nint bestLocalRot[N][M];\n// Final best (true score)\nint bestRot[N][M];\n\n// Rotation table: rotTable[t][r] = tile type after rotating t by r times 90deg CCW\nint rotTable[8][4];\n\n// Rail mapping: toTbl[t][d] = exit direction when entering tile type t from direction d\n// d: 0 = left, 1 = up, 2 = right, 3 = down\nint toTbl[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// Whether side d of tile type t has a rail\nbool useSide[8][4];\n\n// For loop detection in computeTrueScore (using precomputed transitions)\nbool visitedState[TOT_STATES];\nint  pathId[TOT_STATES];\nint  pathStep[TOT_STATES];\n\n// Precomputed \"next state\" transition: from (i, j, d) to next state's index, or -1 if dead-end\nint nextStateArr[TOT_STATES];\n\nint di[4] = {0, -1, 0, 1};  // left, up, right, down\nint dj[4] = {-1, 0, 1, 0};\n\nmt19937_64 rng(20240131);\n\n// Encode (i, j, d) into a single index 0..3599\ninline int encodeState(int i, int j, int d) {\n    return ((i * M + j) << 2) | d;  // 0..3599\n}\n\n// Compute local score = number of connected internal edges\nint computeLocalScore() {\n    int connected = 0;\n\n    // Horizontal internal edges: (i,j)-(i,j+1)\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < M - 1; ++j) {\n            int t1 = curTile[i][j];\n            int t2 = curTile[i][j + 1];\n            if (useSide[t1][2] && useSide[t2][0]) connected++;\n        }\n    }\n    // Vertical internal edges: (i,j)-(i+1,j)\n    for (int i = 0; i < N - 1; ++i) {\n        for (int j = 0; j < M; ++j) {\n            int t1 = curTile[i][j];\n            int t2 = curTile[i + 1][j];\n            if (useSide[t1][3] && useSide[t2][1]) connected++;\n        }\n    }\n    return connected;\n}\n\n// Incremental delta of local score when tile (i,j) type changes from oldT to newT\ninline int deltaLocalScoreTile(int i, int j, int oldT, int newT) {\n    int deltaConn = 0;\n\n    // Up neighbor\n    if (i > 0) {\n        int neighbor = curTile[i - 1][j];\n        bool neighborUsedDown = useSide[neighbor][3];\n        bool oldUsedUp = useSide[oldT][1];\n        bool newUsedUp = useSide[newT][1];\n        int before = (oldUsedUp && neighborUsedDown) ? 1 : 0;\n        int after  = (newUsedUp && neighborUsedDown) ? 1 : 0;\n        deltaConn += after - before;\n    }\n\n    // Down neighbor\n    if (i < N - 1) {\n        int neighbor = curTile[i + 1][j];\n        bool neighborUsedUp = useSide[neighbor][1];\n        bool oldUsedDown = useSide[oldT][3];\n        bool newUsedDown = useSide[newT][3];\n        int before = (oldUsedDown && neighborUsedUp) ? 1 : 0;\n        int after  = (newUsedDown && neighborUsedUp) ? 1 : 0;\n        deltaConn += after - before;\n    }\n\n    // Left neighbor\n    if (j > 0) {\n        int neighbor = curTile[i][j - 1];\n        bool neighborUsedRight = useSide[neighbor][2];\n        bool oldUsedLeft = useSide[oldT][0];\n        bool newUsedLeft = useSide[newT][0];\n        int before = (oldUsedLeft && neighborUsedRight) ? 1 : 0;\n        int after  = (newUsedLeft && neighborUsedRight) ? 1 : 0;\n        deltaConn += after - before;\n    }\n\n    // Right neighbor\n    if (j < M - 1) {\n        int neighbor = curTile[i][j + 1];\n        bool neighborUsedLeft = useSide[neighbor][0];\n        bool oldUsedRight = useSide[oldT][2];\n        bool newUsedRight = useSide[newT][2];\n        int before = (oldUsedRight && neighborUsedLeft) ? 1 : 0;\n        int after  = (newUsedRight && neighborUsedLeft) ? 1 : 0;\n        deltaConn += after - before;\n    }\n\n    return deltaConn;\n}\n\n// Build transitions for all states based on curTile\nvoid buildAllTransitions() {\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < M; ++j) {\n            int t = curTile[i][j];\n            for (int d = 0; d < 4; ++d) {\n                int idx = encodeState(i, j, d);\n                int d2 = toTbl[t][d];\n                if (d2 == -1) {\n                    nextStateArr[idx] = -1;\n                    continue;\n                }\n                int ni = i + di[d2];\n                int nj = j + dj[d2];\n                if (ni < 0 || ni >= N || nj < 0 || nj >= M) {\n                    nextStateArr[idx] = -1;\n                } else {\n                    int nd = (d2 + 2) & 3;\n                    nextStateArr[idx] = encodeState(ni, nj, nd);\n                }\n            }\n        }\n    }\n}\n\n// Update transitions only for tile (i,j) based on current curTile[i][j]\ninline void updateTransitionsForTile(int i, int j) {\n    int t = curTile[i][j];\n    for (int d = 0; d < 4; ++d) {\n        int idx = encodeState(i, j, d);\n        int d2 = toTbl[t][d];\n        if (d2 == -1) {\n            nextStateArr[idx] = -1;\n            continue;\n        }\n        int ni = i + di[d2];\n        int nj = j + dj[d2];\n        if (ni < 0 || ni >= N || nj < 0 || nj >= M) {\n            nextStateArr[idx] = -1;\n        } else {\n            int nd = (d2 + 2) & 3;\n            nextStateArr[idx] = encodeState(ni, nj, nd);\n        }\n    }\n}\n\n// Compute true score = product of lengths of two longest loops\nint computeTrueScore() {\n    fill(visitedState, visitedState + TOT_STATES, false);\n    fill(pathId, pathId + TOT_STATES, 0);\n\n    int best1 = 0, best2 = 0;\n    int curPathId = 1;\n\n    for (int s = 0; s < TOT_STATES; ++s) {\n        if (visitedState[s]) continue;\n        int nxt0 = nextStateArr[s];\n        if (nxt0 < 0) {\n            visitedState[s] = true;\n            continue;\n        }\n\n        int cur = s;\n        int len = 0;\n        ++curPathId;\n\n        while (true) {\n            visitedState[cur] = true;\n            pathId[cur] = curPathId;\n            pathStep[cur] = len;\n\n            int nxt = nextStateArr[cur];\n            if (nxt < 0) break;\n            ++len;\n            if (pathId[nxt] == curPathId) {\n                int cycLen = len - pathStep[nxt];\n                if (cycLen >= best1) {\n                    best2 = best1;\n                    best1 = cycLen;\n                } else if (cycLen > best2) {\n                    best2 = cycLen;\n                }\n                break;\n            }\n            if (visitedState[nxt]) break;\n            cur = nxt;\n        }\n    }\n\n    if (best2 == 0) return 0;\n    return best1 * best2;\n}\n\ninline double randDouble() {\n    return (double)(rng() >> 11) * (1.0 / (1ULL << 53));\n}\n\n// For multi-tile moves in SA\nstruct TileChange {\n    int i, j;\n    int oldRot, oldT;\n    int newRot, newT;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // Precompute rotation table\n    int rotMap[8] = {1, 2, 3, 0, 5, 4, 7, 6};\n    for (int t = 0; t < 8; ++t) {\n        rotTable[t][0] = t;\n        for (int r = 1; r < 4; ++r) {\n            rotTable[t][r] = rotMap[ rotTable[t][r - 1] ];\n        }\n    }\n\n    // Precompute useSide\n    for (int t = 0; t < 8; ++t) {\n        for (int d = 0; d < 4; ++d) {\n            useSide[t][d] = (toTbl[t][d] != -1);\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 < M; ++j) {\n            baseTile[i][j] = s[j] - '0';\n        }\n    }\n\n    auto timeStart = chrono::steady_clock::now();\n    const double GLOBAL_TIME_LIMIT = 1.95;  // slightly larger, still safe under 2.0\n\n    // ===== Stage 1: Multi-start greedy local search on local score =====\n    const int MAX_RUNS = 8;\n    const int MAX_PASS = 10;\n\n    vector<int> order(N * M);\n    iota(order.begin(), order.end(), 0);\n\n    int bestLocalScore = numeric_limits<int>::min();\n\n    for (int run = 0; run < MAX_RUNS; ++run) {\n        // Random initial rotations\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < M; ++j) {\n                int r = (int)(rng() & 3ULL);  // 0..3\n                curRot[i][j] = r;\n                curTile[i][j] = rotTable[ baseTile[i][j] ][r];\n            }\n        }\n\n        int curLocalScore = computeLocalScore();\n\n        for (int pass = 0; pass < MAX_PASS; ++pass) {\n            bool changed = false;\n            shuffle(order.begin(), order.end(), rng);\n\n            for (int idxCell : order) {\n                int i = idxCell / M;\n                int j = idxCell % M;\n\n                int oldRot = curRot[i][j];\n                int oldT = curTile[i][j];\n\n                int bestDelta = 0;\n                int bestR = oldRot;\n                int bestT = oldT;\n\n                // Try all 4 rotations\n                for (int r = 0; r < 4; ++r) {\n                    if (r == oldRot) continue;\n                    int newT = rotTable[ baseTile[i][j] ][r];\n                    if (newT == oldT) continue; // same effective type\n                    int delta = deltaLocalScoreTile(i, j, oldT, newT);\n                    if (delta > bestDelta) {\n                        bestDelta = delta;\n                        bestR = r;\n                        bestT = newT;\n                    }\n                }\n\n                if (bestDelta > 0) {\n                    curRot[i][j] = bestR;\n                    curTile[i][j] = bestT;\n                    curLocalScore += bestDelta;\n                    changed = true;\n                }\n            }\n\n            if (!changed) break;\n        }\n\n        if (curLocalScore > bestLocalScore) {\n            bestLocalScore = curLocalScore;\n            for (int i = 0; i < N; ++i)\n                for (int j = 0; j < M; ++j)\n                    bestLocalRot[i][j] = curRot[i][j];\n        }\n\n        double elapsed = chrono::duration<double>(chrono::steady_clock::now() - timeStart).count();\n        if (elapsed > GLOBAL_TIME_LIMIT * 0.20) {\n            // Keep enough time for stages 2 and 3\n            break;\n        }\n    }\n\n    // Initialize curRot/curTile from best local configuration\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < M; ++j) {\n            curRot[i][j] = bestLocalRot[i][j];\n            curTile[i][j] = rotTable[ baseTile[i][j] ][curRot[i][j]];\n        }\n    }\n\n    // Build transitions for Stage 2 & 3\n    buildAllTransitions();\n\n    // Initial true score from Stage-1 result\n    int curScore = computeTrueScore();\n    int bestScore = curScore;\n\n    // Copy as initial best rotations for Stage 2/3\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < M; ++j)\n            bestRot[i][j] = curRot[i][j];\n\n    // ===== Stage 2: Greedy hill-climb on true score (1 pass) =====\n    const int TRUE_PASSES = 1;\n    vector<int> order2(N * M);\n    iota(order2.begin(), order2.end(), 0);\n\n    for (int pass = 0; pass < TRUE_PASSES; ++pass) {\n        double elapsed = chrono::duration<double>(chrono::steady_clock::now() - timeStart).count();\n        if (elapsed > GLOBAL_TIME_LIMIT * 0.55) break; // leave time for SA\n\n        bool changed = false;\n        shuffle(order2.begin(), order2.end(), rng);\n\n        for (int idxCell : order2) {\n            double now = chrono::duration<double>(chrono::steady_clock::now() - timeStart).count();\n            if (now > GLOBAL_TIME_LIMIT * 0.55) break; // time check\n\n            int i = idxCell / M;\n            int j = idxCell % M;\n\n            int oldRot = curRot[i][j];\n            int oldT = curTile[i][j];\n            int base = baseTile[i][j];\n\n            int bestR = oldRot;\n            int bestT = oldT;\n            int bestCandScore = curScore;\n            int bestDiff = 0;\n\n            // Try all alternative effective tile types\n            for (int r = 0; r < 4; ++r) {\n                if (r == oldRot) continue;\n                int newT = rotTable[base][r];\n                if (newT == oldT) continue;\n\n                // apply candidate\n                curRot[i][j] = r;\n                curTile[i][j] = newT;\n                updateTransitionsForTile(i, j);\n\n                int sc = computeTrueScore();\n                int diff = sc - curScore;\n                if (diff > bestDiff) {\n                    bestDiff = diff;\n                    bestR = r;\n                    bestT = newT;\n                    bestCandScore = sc;\n                }\n\n                // revert\n                curRot[i][j] = oldRot;\n                curTile[i][j] = oldT;\n                updateTransitionsForTile(i, j);\n            }\n\n            if (bestDiff > 0) {\n                // apply best candidate\n                curRot[i][j] = bestR;\n                curTile[i][j] = bestT;\n                updateTransitionsForTile(i, j);\n                curScore = bestCandScore;\n                changed = true;\n\n                if (curScore > bestScore) {\n                    bestScore = curScore;\n                    for (int x = 0; x < N; ++x)\n                        for (int y = 0; y < M; ++y)\n                            bestRot[x][y] = curRot[x][y];\n                }\n            }\n        }\n\n        if (!changed) break;\n    }\n\n    // Reset current configuration to best found so far before SA\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < M; ++j) {\n            curRot[i][j] = bestRot[i][j];\n            curTile[i][j] = rotTable[ baseTile[i][j] ][curRot[i][j]];\n        }\n    }\n    buildAllTransitions();\n    curScore = bestScore;\n\n    // Precompute indices of cross tiles (type 4 or 5) to bias SA moves\n    vector<int> crossIdx;\n    crossIdx.reserve(N * M / 2);\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < M; ++j) {\n            int t0 = baseTile[i][j];\n            if (t0 == 4 || t0 == 5) {\n                crossIdx.push_back(i * M + j);\n            }\n        }\n    }\n\n    // ===== Stage 3: Simulated annealing on true score (single- & multi-tile moves) =====\n    const double T0  = 800.0; // global initial temperature\n    const double T1  = 3.0;   // global final temperature\n    const double TL0 = 6.0;   // local filter initial \"temperature\"\n    const double TL1 = 1.0;   // local filter final \"temperature\"\n\n    while (true) {\n        double elapsed = chrono::duration<double>(chrono::steady_clock::now() - timeStart).count();\n        if (elapsed > GLOBAL_TIME_LIMIT) break;\n        double progress = elapsed / GLOBAL_TIME_LIMIT;\n        if (progress > 1.0) progress = 1.0;\n        double T = T0 + (T1 - T0) * progress;\n        double TL = TL0 + (TL1 - TL0) * progress;\n\n        bool multi = (rng() % 6 == 0); // ~16% multi-tile moves\n\n        if (!multi) {\n            // ---- Single-tile move ----\n            int idxCell;\n            if (!crossIdx.empty() && (rng() % 4 != 0)) { // 75% from cross tiles\n                idxCell = crossIdx[ (int)(rng() % crossIdx.size()) ];\n            } else {\n                idxCell = (int)(rng() % (N * M));\n            }\n            int i = idxCell / M;\n            int j = idxCell % M;\n\n            int oldRot = curRot[i][j];\n            int oldT = curTile[i][j];\n            int base = baseTile[i][j];\n\n            int newRot, newT;\n            // Propose a different effective tile type via rotation\n            do {\n                newRot = (int)(rng() & 3ULL);  // 0..3\n                newT = rotTable[base][newRot];\n            } while (newT == oldT);\n\n            int localDelta = deltaLocalScoreTile(i, j, oldT, newT);\n\n            // Local pre-filter: skip strongly bad local moves with high probability\n            bool evaluate = false;\n            if (localDelta >= 0) {\n                evaluate = true;\n            } else {\n                double pLocal = exp((double)localDelta / TL); // localDelta <= -1\n                if (randDouble() < pLocal) evaluate = true;\n            }\n            if (!evaluate) continue;\n\n            // Apply tentative move\n            curRot[i][j] = newRot;\n            curTile[i][j] = newT;\n            updateTransitionsForTile(i, j);\n\n            int newScore = computeTrueScore();\n            int diff = newScore - curScore;\n\n            bool accept = false;\n            if (diff >= 0) {\n                accept = true;\n            } else {\n                double prob = exp((double)diff / T);\n                if (randDouble() < prob) accept = true;\n            }\n\n            if (accept) {\n                curScore = newScore;\n                if (newScore > bestScore) {\n                    bestScore = newScore;\n                    for (int x = 0; x < N; ++x)\n                        for (int y = 0; y < M; ++y)\n                            bestRot[x][y] = curRot[x][y];\n                }\n            } else {\n                // Revert move\n                curRot[i][j] = oldRot;\n                curTile[i][j] = oldT;\n                updateTransitionsForTile(i, j);\n            }\n        } else {\n            // ---- Multi-tile move (2 tiles) ----\n            const int K = 2;\n            TileChange ch[K];\n\n            // Select K distinct tiles (prefer cross tiles when available)\n            int chosenIdx[K];\n            for (int k = 0; k < K; ++k) {\n                int idxCell;\n                while (true) {\n                    if (!crossIdx.empty()) {\n                        idxCell = crossIdx[ (int)(rng() % crossIdx.size()) ];\n                    } else {\n                        idxCell = (int)(rng() % (N * M));\n                    }\n                    bool ok = true;\n                    for (int t = 0; t < k; ++t)\n                        if (idxCell == chosenIdx[t]) { ok = false; break; }\n                    if (ok) break;\n                }\n                chosenIdx[k] = idxCell;\n                int i = idxCell / M;\n                int j = idxCell % M;\n                ch[k].i = i;\n                ch[k].j = j;\n                ch[k].oldRot = curRot[i][j];\n                ch[k].oldT   = curTile[i][j];\n            }\n\n            int totalLocalDelta = 0;\n            bool anyChange = false;\n\n            // Propose new rotations and compute approximate local delta\n            for (int k = 0; k < K; ++k) {\n                int i = ch[k].i;\n                int j = ch[k].j;\n                int base = baseTile[i][j];\n                int newRot, newT;\n                int oldT = ch[k].oldT;\n\n                int tries = 0;\n                do {\n                    newRot = (int)(rng() & 3ULL);\n                    newT = rotTable[base][newRot];\n                    ++tries;\n                    if (tries > 8) break;\n                } while (newT == oldT);\n\n                if (newT == oldT) {\n                    anyChange = false;\n                    break;\n                }\n\n                ch[k].newRot = newRot;\n                ch[k].newT   = newT;\n                anyChange = true;\n\n                int ld = deltaLocalScoreTile(i, j, oldT, newT);\n                totalLocalDelta += ld;\n            }\n\n            if (!anyChange) continue;\n\n            // Local filter for multi-move\n            bool evaluate = false;\n            if (totalLocalDelta >= 0) {\n                evaluate = true;\n            } else {\n                double pLocal = exp((double)totalLocalDelta / TL);\n                if (randDouble() < pLocal) evaluate = true;\n            }\n            if (!evaluate) continue;\n\n            // Apply tentative multi-move\n            for (int k = 0; k < K; ++k) {\n                int i = ch[k].i;\n                int j = ch[k].j;\n                curRot[i][j] = ch[k].newRot;\n                curTile[i][j] = ch[k].newT;\n                updateTransitionsForTile(i, j);\n            }\n\n            int newScore = computeTrueScore();\n            int diff = newScore - curScore;\n\n            bool accept = false;\n            if (diff >= 0) {\n                accept = true;\n            } else {\n                double prob = exp((double)diff / T);\n                if (randDouble() < prob) accept = true;\n            }\n\n            if (accept) {\n                curScore = newScore;\n                if (newScore > bestScore) {\n                    bestScore = newScore;\n                    for (int x = 0; x < N; ++x)\n                        for (int y = 0; y < M; ++y)\n                            bestRot[x][y] = curRot[x][y];\n                }\n            } else {\n                // Revert multi-move\n                for (int k = 0; k < K; ++k) {\n                    int i = ch[k].i;\n                    int j = ch[k].j;\n                    curRot[i][j] = ch[k].oldRot;\n                    curTile[i][j] = ch[k].oldT;\n                    updateTransitionsForTile(i, j);\n                }\n            }\n        }\n    }\n\n    // ===== Output best rotations =====\n    string out;\n    out.reserve(N * M);\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < M; ++j) {\n            int r = bestRot[i][j] & 3;\n            out.push_back(char('0' + r));\n        }\n    }\n    cout << out << '\\n';\n\n    return 0;\n}","ahc011":"#include <bits/stdc++.h>\nusing namespace std;\n\n// ====== Global constants and types ======\n\nstatic const int MAXN = 10;\n\nint N, T;\n\n// Board representation\nstruct Board {\n    unsigned char a[MAXN][MAXN];\n};\n\n// Directions for graph connectivity (Up, Right, Down, Left)\nconst int DX[4]   = {-1, 0, 1, 0};\nconst int DY[4]   = { 0, 1, 0,-1};\n// Bit masks corresponding to U,R,D,L in that order\nconst int MASK[4] = {2, 4, 8, 1};\n// Opposite directions\nconst int OPP[4]  = {2, 3, 0, 1};\n\nstruct EvalRes {\n    int bestTree;    // size of largest tree component\n    int bestConn;    // size of largest connected component\n    int totalTree;   // sum of sizes of all tree components\n};\n\n// ====== Evaluation of a board configuration ======\n\nEvalRes evaluate(const Board &B) {\n    static bool vis[MAXN][MAXN];\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            vis[i][j] = false;\n\n    int bestTree = 0;\n    int bestConn = 0;\n    int totalTree = 0;\n\n    int qx[MAXN * MAXN];\n    int qy[MAXN * MAXN];\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (B.a[i][j] == 0 || vis[i][j]) continue;\n\n            int v = 0; // vertices in this component\n            int e = 0; // edges in this component\n\n            int head = 0, tail = 0;\n            vis[i][j] = true;\n            qx[tail] = i;\n            qy[tail] = j;\n            ++tail;\n\n            while (head < tail) {\n                int x = qx[head];\n                int y = qy[head];\n                ++head;\n\n                ++v;\n                unsigned char tile = B.a[x][y];\n\n                for (int dir = 0; dir < 4; ++dir) {\n                    if (!(tile & MASK[dir])) continue;\n                    int nx = x + DX[dir];\n                    int ny = y + DY[dir];\n                    if (nx < 0 || nx >= N || ny < 0 || ny >= N) continue;\n                    unsigned char nt = B.a[nx][ny];\n                    if (nt == 0) continue;\n                    if (!(nt & MASK[OPP[dir]])) continue;\n\n                    if (!vis[nx][ny]) {\n                        vis[nx][ny] = true;\n                        qx[tail] = nx;\n                        qy[tail] = ny;\n                        ++tail;\n                    }\n                    // count each undirected edge once\n                    if (x < nx || (x == nx && y < ny)) {\n                        ++e;\n                    }\n                }\n            }\n\n            bestConn = max(bestConn, v);\n            if (e == v - 1) {\n                bestTree = max(bestTree, v);\n                totalTree += v;\n            }\n        }\n    }\n\n    return {bestTree, bestConn, totalTree};\n}\n\n// Convert EvalRes to a scalar score (lexicographic: bestTree > totalTree > bestConn)\ninline long long evalScore(const EvalRes &er) {\n    // N <= 10, sizes <= 99, so these weights keep lexicographic priority.\n    return (long long)er.bestTree * 1000000LL\n         + (long long)er.totalTree * 1000LL\n         + (long long)er.bestConn;\n}\n\n// Comparison of two EvalRes according to the same lexicographic priority\ninline bool betterEval(const EvalRes &a, const EvalRes &b) {\n    if (a.bestTree != b.bestTree) return a.bestTree > b.bestTree;\n    if (a.totalTree != b.totalTree) return a.totalTree > b.totalTree;\n    if (a.bestConn != b.bestConn) return a.bestConn > b.bestConn;\n    return false;\n}\n\n// ====== Sliding puzzle mechanics ======\n\ninline bool legalMove(int r, int c, char mv) {\n    if (mv == 'U') return r > 0;\n    if (mv == 'D') return r + 1 < N;\n    if (mv == 'L') return c > 0;\n    if (mv == 'R') return c + 1 < N;\n    return false;\n}\n\n// Apply move to board and blank position\ninline void applyMove(Board &B, int &r, int &c, char mv) {\n    if (mv == 'U') {\n        swap(B.a[r][c], B.a[r-1][c]);\n        --r;\n    } else if (mv == 'D') {\n        swap(B.a[r][c], B.a[r+1][c]);\n        ++r;\n    } else if (mv == 'L') {\n        swap(B.a[r][c], B.a[r][c-1]);\n        --c;\n    } else if (mv == 'R') {\n        swap(B.a[r][c], B.a[r][c+1]);\n        ++c;\n    }\n}\n\n// Opposite sliding move\ninline char oppositeMove(char mv) {\n    if (mv == 'U') return 'D';\n    if (mv == 'D') return 'U';\n    if (mv == 'L') return 'R';\n    if (mv == 'R') return 'L';\n    return '?';\n}\n\n// ====== Time control ======\n\nusing Clock = chrono::steady_clock;\ninline double nowSec(const Clock::time_point &start) {\n    return chrono::duration<double>(Clock::now() - start).count();\n}\n\n// ====== Depth-limited DFS for lookahead scoring ======\n\nint LOOKAHEAD_DEPTH; // decided from N in main\n\n// Depth-limited DFS to find best reachable score within given depth\n// starting from board B and blank position (br, bc).\n// lastMove: last move applied to reach this state (to avoid immediate reverse),\n// depth: remaining depth to explore (0 means just evaluate this state).\nlong long dfsScore(const Board &B, int br, int bc, char lastMove, int depth) {\n    EvalRes er = evaluate(B);\n    long long best = evalScore(er);\n    if (depth == 0) return best;\n\n    static const char allMoves[4] = {'U', 'D', 'L', 'R'};\n    char cand[4];\n    int cnt = 0;\n    for (int k = 0; k < 4; ++k) {\n        char mv = allMoves[k];\n        if (!legalMove(br, bc, mv)) continue;\n        if (lastMove != '?' && mv == oppositeMove(lastMove)) continue;\n        cand[cnt++] = mv;\n    }\n\n    for (int i = 0; i < cnt; ++i) {\n        char mv = cand[i];\n        Board nb = B;\n        int nbr = br, nbc = bc;\n        applyMove(nb, nbr, nbc, mv);\n        long long sc = dfsScore(nb, nbr, nbc, mv, depth - 1);\n        if (sc > best) best = sc;\n    }\n    return best;\n}\n\n// ====== Main heuristic: multi-start greedy with lookahead ======\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    if (!(cin >> N >> T)) {\n        return 0;\n    }\n\n    Board initialBoard;\n    int initialBlankR = -1, initialBlankC = -1;\n\n    for (int i = 0; i < N; ++i) {\n        string row;\n        cin >> row;\n        for (int j = 0; j < N; ++j) {\n            char ch = row[j];\n            int val;\n            if ('0' <= ch && ch <= '9') val = ch - '0';\n            else val = ch - 'a' + 10;\n            initialBoard.a[i][j] = static_cast<unsigned char>(val);\n            if (val == 0) {\n                initialBlankR = i;\n                initialBlankC = j;\n            }\n        }\n    }\n\n    // Decide lookahead depth depending on N.\n    // Deeper for smaller boards, shallower for largest boards to keep time.\n    if (N <= 7) LOOKAHEAD_DEPTH = 4;\n    else LOOKAHEAD_DEPTH = 3;\n\n    // RNG for tie-breaking\n    mt19937_64 rng(\n        (uint64_t)chrono::high_resolution_clock::now().time_since_epoch().count()\n    );\n\n    auto startTime = Clock::now();\n    const double TIME_LIMIT = 2.8; // seconds, safety margin under 3.0\n\n    EvalRes initialEval = evaluate(initialBoard);\n    int totalTiles = N * N - 1;\n\n    // If initial board is already a full tree, output empty sequence.\n    if (initialEval.bestTree == totalTiles) {\n        cout << \"\\n\";\n        return 0;\n    }\n\n    EvalRes bestOverallEval = initialEval;\n    string bestOverallOps;\n    int bestOverallStep = 0;\n\n    static const char allMoves[4] = {'U', 'D', 'L', 'R'};\n    const int MAX_RUNS = 100; // upper bound; actual runs limited by TIME_LIMIT\n\n    for (int run = 0; run < MAX_RUNS && nowSec(startTime) < TIME_LIMIT; ++run) {\n        Board board = initialBoard;\n        int blankR = initialBlankR;\n        int blankC = initialBlankC;\n\n        string ops;\n        ops.reserve(T);\n\n        EvalRes bestRunEval = initialEval;\n        int bestRunStep = 0;\n        char lastMove = '?';\n\n        for (int step = 0; step < T; ++step) {\n            if (nowSec(startTime) >= TIME_LIMIT) break;\n\n            // Build candidate first moves, avoiding immediate reverse if possible.\n            char cand1[4];\n            int cand1cnt = 0;\n            for (int k = 0; k < 4; ++k) {\n                char mv = allMoves[k];\n                if (!legalMove(blankR, blankC, mv)) continue;\n                if (step > 0 && mv == oppositeMove(lastMove)) continue;\n                cand1[cand1cnt++] = mv;\n            }\n            if (cand1cnt == 0) {\n                // All legal moves are reverse of last; allow them.\n                for (int k = 0; k < 4; ++k) {\n                    char mv = allMoves[k];\n                    if (legalMove(blankR, blankC, mv)) {\n                        cand1[cand1cnt++] = mv;\n                    }\n                }\n                if (cand1cnt == 0) break; // no legal moves (shouldn't happen)\n            }\n\n            long long bestScoreStep = LLONG_MIN;\n            char chosenMove = cand1[0];\n            int tieCount = 0;\n\n            // For each candidate first move, perform depth-limited search.\n            for (int idx = 0; idx < cand1cnt; ++idx) {\n                char d1 = cand1[idx];\n\n                Board b1 = board;\n                int br1 = blankR, bc1 = blankC;\n                applyMove(b1, br1, bc1, d1);\n\n                // We already performed one move (d1); explore up to LOOKAHEAD_DEPTH-1 more.\n                long long sc = dfsScore(b1, br1, bc1, d1, LOOKAHEAD_DEPTH - 1);\n\n                if (sc > bestScoreStep) {\n                    bestScoreStep = sc;\n                    chosenMove = d1;\n                    tieCount = 1;\n                } else if (sc == bestScoreStep) {\n                    ++tieCount;\n                    if (rng() % tieCount == 0) {\n                        chosenMove = d1;\n                    }\n                }\n            }\n\n            // Commit chosen move\n            applyMove(board, blankR, blankC, chosenMove);\n            ops.push_back(chosenMove);\n            lastMove = chosenMove;\n\n            // Evaluate current board and update run-best prefix\n            EvalRes curEval = evaluate(board);\n            if (betterEval(curEval, bestRunEval)) {\n                bestRunEval = curEval;\n                bestRunStep = (int)ops.size();\n                if (bestRunEval.bestTree == totalTiles) {\n                    // Found a full tree; no need to continue this run.\n                    break;\n                }\n            }\n        }\n\n        // Update global best over all runs\n        if (betterEval(bestRunEval, bestOverallEval)) {\n            bestOverallEval = bestRunEval;\n            bestOverallStep = bestRunStep;\n            bestOverallOps = ops.substr(0, bestRunStep);\n            if (bestOverallEval.bestTree == totalTiles) {\n                // Reached optimal S; further improvements only affect K,\n                // but when S < N^2-1 score ignores K, so we can stop.\n                break;\n            }\n        }\n    }\n\n    if (bestOverallStep == 0) {\n        // best is initial board\n        cout << \"\\n\";\n    } else {\n        cout << bestOverallOps << \"\\n\";\n    }\n\n    return 0;\n}","ahc012":"#include <bits/stdc++.h>\nusing namespace std;\n\n// Constants\nstatic const int RADIUS = 10000;   // radius of the cake\nstatic const int BIG    = 100000;  // endpoints for axis-aligned lines\n\n// Pattern of regions: up to 128 bits (we only need <= 100)\nstruct Pattern {\n    uint64_t lo, hi;\n    bool operator==(const Pattern& o) const noexcept {\n        return lo == o.lo && hi == o.hi;\n    }\n};\nstruct PatternHash {\n    size_t operator()(const Pattern& p) const noexcept {\n        uint64_t x = p.lo * 0x9E3779B97F4A7C15ULL;\n        x ^= p.hi + 0x9E3779B97F4A7C15ULL + (x << 6) + (x >> 2);\n        return static_cast<size_t>(x);\n    }\n};\n\n// Line in Ax + By + C = 0 form, plus integer endpoints to output\nstruct Line {\n    long long A, B, C;\n    int px, py, qx, qy;\n};\n\n// Build quantile-based cut positions along one axis.\n//\n// Npoints: number of strawberries\n// Nc: desired number of cuts along this axis\n// sortedCoord: sorted coordinates (x or y) of all strawberries (size Npoints)\n// boundaryCoord: precomputed boundary coordinate for each boundary index 0..Npoints\n// boundaryValid: whether boundary 0..Npoints can be used without hitting any strawberry\n//\n// If we can't pick Nc valid boundaries, we fall back to uniform spacing.\nvector<int> build_quantile_cuts(\n    int Npoints,\n    int Nc,\n    const vector<int> &sortedCoord,\n    const vector<int> &boundaryCoord,\n    const vector<char> &boundaryValid\n) {\n    vector<int> cuts;\n    if (Nc <= 0) return cuts;\n\n    int validCount = 0;\n    for (int b = 0; b <= Npoints; ++b) {\n        if (boundaryValid[b]) ++validCount;\n    }\n\n    if (validCount <= Nc) {\n        // Fallback: uniform spacing in [-RADIUS, RADIUS]\n        cuts.reserve(Nc);\n        for (int i = 1; i <= Nc; ++i) {\n            long long num = 2LL * RADIUS * i;\n            int c = -RADIUS + (int)(num / (Nc + 1)); // floor\n            cuts.push_back(c);\n        }\n        return cuts;\n    }\n\n    cuts.reserve(Nc);\n    int prevB = -1;\n    bool success = true;\n    for (int i = 1; i <= Nc; ++i) {\n        long long target = 1LL * i * Npoints / (Nc + 1); // in [0, Npoints]\n        int bestB = -1;\n        long long bestDist = (1LL << 60);\n\n        // Choose next valid boundary index b > prevB minimizing |b - target|\n        for (int b = prevB + 1; b <= Npoints; ++b) {\n            if (!boundaryValid[b]) continue;\n            long long dist = llabs((long long)b - target);\n            if (dist < bestDist) {\n                bestDist = dist;\n                bestB = b;\n            }\n        }\n        if (bestB == -1) {\n            success = false;\n            break;\n        }\n        prevB = bestB;\n        cuts.push_back(boundaryCoord[bestB]);\n    }\n\n    if (!success || (int)cuts.size() != Nc) {\n        // Fallback: uniform spacing\n        cuts.clear();\n        cuts.reserve(Nc);\n        for (int i = 1; i <= Nc; ++i) {\n            long long num = 2LL * RADIUS * i;\n            int c = -RADIUS + (int)(num / (Nc + 1)); // floor\n            cuts.push_back(c);\n        }\n    }\n\n    return cuts;\n}\n\n// Compute current score (sum_d min(a_d, b_d)) for given patterns and lines.\nlong long compute_score_current(\n    const vector<uint64_t> &patLo,\n    const vector<uint64_t> &patHi,\n    int Lcur,\n    const vector<int> &a,\n    unordered_map<Pattern,int,PatternHash> &mp\n) {\n    int N = (int)patLo.size();\n    mp.clear();\n\n    if (Lcur == 0) {\n        int s = N;\n        int B[11];\n        memset(B, 0, sizeof(B));\n        if (1 <= s && s <= 10) B[s] = 1;\n        long long score = 0;\n        for (int d = 1; d <= 10; ++d) {\n            score += min((long long)a[d], (long long)B[d]);\n        }\n        return score;\n    }\n\n    mp.reserve(N * 2);\n    for (int i = 0; i < N; ++i) {\n        Pattern key{patLo[i], patHi[i]};\n        mp[key] += 1;\n    }\n\n    int B[11];\n    memset(B, 0, sizeof(B));\n    for (auto &kv : mp) {\n        int s = kv.second;\n        if (1 <= s && s <= 10) B[s] += 1;\n    }\n\n    long long score = 0;\n    for (int d = 1; d <= 10; ++d) {\n        score += min((long long)a[d], (long long)B[d]);\n    }\n    return score;\n}\n\n// Evaluate candidate line appended to current lines (patterns).\n// Returns score, or -1 if invalid (passes any strawberry center).\nlong long evaluate_candidate(\n    const Line &cand,\n    const vector<uint64_t> &patLo,\n    const vector<uint64_t> &patHi,\n    int Lcur,\n    const vector<pair<int,int>> &pts,\n    const vector<int> &a,\n    unordered_map<Pattern,int,PatternHash> &mp\n) {\n    int N = (int)pts.size();\n    mp.clear();\n    mp.reserve(N * 2);\n\n    bool invalid = false;\n\n    for (int i = 0; i < N; ++i) {\n        long long x = pts[i].first;\n        long long y = pts[i].second;\n        long long val = cand.A * x + cand.B * y + cand.C;\n        if (val == 0) {\n            invalid = true;\n            break;\n        }\n        Pattern key{patLo[i], patHi[i]};\n        if (val > 0) {\n            int bitpos = Lcur;\n            if (bitpos < 64) {\n                key.lo |= (1ULL << bitpos);\n            } else {\n                key.hi |= (1ULL << (bitpos - 64));\n            }\n        }\n        mp[key] += 1;\n    }\n\n    if (invalid) return -1;\n\n    int B[11];\n    memset(B, 0, sizeof(B));\n    for (auto &kv : mp) {\n        int s = kv.second;\n        if (1 <= s && s <= 10) B[s] += 1;\n    }\n\n    long long score = 0;\n    for (int d = 1; d <= 10; ++d) {\n        score += min((long long)a[d], (long long)B[d]);\n    }\n    return score;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, K;\n    if (!(cin >> N >> K)) return 0;\n    vector<int> a(11);\n    long long sumA = 0;\n    for (int d = 1; d <= 10; ++d) {\n        cin >> a[d];\n        sumA += a[d];\n    }\n    vector<pair<int,int>> pts(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> pts[i].first >> pts[i].second;\n    }\n\n    if (sumA == 0 || K == 0) {\n        cout << 0 << '\\n';\n        return 0;\n    }\n\n    // Average desired piece size\n    double avgD = (double)N / (double)sumA;\n\n    // Poisson fit on attendee-years distribution to tune lambda\n    vector<double> w(11, 0.0);\n    for (int d = 1; d <= 10; ++d) {\n        w[d] = (double)a[d] / (double)sumA;\n    }\n    double bestLambda = avgD;\n    double bestErr = 1e100;\n\n    for (double lambda = 1.0; lambda <= 8.0001; lambda += 0.1) {\n        double P[11];\n        P[0] = exp(-lambda);\n        double sum1to10 = 0.0;\n        for (int k = 1; k <= 10; ++k) {\n            P[k] = P[k-1] * lambda / k;\n            sum1to10 += P[k];\n        }\n        if (sum1to10 <= 0.0) continue;\n        double err = 0.0;\n        for (int d = 1; d <= 10; ++d) {\n            double q = P[d] / sum1to10;\n            double diff = q - w[d];\n            err += diff * diff;\n        }\n        if (err < bestErr) {\n            bestErr = err;\n            bestLambda = lambda;\n        }\n    }\n\n    double lambdaTarget = 0.5 * avgD + 0.5 * bestLambda;\n    lambdaTarget = max(2.0, min(8.0, lambdaTarget));\n\n    int cellsTarget = (int)llround((double)N / lambdaTarget);\n    if (cellsTarget < 1) cellsTarget = 1;\n\n    // Reserve some cuts for greedy improvement (reduce from 40 to 30 for better balance)\n    int Kextra = min(30, K / 2);   // up to 30 greedy cuts\n    if (Kextra < 0) Kextra = 0;\n    if (Kextra > K) Kextra = K;\n    int KgridLimit = max(0, K - Kextra);\n\n    // Determine grid sizes Nx, Ny with Nx + Ny <= KgridLimit\n    int bestNx = 0, bestNy = 0;\n    if (KgridLimit > 0) {\n        long long maxCellsPossible = 0;\n        for (int Nx = 0; Nx <= KgridLimit; ++Nx) {\n            int Ny = KgridLimit - Nx;\n            long long cells = 1LL * (Nx + 1) * (Ny + 1);\n            if (cells > maxCellsPossible) maxCellsPossible = cells;\n        }\n        if (cellsTarget > (int)maxCellsPossible) cellsTarget = (int)maxCellsPossible;\n\n        long long bestCellErr = (1LL << 60);\n        int bestSquarePenalty = (1 << 30);\n        for (int Nx = 0; Nx <= KgridLimit; ++Nx) {\n            for (int Ny = 0; Ny <= KgridLimit - Nx; ++Ny) {\n                long long cells = 1LL * (Nx + 1) * (Ny + 1);\n                long long err = llabs(cells - (long long)cellsTarget);\n                int squarePenalty = abs(Nx - Ny);\n                if (err < bestCellErr ||\n                    (err == bestCellErr && squarePenalty < bestSquarePenalty)) {\n                    bestCellErr = err;\n                    bestSquarePenalty = squarePenalty;\n                    bestNx = Nx;\n                    bestNy = Ny;\n                }\n            }\n        }\n    } else {\n        bestNx = bestNy = 0;\n    }\n\n    int Nx = bestNx;\n    int Ny = bestNy;\n\n    // Sorted coordinates for boundaries\n    vector<int> xs(N), ys(N);\n    for (int i = 0; i < N; ++i) {\n        xs[i] = pts[i].first;\n        ys[i] = pts[i].second;\n    }\n    sort(xs.begin(), xs.end());\n    sort(ys.begin(), ys.end());\n\n    // Build X boundaries\n    vector<int> xBoundaryCoord(N + 1);\n    vector<char> xBoundaryValid(N + 1, 0);\n    if (N > 0) {\n        int c0 = xs[0] - 1;\n        if (c0 < -RADIUS) c0 = -RADIUS;\n        xBoundaryCoord[0] = c0;\n        xBoundaryValid[0] = 1;\n\n        for (int b = 1; b <= N - 1; ++b) {\n            int left = xs[b-1];\n            int right = xs[b];\n            if (right - left >= 2) {\n                int c = (left + right) / 2;\n                xBoundaryCoord[b] = c;\n                xBoundaryValid[b] = 1;\n            } else {\n                xBoundaryValid[b] = 0;\n            }\n        }\n\n        int cN = xs[N-1] + 1;\n        if (cN > RADIUS) cN = RADIUS;\n        xBoundaryCoord[N] = cN;\n        xBoundaryValid[N] = 1;\n    }\n\n    // Build Y boundaries\n    vector<int> yBoundaryCoord(N + 1);\n    vector<char> yBoundaryValid(N + 1, 0);\n    if (N > 0) {\n        int c0 = ys[0] - 1;\n        if (c0 < -RADIUS) c0 = -RADIUS;\n        yBoundaryCoord[0] = c0;\n        yBoundaryValid[0] = 1;\n\n        for (int b = 1; b <= N - 1; ++b) {\n            int down = ys[b-1];\n            int up   = ys[b];\n            if (up - down >= 2) {\n                int c = (down + up) / 2;\n                yBoundaryCoord[b] = c;\n                yBoundaryValid[b] = 1;\n            } else {\n                yBoundaryValid[b] = 0;\n            }\n        }\n\n        int cN = ys[N-1] + 1;\n        if (cN > RADIUS) cN = RADIUS;\n        yBoundaryCoord[N] = cN;\n        yBoundaryValid[N] = 1;\n    }\n\n    // Quantile-based vertical and horizontal cuts\n    vector<int> xCuts = build_quantile_cuts(N, Nx, xs, xBoundaryCoord, xBoundaryValid);\n    vector<int> yCuts = build_quantile_cuts(N, Ny, ys, yBoundaryCoord, yBoundaryValid);\n\n    // Build initial line set (grid lines)\n    vector<Line> lines;\n    lines.reserve(K);\n    // vertical lines\n    for (int c : xCuts) {\n        Line L;\n        L.A = 1; L.B = 0; L.C = -c;\n        L.px = c; L.py = -BIG;\n        L.qx = c; L.qy =  BIG;\n        lines.push_back(L);\n    }\n    // horizontal lines\n    for (int c : yCuts) {\n        Line L;\n        L.A = 0; L.B = 1; L.C = -c;\n        L.px = -BIG; L.py = c;\n        L.qx =  BIG; L.qy = c;\n        lines.push_back(L);\n    }\n\n    int Lcur = (int)lines.size();\n\n    // Patterns for each strawberry\n    vector<uint64_t> patLo(N, 0), patHi(N, 0);\n    for (int i = 0; i < Lcur; ++i) {\n        const Line &L = lines[i];\n        for (int j = 0; j < N; ++j) {\n            long long x = pts[j].first;\n            long long y = pts[j].second;\n            long long val = L.A * x + L.B * y + L.C;\n            bool side = (val > 0);\n            if (side) {\n                int bitpos = i;\n                if (bitpos < 64) {\n                    patLo[j] |= (1ULL << bitpos);\n                } else {\n                    patHi[j] |= (1ULL << (bitpos - 64));\n                }\n            }\n        }\n    }\n\n    unordered_map<Pattern,int,PatternHash> mpCur, mpCand;\n    mpCur.reserve(N * 2);\n    mpCand.reserve(N * 2);\n\n    long long currentScore = compute_score_current(patLo, patHi, Lcur, a, mpCur);\n\n    // Random engine\n    uint64_t seed = 123456789ULL ^ (uint64_t)N;\n    if (N > 0) {\n        seed ^= (uint64_t)(pts[0].first * 1000003LL) ^ (uint64_t)(pts[0].second * 10007LL);\n    }\n    mt19937_64 rng(seed);\n    uniform_int_distribution<int> coordDist(-RADIUS, RADIUS);\n\n    const pair<int,int> offsets[8] = {\n        {1,0},{-1,0},{0,1},{0,-1},\n        {1,1},{-1,1},{1,-1},{-1,-1}\n    };\n\n    int usedExtra = 0;\n    const int CANDIDATES_PER_STEP = 35;  // evaluated per iteration\n    const int TRY_LIMIT_MULT = 4;        // tries up to CANDIDATES_PER_STEP * this\n\n    while (usedExtra < Kextra) {\n        // Recompute region partition for current lines\n        currentScore = compute_score_current(patLo, patHi, Lcur, a, mpCur);\n\n        // Collect large regions (patterns with many strawberries)\n        vector<pair<int,Pattern>> regions;\n        regions.reserve(mpCur.size());\n        for (auto &kv : mpCur) {\n            regions.emplace_back(kv.second, kv.first);\n        }\n        sort(regions.begin(), regions.end(),\n            [](const pair<int,Pattern> &x, const pair<int,Pattern> &y) {\n                return x.first > y.first;\n            });\n\n        const int MAX_BIG = 8;\n        const int MIN_BIG_SIZE = 10;\n        vector<Pattern> bigPatterns;\n        vector<vector<int>> bigIndices;\n        bigPatterns.reserve(MAX_BIG);\n        bigIndices.reserve(MAX_BIG);\n\n        for (int i = 0; i < (int)regions.size() && (int)bigPatterns.size() < MAX_BIG; ++i) {\n            int cnt = regions[i].first;\n            if (cnt < MIN_BIG_SIZE) break;\n            Pattern pat = regions[i].second;\n            bigPatterns.push_back(pat);\n        }\n\n        if (!bigPatterns.empty()) {\n            bigIndices.resize(bigPatterns.size());\n            for (int i = 0; i < N; ++i) {\n                Pattern p{patLo[i], patHi[i]};\n                for (int k = 0; k < (int)bigPatterns.size(); ++k) {\n                    if (p.lo == bigPatterns[k].lo && p.hi == bigPatterns[k].hi) {\n                        bigIndices[k].push_back(i);\n                        break;\n                    }\n                }\n            }\n        }\n\n        long long bestScoreIter = currentScore;\n        Line bestLine;\n        bool improved = false;\n\n        int validCandidates = 0;\n        int tries = 0;\n        int TRY_LIMIT = CANDIDATES_PER_STEP * TRY_LIMIT_MULT;\n\n        // Precompute cluster sizes for weighted choice\n        vector<int> clusterSizes;\n        int totalClusterSize = 0;\n        if (!bigIndices.empty()) {\n            clusterSizes.resize(bigIndices.size());\n            for (int k = 0; k < (int)bigIndices.size(); ++k) {\n                clusterSizes[k] = (int)bigIndices[k].size();\n                totalClusterSize += clusterSizes[k];\n            }\n        }\n\n        while (validCandidates < CANDIDATES_PER_STEP && tries < TRY_LIMIT) {\n            ++tries;\n            Line cand;\n            bool useCluster = (!bigIndices.empty() && (rng() % 4 != 0)); // ~3/4 cluster-based\n\n            if (useCluster) {\n                // Choose cluster weighted by size\n                if (totalClusterSize < 2) {\n                    useCluster = false;\n                } else {\n                    int r = (int)(rng() % totalClusterSize);\n                    int cid = 0;\n                    while (cid < (int)clusterSizes.size() && r >= clusterSizes[cid]) {\n                        r -= clusterSizes[cid];\n                        ++cid;\n                    }\n                    if (cid >= (int)bigIndices.size() || bigIndices[cid].size() < 2) {\n                        useCluster = false;\n                    } else {\n                        const vector<int> &idxs = bigIndices[cid];\n                        int sz = (int)idxs.size();\n                        int i1 = rng() % sz;\n                        int i2 = rng() % (sz - 1);\n                        if (i2 >= i1) ++i2;\n                        int pIdx = idxs[i1];\n                        int qIdx = idxs[i2];\n                        int x1 = pts[pIdx].first;\n                        int y1 = pts[pIdx].second;\n                        int x2 = pts[qIdx].first;\n                        int y2 = pts[qIdx].second;\n                        auto off = offsets[rng() & 7];\n                        int ox = off.first;\n                        int oy = off.second;\n                        cand.px = x1 + ox;\n                        cand.py = y1 + oy;\n                        cand.qx = x2 + ox;\n                        cand.qy = y2 + oy;\n                        if (cand.px == cand.qx && cand.py == cand.qy) {\n                            // degenerate, fall back to global\n                            useCluster = false;\n                        } else {\n                            long long X1 = cand.px, Y1 = cand.py;\n                            long long X2 = cand.qx, Y2 = cand.qy;\n                            cand.A = Y2 - Y1;\n                            cand.B = X1 - X2;\n                            cand.C = X2 * Y1 - X1 * Y2;\n                        }\n                    }\n                }\n            }\n\n            if (!useCluster) {\n                // Global random line\n                do {\n                    cand.px = coordDist(rng);\n                    cand.py = coordDist(rng);\n                    cand.qx = coordDist(rng);\n                    cand.qy = coordDist(rng);\n                } while (cand.px == cand.qx && cand.py == cand.qy);\n                long long x1 = cand.px, y1 = cand.py;\n                long long x2 = cand.qx, y2 = cand.qy;\n                cand.A = y2 - y1;\n                cand.B = x1 - x2;\n                cand.C = x2 * y1 - x1 * y2;\n                if (cand.A == 0 && cand.B == 0) continue;\n            }\n\n            long long candScore = evaluate_candidate(cand, patLo, patHi, Lcur, pts, a, mpCand);\n            if (candScore < 0) continue; // invalid (passes any strawberry)\n\n            ++validCandidates;\n            if (candScore > bestScoreIter) {\n                bestScoreIter = candScore;\n                bestLine = cand;\n                improved = true;\n            }\n        }\n\n        if (!improved) break;\n\n        // Commit best line\n        lines.push_back(bestLine);\n        int newIndex = Lcur;\n        ++Lcur;\n        ++usedExtra;\n\n        const Line &L = lines.back();\n        for (int j = 0; j < N; ++j) {\n            long long x = pts[j].first;\n            long long y = pts[j].second;\n            long long val = L.A * x + L.B * y + L.C;\n            // val == 0 should not happen (we avoided such lines in evaluate_candidate)\n            bool side = (val > 0);\n            if (side) {\n                if (newIndex < 64) {\n                    patLo[j] |= (1ULL << newIndex);\n                } else {\n                    patHi[j] |= (1ULL << (newIndex - 64));\n                }\n            }\n        }\n\n        currentScore = bestScoreIter;\n        if (Lcur >= K) break;\n    }\n\n    int totalCuts = (int)lines.size();\n    if (totalCuts > K) totalCuts = K;\n\n    cout << totalCuts << '\\n';\n    for (int i = 0; i < totalCuts; ++i) {\n        const Line &L = lines[i];\n        cout << L.px << ' ' << L.py << ' ' << L.qx << ' ' << L.qy << '\\n';\n    }\n\n    return 0;\n}","ahc014":"#include <bits/stdc++.h>\nusing namespace std;\n\n// =================== Constants & Globals ===================\n\nconst int MAXN = 65;  // N <= 61\n\nint N, M;\n\n// Board state\nstatic bool hasDot[MAXN][MAXN];      // [x][y]\nstatic bool horUsed[MAXN][MAXN];     // [y][x] edge from (x,y) to (x+1,y)\nstatic bool verUsed[MAXN][MAXN];     // [x][y] edge from (x,y) to (x,y+1)\nstatic bool diagUpUsed[MAXN][MAXN];  // [x][y] edge from (x,y) to (x+1,y+1)\nstatic bool diagDownUsed[MAXN][MAXN];// [x][y] edge from (x,y+1) to (x+1,y)\n\nstatic int rowPrefix[MAXN][MAXN+1];  // [y][i]: dots with x < i\nstatic int colPrefix[MAXN][MAXN+1];  // [x][i]: dots with y < i\nstatic int cellWeight[MAXN][MAXN];   // w(x,y)\n\n// Heuristic coefficients\nconst int W_NEW_COEF         = 3000;\nconst int SUM_EXIST_COEF     = 5;\nconst int EDGE_PENALTY_AXIS  = 50;   // stronger penalty for axis rectangles\nconst int EDGE_PENALTY_ROT   = 30;   // weaker penalty for rotated squares\nconst int ROT_TYPE_BONUS     = 2000;\n\n// Candidate type\nconstexpr uint8_t TYPE_AXIS = 0;\nconstexpr uint8_t TYPE_ROT  = 1;\n\n// Candidate rectangle\nstruct Candidate {\n    int weight;      // heuristic score for priority_queue\n    uint8_t type;    // 0: axis-aligned, 1: 45\u00b0 square\n    uint8_t px, py;  // new dot position\n    uint8_t pad;     // unused / padding\n    union {\n        struct { uint8_t xL, yB, xR, yT; } axis;\n        struct {\n            uint8_t vx[4];  // vertices in cyclic order\n            uint8_t vy[4];\n        } rot;\n    } u;\n};\n\nbool operator<(const Candidate &a, const Candidate &b) {\n    // max-heap by heuristic score\n    return a.weight < b.weight;\n}\n\n// Two queues: rotated first phase, then axis+rot together\npriority_queue<Candidate> pqAxis;\npriority_queue<Candidate> pqRot;\n\n// Move record\nstruct Move {\n    int x1, y1, x2, y2, x3, y3, x4, y4;\n};\n\nvector<Move> moves;\n\n// =================== Basic Operations ===================\n\ninline void addDot(int x, int y) {\n    if (hasDot[x][y]) return;\n    hasDot[x][y] = true;\n    for (int i = x + 1; i <= N; ++i) rowPrefix[y][i] += 1;\n    for (int i = y + 1; i <= N; ++i) colPrefix[x][i] += 1;\n}\n\n// =================== Axis-aligned Rectangles ===================\n\n// Generate all axis-aligned rectangles where the newly added dot is a vertex\n// and exactly three corners have dots (so the fourth is a candidate new dot).\ninline void updateAxisForNewDot(int x, int y) {\n    for (int x2 = 0; x2 < N; ++x2) {\n        if (x2 == x) continue;\n        int xL = (x2 < x) ? x2 : x;\n        int xR = (x2 < x) ? x : x2;\n        for (int y2 = 0; y2 < N; ++y2) {\n            if (y2 == y) continue;\n            int yB = (y2 < y) ? y2 : y;\n            int yT = (y2 < y) ? y : y2;\n\n            bool BL = hasDot[xL][yB];\n            bool BR = hasDot[xR][yB];\n            bool TR = hasDot[xR][yT];\n            bool TL = hasDot[xL][yT];\n            int cnt = BL + BR + TR + TL;\n            if (cnt != 3) continue;\n\n            int px, py;\n            if (!BL) { px = xL; py = yB; }\n            else if (!BR) { px = xR; py = yB; }\n            else if (!TR) { px = xR; py = yT; }\n            else { px = xL; py = yT; }\n\n            int w_new = cellWeight[px][py];\n\n            int sumExisting = 0;\n            if (BL) sumExisting += cellWeight[xL][yB];\n            if (BR) sumExisting += cellWeight[xR][yB];\n            if (TR) sumExisting += cellWeight[xR][yT];\n            if (TL) sumExisting += cellWeight[xL][yT];\n\n            int width  = xR - xL;\n            int height = yT - yB;\n            int edges  = 2 * (width + height);\n\n            int score = w_new * W_NEW_COEF +\n                        sumExisting * SUM_EXIST_COEF -\n                        edges * EDGE_PENALTY_AXIS;\n\n            Candidate c;\n            c.weight = score;\n            c.type   = TYPE_AXIS;\n            c.px = (uint8_t)px;\n            c.py = (uint8_t)py;\n            c.pad = 0;\n            c.u.axis.xL = (uint8_t)xL;\n            c.u.axis.yB = (uint8_t)yB;\n            c.u.axis.xR = (uint8_t)xR;\n            c.u.axis.yT = (uint8_t)yT;\n            pqAxis.push(c);\n        }\n    }\n}\n\ninline bool validateAxis(const Candidate &c) {\n    int px = c.px, py = c.py;\n    if (hasDot[px][py]) return false;\n\n    const auto &ax = c.u.axis;\n    int xL = ax.xL, xR = ax.xR;\n    int yB = ax.yB, yT = ax.yT;\n\n    bool isCorner =\n        (px == xL && py == yB) ||\n        (px == xR && py == yB) ||\n        (px == xR && py == yT) ||\n        (px == xL && py == yT);\n    if (!isCorner) return false;\n\n    if (!(px == xL && py == yB) && !hasDot[xL][yB]) return false;\n    if (!(px == xR && py == yB) && !hasDot[xR][yB]) return false;\n    if (!(px == xR && py == yT) && !hasDot[xR][yT]) return false;\n    if (!(px == xL && py == yT) && !hasDot[xL][yT]) return false;\n\n    if (xR - xL > 1) {\n        int sumBottom = rowPrefix[yB][xR] - rowPrefix[yB][xL + 1];\n        if (sumBottom > 0) return false;\n        int sumTop = rowPrefix[yT][xR] - rowPrefix[yT][xL + 1];\n        if (sumTop > 0) return false;\n    }\n    if (yT - yB > 1) {\n        int sumLeft  = colPrefix[xL][yT] - colPrefix[xL][yB + 1];\n        if (sumLeft > 0) return false;\n        int sumRight = colPrefix[xR][yT] - colPrefix[xR][yB + 1];\n        if (sumRight > 0) return false;\n    }\n\n    for (int x = xL; x < xR; ++x) {\n        if (horUsed[yB][x]) return false;\n        if (horUsed[yT][x]) return false;\n    }\n    for (int y = yB; y < yT; ++y) {\n        if (verUsed[xL][y]) return false;\n        if (verUsed[xR][y]) return false;\n    }\n\n    return true;\n}\n\ninline void markEdgesAxis(const Candidate &c) {\n    const auto &ax = c.u.axis;\n    int xL = ax.xL, xR = ax.xR;\n    int yB = ax.yB, yT = ax.yT;\n    for (int x = xL; x < xR; ++x) {\n        horUsed[yB][x] = true;\n        horUsed[yT][x] = true;\n    }\n    for (int y = yB; y < yT; ++y) {\n        verUsed[xL][y] = true;\n        verUsed[xR][y] = true;\n    }\n}\n\n// =================== 45\u00b0 Rotated Squares (Diamonds) ===================\n\ninline void updateRotatedForNewDot(int x, int y) {\n    // Orientation 0: new dot is Up\n    {\n        for (int k = 1;; ++k) {\n            int rx = x + k;\n            int ry = y - k;\n            int dx = x;\n            int dy = y - 2 * k;\n            int lx = x - k;\n            int ly = y - k;\n            if (rx >= N || lx < 0 || dy < 0) break;\n\n            int vx[4] = {x,  rx, dx, lx};\n            int vy[4] = {y,  ry, dy, ly};\n            bool s[4];\n            s[0] = true;              // Up (new dot)\n            s[1] = hasDot[rx][ry];    // Right\n            s[2] = hasDot[dx][dy];    // Down\n            s[3] = hasDot[lx][ly];    // Left\n\n            int cnt = s[0] + s[1] + s[2] + s[3];\n            if (cnt != 3) continue;\n\n            int miss = -1;\n            for (int i = 0; i < 4; ++i) if (!s[i]) { miss = i; break; }\n            int px = vx[miss], py = vy[miss];\n            int w_new = cellWeight[px][py];\n\n            int sumExisting = 0;\n            for (int i = 0; i < 4; ++i)\n                if (s[i]) sumExisting += cellWeight[vx[i]][vy[i]];\n\n            int side = abs(vx[1] - vx[0]);\n            int edges = 4 * side;\n\n            int score = w_new * W_NEW_COEF +\n                        sumExisting * SUM_EXIST_COEF +\n                        ROT_TYPE_BONUS -\n                        edges * EDGE_PENALTY_ROT;\n\n            Candidate c;\n            c.weight = score;\n            c.type   = TYPE_ROT;\n            c.px = (uint8_t)px;\n            c.py = (uint8_t)py;\n            c.pad = 0;\n            for (int i = 0; i < 4; ++i) {\n                c.u.rot.vx[i] = (uint8_t)vx[i];\n                c.u.rot.vy[i] = (uint8_t)vy[i];\n            }\n            pqRot.push(c);\n        }\n    }\n\n    // Orientation 1: new dot is Right\n    {\n        for (int k = 1;; ++k) {\n            int ux = x - k;\n            int uy = y + k;\n            int dx = x - k;\n            int dy = y - k;\n            int lx = x - 2 * k;\n            int ly = y;\n            if (lx < 0 || ux < 0 || uy >= N || dy < 0) break;\n\n            int vx[4] = {ux, x,  dx, lx};\n            int vy[4] = {uy, y,  dy, ly};\n            bool s[4];\n            s[1] = true;              // Right (new dot)\n            s[0] = hasDot[ux][uy];    // Up\n            s[2] = hasDot[dx][dy];    // Down\n            s[3] = hasDot[lx][ly];    // Left\n\n            int cnt = s[0] + s[1] + s[2] + s[3];\n            if (cnt != 3) continue;\n\n            int miss = -1;\n            for (int i = 0; i < 4; ++i) if (!s[i]) { miss = i; break; }\n            int px = vx[miss], py = vy[miss];\n            int w_new = cellWeight[px][py];\n\n            int sumExisting = 0;\n            for (int i = 0; i < 4; ++i)\n                if (s[i]) sumExisting += cellWeight[vx[i]][vy[i]];\n\n            int side = abs(vx[1] - vx[0]);\n            int edges = 4 * side;\n\n            int score = w_new * W_NEW_COEF +\n                        sumExisting * SUM_EXIST_COEF +\n                        ROT_TYPE_BONUS -\n                        edges * EDGE_PENALTY_ROT;\n\n            Candidate c;\n            c.weight = score;\n            c.type   = TYPE_ROT;\n            c.px = (uint8_t)px;\n            c.py = (uint8_t)py;\n            c.pad = 0;\n            for (int i = 0; i < 4; ++i) {\n                c.u.rot.vx[i] = (uint8_t)vx[i];\n                c.u.rot.vy[i] = (uint8_t)vy[i];\n            }\n            pqRot.push(c);\n        }\n    }\n\n    // Orientation 2: new dot is Down\n    {\n        for (int k = 1;; ++k) {\n            int ux = x;\n            int uy = y + 2 * k;\n            int rx = x + k;\n            int ry = y + k;\n            int lx = x - k;\n            int ly = y + k;\n            if (uy >= N || rx >= N || lx < 0) break;\n\n            int vx[4] = {ux, rx, x,  lx};\n            int vy[4] = {uy, ry, y,  ly};\n            bool s[4];\n            s[2] = true;              // Down (new dot)\n            s[0] = hasDot[ux][uy];    // Up\n            s[1] = hasDot[rx][ry];    // Right\n            s[3] = hasDot[lx][ly];    // Left\n\n            int cnt = s[0] + s[1] + s[2] + s[3];\n            if (cnt != 3) continue;\n\n            int miss = -1;\n            for (int i = 0; i < 4; ++i) if (!s[i]) { miss = i; break; }\n            int px = vx[miss], py = vy[miss];\n            int w_new = cellWeight[px][py];\n\n            int sumExisting = 0;\n            for (int i = 0; i < 4; ++i)\n                if (s[i]) sumExisting += cellWeight[vx[i]][vy[i]];\n\n            int side = abs(vx[1] - vx[0]);\n            int edges = 4 * side;\n\n            int score = w_new * W_NEW_COEF +\n                        sumExisting * SUM_EXIST_COEF +\n                        ROT_TYPE_BONUS -\n                        edges * EDGE_PENALTY_ROT;\n\n            Candidate c;\n            c.weight = score;\n            c.type   = TYPE_ROT;\n            c.px = (uint8_t)px;\n            c.py = (uint8_t)py;\n            c.pad = 0;\n            for (int i = 0; i < 4; ++i) {\n                c.u.rot.vx[i] = (uint8_t)vx[i];\n                c.u.rot.vy[i] = (uint8_t)vy[i];\n            }\n            pqRot.push(c);\n        }\n    }\n\n    // Orientation 3: new dot is Left\n    {\n        for (int k = 1;; ++k) {\n            int ux = x + k;\n            int uy = y + k;\n            int rx = x + 2 * k;\n            int ry = y;\n            int dx = x + k;\n            int dy = y - k;\n            if (rx >= N || uy >= N || dy < 0) break;\n\n            int vx[4] = {ux, rx, dx, x};\n            int vy[4] = {uy, ry, dy, y};\n            bool s[4];\n            s[3] = true;              // Left (new dot)\n            s[0] = hasDot[ux][uy];    // Up\n            s[1] = hasDot[rx][ry];    // Right\n            s[2] = hasDot[dx][dy];    // Down\n\n            int cnt = s[0] + s[1] + s[2] + s[3];\n            if (cnt != 3) continue;\n\n            int miss = -1;\n            for (int i = 0; i < 4; ++i) if (!s[i]) { miss = i; break; }\n            int px = vx[miss], py = vy[miss];\n            int w_new = cellWeight[px][py];\n\n            int sumExisting = 0;\n            for (int i = 0; i < 4; ++i)\n                if (s[i]) sumExisting += cellWeight[vx[i]][vy[i]];\n\n            int side = abs(vx[1] - vx[0]);\n            int edges = 4 * side;\n\n            int score = w_new * W_NEW_COEF +\n                        sumExisting * SUM_EXIST_COEF +\n                        ROT_TYPE_BONUS -\n                        edges * EDGE_PENALTY_ROT;\n\n            Candidate c;\n            c.weight = score;\n            c.type   = TYPE_ROT;\n            c.px = (uint8_t)px;\n            c.py = (uint8_t)py;\n            c.pad = 0;\n            for (int i = 0; i < 4; ++i) {\n                c.u.rot.vx[i] = (uint8_t)vx[i];\n                c.u.rot.vy[i] = (uint8_t)vy[i];\n            }\n            pqRot.push(c);\n        }\n    }\n}\n\ninline bool validateRot(const Candidate &c) {\n    int px = c.px, py = c.py;\n    if (hasDot[px][py]) return false;\n\n    const auto &rt = c.u.rot;\n\n    int idx = -1;\n    for (int i = 0; i < 4; ++i) {\n        if (rt.vx[i] == px && rt.vy[i] == py) {\n            idx = i;\n            break;\n        }\n    }\n    if (idx == -1) return false;\n\n    for (int i = 0; i < 4; ++i) {\n        if (i == idx) continue;\n        int vx = rt.vx[i], vy = rt.vy[i];\n        if (!hasDot[vx][vy]) return false;\n    }\n\n    for (int e = 0; e < 4; ++e) {\n        int x1 = rt.vx[e];\n        int y1 = rt.vy[e];\n        int x2 = rt.vx[(e + 1) & 3];\n        int y2 = rt.vy[(e + 1) & 3];\n\n        int dx = x2 - x1;\n        int dy = y2 - y1;\n        int steps = abs(dx);\n        if (steps == 0) return false;\n\n        int sxStep = (dx > 0) ? 1 : -1;\n        int syStep = (dy > 0) ? 1 : -1;\n\n        for (int i = 1; i < steps; ++i) {\n            int qx = x1 + sxStep * i;\n            int qy = y1 + syStep * i;\n            if (hasDot[qx][qy]) return false;\n        }\n\n        bool slopeUp = ((long long)dx * dy > 0);\n        if (slopeUp) {\n            int sx = min(x1, x2);\n            int sy = min(y1, y2);\n            for (int i = 0; i < steps; ++i) {\n                if (diagUpUsed[sx + i][sy + i]) return false;\n            }\n        } else {\n            int sx = min(x1, x2);\n            int sy = max(y1, y2);\n            for (int i = 0; i < steps; ++i) {\n                int bx = sx + i;\n                int by = sy - 1 - i;\n                if (diagDownUsed[bx][by]) return false;\n            }\n        }\n    }\n\n    return true;\n}\n\ninline void markEdgesRot(const Candidate &c) {\n    const auto &rt = c.u.rot;\n    for (int e = 0; e < 4; ++e) {\n        int x1 = rt.vx[e];\n        int y1 = rt.vy[e];\n        int x2 = rt.vx[(e + 1) & 3];\n        int y2 = rt.vy[(e + 1) & 3];\n\n        int dx = x2 - x1;\n        int dy = y2 - y1;\n        int steps = abs(dx);\n        bool slopeUp = ((long long)dx * dy > 0);\n\n        if (slopeUp) {\n            int sx = min(x1, x2);\n            int sy = min(y1, y2);\n            for (int i = 0; i < steps; ++i) {\n                diagUpUsed[sx + i][sy + i] = true;\n            }\n        } else {\n            int sx = min(x1, x2);\n            int sy = max(y1, y2);\n            for (int i = 0; i < steps; ++i) {\n                int bx = sx + i;\n                int by = sy - 1 - i;\n                diagDownUsed[bx][by] = true;\n            }\n        }\n    }\n}\n\n// =================== Main ===================\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> M;\n    vector<pair<int,int>> initial(M);\n    for (int i = 0; i < M; ++i) {\n        int x, y;\n        cin >> x >> y;\n        initial[i] = {x, y};\n    }\n\n    // Precompute weights\n    int c = (N - 1) / 2;\n    for (int x = 0; x < N; ++x) {\n        for (int y = 0; y < N; ++y) {\n            int dx = x - c;\n            int dy = y - c;\n            cellWeight[x][y] = dx * dx + dy * dy + 1;\n        }\n    }\n\n    // Add initial dots and generate initial candidates\n    for (int i = 0; i < M; ++i) {\n        int x = initial[i].first;\n        int y = initial[i].second;\n        addDot(x, y);\n        updateAxisForNewDot(x, y);\n        updateRotatedForNewDot(x, y);\n    }\n\n    auto start_time = chrono::steady_clock::now();\n    const double TOTAL_TIME_LIMIT = 4.8;\n\n    // Dynamic rotated-phase ratio based on N: from ~0.45 at N=31 to ~0.60 at N=61\n    double baseRatio = 0.45;\n    double extra = 0.15 * (double)(N - 31) / 30.0; // N in [31,61]\n    if (extra < 0.0) extra = 0.0;\n    if (extra > 0.15) extra = 0.15;\n    double ROT_PHASE_RATIO = baseRatio + extra;\n    double ROT_PHASE_LIMIT  = TOTAL_TIME_LIMIT * ROT_PHASE_RATIO;\n\n    int iter = 0;\n\n    // Phase 1: use only rotated candidates\n    while (!pqRot.empty()) {\n        if ((iter & 0xFF) == 0) {\n            double elapsed = chrono::duration<double>(\n                                 chrono::steady_clock::now() - start_time\n                             ).count();\n            if (elapsed > ROT_PHASE_LIMIT) break;\n        }\n        ++iter;\n\n        Candidate cand = pqRot.top();\n        pqRot.pop();\n\n        if (!validateRot(cand)) continue;\n\n        markEdgesRot(cand);\n        int px = cand.px;\n        int py = cand.py;\n        addDot(px, py);\n        updateAxisForNewDot(px, py);\n        updateRotatedForNewDot(px, py);\n\n        const auto &rt = cand.u.rot;\n        int idx = 0;\n        for (; idx < 4; ++idx) {\n            if (rt.vx[idx] == px && rt.vy[idx] == py) break;\n        }\n        if (idx == 4) idx = 0;\n\n        int x1 = rt.vx[idx],           y1 = rt.vy[idx];\n        int x2 = rt.vx[(idx + 1) & 3], y2 = rt.vy[(idx + 1) & 3];\n        int x3 = rt.vx[(idx + 2) & 3], y3 = rt.vy[(idx + 2) & 3];\n        int x4 = rt.vx[(idx + 3) & 3], y4 = rt.vy[(idx + 3) & 3];\n        moves.push_back({x1, y1, x2, y2, x3, y3, x4, y4});\n    }\n\n    // Phase 2: both rotated and axis candidates, choose best by score\n    while (!pqRot.empty() || !pqAxis.empty()) {\n        if ((iter & 0xFF) == 0) {\n            double elapsed = chrono::duration<double>(\n                                 chrono::steady_clock::now() - start_time\n                             ).count();\n            if (elapsed > TOTAL_TIME_LIMIT) break;\n        }\n        ++iter;\n\n        bool chooseRot;\n        if (pqRot.empty()) chooseRot = false;\n        else if (pqAxis.empty()) chooseRot = true;\n        else chooseRot = (pqRot.top().weight >= pqAxis.top().weight);\n\n        Candidate cand = chooseRot ? pqRot.top() : pqAxis.top();\n        if (chooseRot) pqRot.pop(); else pqAxis.pop();\n\n        if (cand.type == TYPE_AXIS) {\n            if (!validateAxis(cand)) continue;\n\n            markEdgesAxis(cand);\n            int px = cand.px;\n            int py = cand.py;\n            addDot(px, py);\n            updateAxisForNewDot(px, py);\n            updateRotatedForNewDot(px, py);\n\n            const auto &ax = cand.u.axis;\n            int xL = ax.xL, xR = ax.xR;\n            int yB = ax.yB, yT = ax.yT;\n\n            int ax0 = xL, ay0 = yB;\n            int bx0 = xR, by0 = yB;\n            int cx0 = xR, cy0 = yT;\n            int dx0 = xL, dy0 = yT;\n\n            Move m;\n            if      (px == ax0 && py == ay0) m = {ax0, ay0, bx0, by0, cx0, cy0, dx0, dy0};\n            else if (px == bx0 && py == by0) m = {bx0, by0, cx0, cy0, dx0, dy0, ax0, ay0};\n            else if (px == cx0 && py == cy0) m = {cx0, cy0, dx0, dy0, ax0, ay0, bx0, by0};\n            else                             m = {dx0, dy0, ax0, ay0, bx0, by0, cx0, cy0};\n            moves.push_back(m);\n\n        } else { // TYPE_ROT\n            if (!validateRot(cand)) continue;\n\n            markEdgesRot(cand);\n            int px = cand.px;\n            int py = cand.py;\n            addDot(px, py);\n            updateAxisForNewDot(px, py);\n            updateRotatedForNewDot(px, py);\n\n            const auto &rt = cand.u.rot;\n            int idx = 0;\n            for (; idx < 4; ++idx) {\n                if (rt.vx[idx] == px && rt.vy[idx] == py) break;\n            }\n            if (idx == 4) idx = 0;\n\n            int x1 = rt.vx[idx],           y1 = rt.vy[idx];\n            int x2 = rt.vx[(idx + 1) & 3], y2 = rt.vy[(idx + 1) & 3];\n            int x3 = rt.vx[(idx + 2) & 3], y3 = rt.vy[(idx + 2) & 3];\n            int x4 = rt.vx[(idx + 3) & 3], y4 = rt.vy[(idx + 3) & 3];\n            moves.push_back({x1, y1, x2, y2, x3, y3, x4, y4});\n        }\n    }\n\n    cout << moves.size() << '\\n';\n    for (const auto &m : moves) {\n        cout << m.x1 << ' ' << m.y1 << ' '\n             << m.x2 << ' ' << m.y2 << ' '\n             << m.x3 << ' ' << m.y3 << ' '\n             << m.x4 << ' ' << m.y4 << '\\n';\n    }\n\n    return 0;\n}","ahc015":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const int N = 10;\n\n// Monte Carlo samples (tuned from previously good settings)\nstatic const int K0 = 2;  // 3-step lookahead (very early)\nstatic const int K1 = 3;  // 2-step lookahead (early/mid)\nstatic const int K2 = 4;  // 1-step lookahead (late)\nstatic const int ENUM_LIMIT_1 = 16; // exact 1-step enumeration when empties <= this\n\nstruct Board {\n    uint8_t a[N][N];\n    Board() { memset(a, 0, sizeof(a)); }\n};\n\n// Tilt directions: 0 = F, 1 = B, 2 = L, 3 = R\nvoid tilt(Board &b, int dir) {\n    if (dir == 0) { // F: move toward row 0\n        for (int c = 0; c < N; c++) {\n            int pos = 0;\n            for (int r = 0; r < N; r++) {\n                uint8_t v = b.a[r][c];\n                if (v) {\n                    if (pos != r) b.a[pos][c] = v;\n                    pos++;\n                }\n            }\n            for (int r = pos; r < N; r++) b.a[r][c] = 0;\n        }\n    } else if (dir == 1) { // B: move toward row 9\n        for (int c = 0; c < N; c++) {\n            int pos = N - 1;\n            for (int r = N - 1; r >= 0; r--) {\n                uint8_t v = b.a[r][c];\n                if (v) {\n                    if (pos != r) b.a[pos][c] = v;\n                    pos--;\n                }\n            }\n            for (int r = pos; r >= 0; r--) b.a[r][c] = 0;\n        }\n    } else if (dir == 2) { // L: move toward col 0\n        for (int r = 0; r < N; r++) {\n            int pos = 0;\n            for (int c = 0; c < N; c++) {\n                uint8_t v = b.a[r][c];\n                if (v) {\n                    if (pos != c) b.a[r][pos] = v;\n                    pos++;\n                }\n            }\n            for (int c = pos; c < N; c++) b.a[r][c] = 0;\n        }\n    } else { // R: move toward col 9\n        for (int r = 0; r < N; r++) {\n            int pos = N - 1;\n            for (int c = N - 1; c >= 0; c--) {\n                uint8_t v = b.a[r][c];\n                if (v) {\n                    if (pos != c) b.a[r][pos] = v;\n                    pos--;\n                }\n            }\n            for (int c = pos; c >= 0; c--) b.a[r][c] = 0;\n        }\n    }\n}\n\n// Sum of squared sizes of same-color connected components (4-neighbor)\nlong long evaluate(const Board &b) {\n    static uint32_t vis[N][N];\n    static uint32_t curMark = 1;\n    curMark++;\n\n    static const int dr[4] = {1, -1, 0, 0};\n    static const int dc[4] = {0, 0, 1, -1};\n    int qx[100], qy[100];\n    long long score = 0;\n\n    for (int r = 0; r < N; r++) {\n        for (int c = 0; c < N; c++) {\n            uint8_t color = b.a[r][c];\n            if (color != 0 && vis[r][c] != curMark) {\n                int head = 0, tail = 0;\n                qx[tail] = r;\n                qy[tail] = c;\n                tail++;\n                vis[r][c] = curMark;\n                int cnt = 0;\n\n                while (head < tail) {\n                    int x = qx[head];\n                    int y = qy[head];\n                    head++;\n                    cnt++;\n\n                    for (int k = 0; k < 4; k++) {\n                        int nx = x + dr[k];\n                        int ny = y + dc[k];\n                        if (0 <= nx && nx < N && 0 <= ny && ny < N) {\n                            if (b.a[nx][ny] == color && vis[nx][ny] != curMark) {\n                                vis[nx][ny] = curMark;\n                                qx[tail] = nx;\n                                qy[tail] = ny;\n                                tail++;\n                            }\n                        }\n                    }\n                }\n                score += 1LL * cnt * cnt;\n            }\n        }\n    }\n    return score;\n}\n\n// Spatial bias: distance of each color to its target corner\n// color 1 -> (0,0), color 2 -> (0,9), color 3 -> (9,0)\nint corner_distance(const Board &b) {\n    static const int tr[4] = {0, 0, 0, 9};\n    static const int tc[4] = {0, 0, 9, 0};\n    int dist = 0;\n    for (int r = 0; r < N; r++) {\n        for (int c = 0; c < N; c++) {\n            uint8_t col = b.a[r][c];\n            if (col >= 1 && col <= 3) {\n                dist += abs(r - tr[col]) + abs(c - tc[col]);\n            }\n        }\n    }\n    return dist;\n}\n\n// Count empty cells\nint countEmpty(const Board &b) {\n    int cnt = 0;\n    for (int r = 0; r < N; r++)\n        for (int c = 0; c < N; c++)\n            if (b.a[r][c] == 0) cnt++;\n    return cnt;\n}\n\n// Find p-th empty cell (1-based) in front-to-back, left-to-right order\npair<int,int> findPos(const Board &b, int p) {\n    int cnt = 0;\n    for (int r = 0; r < N; r++) {\n        for (int c = 0; c < N; c++) {\n            if (b.a[r][c] == 0) {\n                cnt++;\n                if (cnt == p) return {r, c};\n            }\n        }\n    }\n    return {-1, -1}; // should not happen\n}\n\n// Choose a random empty cell uniformly from current board\npair<int,int> randomEmptyCell(const Board &b, mt19937_64 &rng) {\n    int empties = 0;\n    for (int r = 0; r < N; r++) {\n        for (int c = 0; c < N; c++) {\n            if (b.a[r][c] == 0) empties++;\n        }\n    }\n    uint64_t x = rng();\n    int k = (int)(x % empties); // 0..empties-1\n    int cnt = 0;\n    for (int r = 0; r < N; r++) {\n        for (int c = 0; c < N; c++) {\n            if (b.a[r][c] == 0) {\n                if (cnt == k) return {r, c};\n                cnt++;\n            }\n        }\n    }\n    return {0, 0}; // fallback, should not occur\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // Read flavor sequence\n    vector<int> f(100);\n    for (int i = 0; i < 100; i++) {\n        if (!(cin >> f[i])) return 0;\n    }\n\n    Board cur;\n    const char DIR_CH[4] = {'F', 'B', 'L', 'R'};\n    mt19937_64 rng(712367821ull); // fixed seed for deterministic behavior\n\n    for (int t = 0; t < 100; t++) {\n        int p;\n        if (!(cin >> p)) return 0;\n\n        // Place current candy\n        auto [r, c] = findPos(cur, p);\n        if (r == -1) return 0;\n        cur.a[r][c] = (uint8_t)f[t];\n\n        long long bestEval = LLONG_MIN;\n        int bestDir = 0;\n        Board bestBoard;\n\n        int remain = 99 - t; // number of future candies after this step\n\n        if (remain >= 3 && t <= 25) {\n            // Very early game: 3-step lookahead with K0 samples\n            for (int dir0 = 0; dir0 < 4; dir0++) {\n                Board b1 = cur;\n                tilt(b1, dir0);\n                long long S0 = evaluate(b1);\n                int dist0 = corner_distance(b1);\n                long long sum1 = 0, sum2 = 0, sum3 = 0;\n\n                for (int s = 0; s < K0; s++) {\n                    // Step t+1\n                    Board sim1 = b1;\n                    auto [r1, c1] = randomEmptyCell(sim1, rng);\n                    sim1.a[r1][c1] = (uint8_t)f[t + 1];\n\n                    long long best1 = LLONG_MIN;\n                    Board b2best;\n                    for (int dir1 = 0; dir1 < 4; dir1++) {\n                        Board b2 = sim1;\n                        tilt(b2, dir1);\n                        long long sc1 = evaluate(b2);\n                        if (sc1 > best1) {\n                            best1 = sc1;\n                            b2best = b2;\n                        }\n                    }\n                    sum1 += best1;\n\n                    // Step t+2\n                    Board sim2 = b2best;\n                    auto [r2, c2] = randomEmptyCell(sim2, rng);\n                    sim2.a[r2][c2] = (uint8_t)f[t + 2];\n\n                    long long best2 = LLONG_MIN;\n                    Board b3best;\n                    for (int dir2 = 0; dir2 < 4; dir2++) {\n                        Board b3 = sim2;\n                        tilt(b3, dir2);\n                        long long sc2 = evaluate(b3);\n                        if (sc2 > best2) {\n                            best2 = sc2;\n                            b3best = b3;\n                        }\n                    }\n                    sum2 += best2;\n\n                    // Step t+3\n                    Board sim3 = b3best;\n                    auto [r3, c3] = randomEmptyCell(sim3, rng);\n                    sim3.a[r3][c3] = (uint8_t)f[t + 3];\n\n                    long long best3 = LLONG_MIN;\n                    for (int dir3 = 0; dir3 < 4; dir3++) {\n                        Board b4 = sim3;\n                        tilt(b4, dir3);\n                        long long sc3 = evaluate(b4);\n                        if (sc3 > best3) {\n                            best3 = sc3;\n                        }\n                    }\n                    sum3 += best3;\n                }\n\n                long long scoreValue = S0 * K0 + sum1 + sum2 + sum3;\n                // soft corner bias: small penalty by distance\n                long long evalScore = scoreValue * 100 - dist0;\n\n                if (evalScore > bestEval) {\n                    bestEval = evalScore;\n                    bestDir = dir0;\n                    bestBoard = b1;\n                }\n            }\n        } else if (remain >= 2 && t <= 60) {\n            // Early/mid game: 2-step lookahead with K1 samples\n            for (int dir0 = 0; dir0 < 4; dir0++) {\n                Board b1 = cur;\n                tilt(b1, dir0);\n                long long S0 = evaluate(b1);\n                int dist0 = corner_distance(b1);\n                long long sum1 = 0, sum2 = 0;\n\n                for (int s = 0; s < K1; s++) {\n                    // Step t+1\n                    Board sim1 = b1;\n                    auto [r1, c1] = randomEmptyCell(sim1, rng);\n                    sim1.a[r1][c1] = (uint8_t)f[t + 1];\n\n                    long long best1 = LLONG_MIN;\n                    Board b2best;\n                    for (int dir1 = 0; dir1 < 4; dir1++) {\n                        Board b2 = sim1;\n                        tilt(b2, dir1);\n                        long long sc1 = evaluate(b2);\n                        if (sc1 > best1) {\n                            best1 = sc1;\n                            b2best = b2;\n                        }\n                    }\n                    sum1 += best1;\n\n                    // Step t+2\n                    Board sim2 = b2best;\n                    auto [r2, c2] = randomEmptyCell(sim2, rng);\n                    sim2.a[r2][c2] = (uint8_t)f[t + 2];\n\n                    long long best2 = LLONG_MIN;\n                    for (int dir2 = 0; dir2 < 4; dir2++) {\n                        Board b3 = sim2;\n                        tilt(b3, dir2);\n                        long long sc2 = evaluate(b3);\n                        if (sc2 > best2) {\n                            best2 = sc2;\n                        }\n                    }\n                    sum2 += best2;\n                }\n\n                long long scoreValue = S0 * K1 + sum1 + sum2;\n                long long evalScore = scoreValue * 100 - dist0;\n\n                if (evalScore > bestEval) {\n                    bestEval = evalScore;\n                    bestDir = dir0;\n                    bestBoard = b1;\n                }\n            }\n        } else if (remain >= 1) {\n            // Late game: 1-step lookahead (exact expectation when empties small)\n            for (int dir0 = 0; dir0 < 4; dir0++) {\n                Board b1 = cur;\n                tilt(b1, dir0);\n                long long S0 = evaluate(b1);\n                int dist0 = corner_distance(b1);\n\n                int empties1 = countEmpty(b1);\n                long long scoreValue;\n                if (empties1 <= ENUM_LIMIT_1) {\n                    // Exact expectation over all possible placements of next candy\n                    long long sum1 = 0;\n                    for (int rr = 0; rr < N; rr++) {\n                        for (int cc = 0; cc < N; cc++) {\n                            if (b1.a[rr][cc] == 0) {\n                                Board sim1 = b1;\n                                sim1.a[rr][cc] = (uint8_t)f[t + 1];\n                                long long best1 = LLONG_MIN;\n                                for (int dir1 = 0; dir1 < 4; dir1++) {\n                                    Board b2 = sim1;\n                                    tilt(b2, dir1);\n                                    long long sc1 = evaluate(b2);\n                                    if (sc1 > best1) best1 = sc1;\n                                }\n                                sum1 += best1;\n                            }\n                        }\n                    }\n                    scoreValue = S0 * empties1 + sum1;\n                } else {\n                    // Monte Carlo approximation\n                    long long sum1 = 0;\n                    for (int s = 0; s < K2; s++) {\n                        Board sim1 = b1;\n                        auto [r1, c1] = randomEmptyCell(sim1, rng);\n                        sim1.a[r1][c1] = (uint8_t)f[t + 1];\n\n                        long long best1 = LLONG_MIN;\n                        for (int dir1 = 0; dir1 < 4; dir1++) {\n                            Board b2 = sim1;\n                            tilt(b2, dir1);\n                            long long sc1 = evaluate(b2);\n                            if (sc1 > best1) {\n                                best1 = sc1;\n                            }\n                        }\n                        sum1 += best1;\n                    }\n                    scoreValue = S0 * K2 + sum1;\n                }\n\n                long long evalScore = scoreValue * 100 - dist0;\n\n                if (evalScore > bestEval) {\n                    bestEval = evalScore;\n                    bestDir = dir0;\n                    bestBoard = b1;\n                }\n            }\n        } else {\n            // Last step: no future candies; only immediate score matters\n            for (int dir0 = 0; dir0 < 4; dir0++) {\n                Board b1 = cur;\n                tilt(b1, dir0);\n                long long S0 = evaluate(b1);\n                int dist0 = corner_distance(b1);\n                long long scoreValue = S0;\n                long long evalScore = scoreValue * 100 - dist0;\n\n                if (evalScore > bestEval) {\n                    bestEval = evalScore;\n                    bestDir = dir0;\n                    bestBoard = b1;\n                }\n            }\n        }\n\n        cur = bestBoard;\n        cout << DIR_CH[bestDir] << '\\n' << flush;\n    }\n\n    return 0;\n}","ahc016":"#include <bits/stdc++.h>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int M;\n    double eps;\n    if (!(cin >> M >> eps)) return 0;\n\n    bool noNoise = (eps < 0.0005);  // eps is multiple of 0.01, so this is effectively eps == 0\n\n    int N = 4;\n    int L = 0;\n\n    if (noNoise) {\n        // eps = 0: choose minimum N such that L >= M\n        while (N < 100) {\n            L = N * (N - 1) / 2;\n            if (L >= M) break;\n            ++N;\n        }\n        L = N * (N - 1) / 2;\n    } else {\n        // eps > 0: choose N using linear + SNR-based constraints\n        const double baseC0 = 6.0;\n        const double baseC1 = 60.0;\n        double L1 = (baseC0 + baseC1 * eps) * M;\n\n        // SNR-based constraint: require separation r0 in units of sigma\n        const double r0 = 4.0;\n        double den = 1.0 - 2.0 * eps;\n        den *= den;\n        double L2;\n        if (den < 1e-12) {\n            // For eps extremely close to 0.5 (not in given constraints), just force max L\n            L2 = 1e18;\n        } else {\n            double alpha2 = (r0 * r0 * eps * (1.0 - eps)) / den;\n            L2 = alpha2 * (M + 1.0) * (M + 1.0);\n        }\n\n        double targetL = max(L1, L2);\n        // Need at least M+1 distinct total edge counts\n        if (targetL < M + 1.0) targetL = M + 1.0;\n        // Cap by maximum possible L (N <= 100)\n        if (targetL > 4950.0) targetL = 4950.0;\n\n        N = 4;\n        while (N < 100) {\n            L = N * (N - 1) / 2;\n            if ((double)L >= targetL) break;\n            ++N;\n        }\n        L = N * (N - 1) / 2;\n    }\n\n    // Decide edge counts m_k\n    vector<int> mEdges(M);\n\n    if (noNoise) {\n        // eps = 0: simply use m_k = k (0..M-1), since L >= M\n        for (int k = 0; k < M; ++k) {\n            mEdges[k] = k;\n        }\n    } else {\n        // eps > 0: spread m_k approximately evenly across 1..L-1\n        for (int k = 0; k < M; ++k) {\n            long long num = 1LL * (k + 1) * L;\n            int mk = (int)(num / (M + 1));  // floor\n            if (mk <= 0) mk = 1;\n            if (mk >= L) mk = L - 1;\n            mEdges[k] = mk;\n        }\n        // Ensure strictly increasing in [1, L-1]\n        if (mEdges[0] <= 0) mEdges[0] = 1;\n        for (int k = 1; k < M; ++k) {\n            if (mEdges[k] <= mEdges[k - 1]) {\n                mEdges[k] = mEdges[k - 1] + 1;\n                if (mEdges[k] >= L) mEdges[k] = L - 1;\n            }\n        }\n    }\n\n    // Precompute mapping from edge index (0..L-1) to (u,v)\n    vector<int> edgeU(L), edgeV(L);\n    {\n        int pos = 0;\n        for (int i = 0; i < N; ++i) {\n            for (int j = i + 1; j < N; ++j) {\n                edgeU[pos] = i;\n                edgeV[pos] = j;\n                ++pos;\n            }\n        }\n    }\n\n    // Precompute expected noisy edge counts for eps > 0\n    vector<double> muEdges;\n    double a = 1.0 - 2.0 * eps;\n    double b = eps * L;\n    if (!noNoise) {\n        muEdges.resize(M);\n        for (int k = 0; k < M; ++k) {\n            muEdges[k] = a * (double)mEdges[k] + b;\n        }\n    }\n\n    // For eps > 0, also precompute expected sorted degree sequences for each G_k\n    vector<vector<double>> muDegSorted;  // size M x N\n    if (!noNoise) {\n        muDegSorted.assign(M, vector<double>(N));\n        vector<int> deg(N);\n        vector<int> idx(N);\n        double shiftDeg = eps * (N - 1);\n        for (int k = 0; k < M; ++k) {\n            // Build degree sequence for graph G_k with \"first mEdges[k] bits = 1\"\n            fill(deg.begin(), deg.end(), 0);\n            int mk = mEdges[k];\n            for (int pos = 0; pos < mk; ++pos) {\n                int u = edgeU[pos];\n                int v = edgeV[pos];\n                ++deg[u];\n                ++deg[v];\n            }\n            // Sort vertices by degree\n            iota(idx.begin(), idx.end(), 0);\n            sort(idx.begin(), idx.end(), [&](int u, int v) {\n                if (deg[u] != deg[v]) return deg[u] < deg[v];\n                return u < v;\n            });\n            // Store expected degrees after noise in sorted order\n            for (int r = 0; r < N; ++r) {\n                int v = idx[r];\n                muDegSorted[k][r] = a * (double)deg[v] + shiftDeg;\n            }\n        }\n    }\n\n    // Output N and graphs as bitstrings of length L\n    cout << N << '\\n';\n    for (int k = 0; k < M; ++k) {\n        int mk = mEdges[k];\n        string s(L, '0');\n        for (int i = 0; i < mk; ++i) s[i] = '1';\n        cout << s << '\\n';\n    }\n    cout.flush();\n\n    // If eps = 0, build direct map from edge count to index and answer queries via edges only\n    if (noNoise) {\n        vector<int> edgeToIndex(L + 1, -1);\n        for (int k = 0; k < M; ++k) {\n            int mk = mEdges[k];\n            if (0 <= mk && mk <= L) edgeToIndex[mk] = k;\n        }\n\n        for (int q = 0; q < 100; ++q) {\n            string H;\n            if (!(cin >> H)) return 0;\n\n            int mPrime = 0;\n            for (char c : H) if (c == '1') ++mPrime;\n\n            int bestK = 0;\n            if (mPrime >= 0 && mPrime <= L && edgeToIndex[mPrime] != -1) {\n                bestK = edgeToIndex[mPrime];\n            } else {\n                // Very unlikely fallback: choose nearest in mEdges\n                int bestDiff = INT_MAX;\n                for (int k = 0; k < M; ++k) {\n                    int diff = abs(mPrime - mEdges[k]);\n                    if (diff < bestDiff) {\n                        bestDiff = diff;\n                        bestK = k;\n                    }\n                }\n            }\n\n            cout << bestK << '\\n';\n            cout.flush();\n        }\n        return 0;\n    }\n\n    // eps > 0: prepare degree-related constants\n    double var_m = (double)L * eps * (1.0 - eps);\n    double sigma_m = sqrt(max(var_m, 1e-9));\n    double var_deg = (double)(N - 1) * eps * (1.0 - eps);\n    double sigma_deg = sqrt(max(var_deg, 1e-9));\n\n    // Degree-term weight and edge-gap threshold:\n    // use degree info only when edge-based evidence is ambiguous\n    const double lambda_deg = 0.08;\n    const double EDGE_GAP_THRESH = 6.0;  // if secondBest - best > this, ignore degree term\n\n    // Buffers for queries\n    vector<int> degH(N), idxH(N), degSortedH(N);\n    vector<double> costE(M);\n\n    // Process 100 queries\n    for (int q = 0; q < 100; ++q) {\n        string H;\n        if (!(cin >> H)) return 0;\n\n        int mPrime = 0;\n        fill(degH.begin(), degH.end(), 0);\n\n        // Count edges and compute degrees in H\n        for (int pos = 0; pos < L; ++pos) {\n            if (H[pos] == '1') {\n                ++mPrime;\n                int u = edgeU[pos];\n                int v = edgeV[pos];\n                ++degH[u];\n                ++degH[v];\n            }\n        }\n\n        // Sorted degrees in H\n        iota(idxH.begin(), idxH.end(), 0);\n        sort(idxH.begin(), idxH.end(), [&](int u, int v) {\n            if (degH[u] != degH[v]) return degH[u] < degH[v];\n            return u < v;\n        });\n        for (int r = 0; r < N; ++r) {\n            degSortedH[r] = degH[idxH[r]];\n        }\n\n        // Edge-only costs and best / second-best by edge evidence\n        int bestK_edge = 0, secondK_edge = -1;\n        double bestCostE = 1e300, secondCostE = 1e300;\n        for (int k = 0; k < M; ++k) {\n            double deltaE = ((double)mPrime - muEdges[k]) / sigma_m;\n            double cE = deltaE * deltaE;\n            costE[k] = cE;\n            if (cE < bestCostE) {\n                secondCostE = bestCostE;\n                secondK_edge = bestK_edge;\n                bestCostE = cE;\n                bestK_edge = k;\n            } else if (cE < secondCostE) {\n                secondCostE = cE;\n                secondK_edge = k;\n            }\n        }\n\n        double edgeGap = secondCostE - bestCostE;\n        if (edgeGap > EDGE_GAP_THRESH) {\n            // Edge evidence is strong; ignore degree term\n            cout << bestK_edge << '\\n';\n            cout.flush();\n            continue;\n        }\n\n        // Otherwise, ambiguous by edge count: refine using degree distributions\n        int bestK = 0;\n        double bestCost = 1e300;\n        for (int k = 0; k < M; ++k) {\n            // Start from edge-only cost\n            double cost = costE[k];\n\n            // Degree distribution contribution (sorted degree sequences)\n            const vector<double> &muDeg = muDegSorted[k];\n            double sumZ2 = 0.0;\n            for (int r = 0; r < N; ++r) {\n                double z = ((double)degSortedH[r] - muDeg[r]) / sigma_deg;\n                sumZ2 += z * z;\n            }\n            cost += lambda_deg * (sumZ2 / (double)N);\n\n            if (cost < bestCost) {\n                bestCost = cost;\n                bestK = k;\n            }\n        }\n\n        cout << bestK << '\\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 id;\n    int w;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, D, K;\n    if (!(cin >> N >> M >> D >> K)) return 0;\n\n    vector<int> U(M), V(M), W(M);\n    for (int i = 0; i < M; i++) {\n        cin >> U[i] >> V[i] >> W[i];\n        --U[i];\n        --V[i];\n    }\n    // Coordinates (unused)\n    for (int i = 0; i < N; i++) {\n        int x, y;\n        cin >> x >> y;\n    }\n\n    // Build adjacency list\n    vector<vector<AdjEdge>> g(N);\n    for (int i = 0; i < M; i++) {\n        int u = U[i], v = V[i], w = W[i];\n        g[u].push_back({v, i, w});\n        g[v].push_back({u, i, w});\n    }\n\n    mt19937_64 rng(123456789);\n\n    // ---------------------- Step 1: Betweenness-like centrality -------------------------\n    int S_c = min(N, 80); // sampled sources for centrality\n    vector<int> perm(N);\n    iota(perm.begin(), perm.end(), 0);\n    shuffle(perm.begin(), perm.end(), rng);\n    vector<int> sources_c(S_c);\n    for (int i = 0; i < S_c; i++) sources_c[i] = perm[i];\n\n    vector<double> central(M, 0.0);\n\n    const long long INFLL = (1LL << 60);\n    vector<long long> distLL(N);\n    vector<int> parent_v(N), parent_e(N);\n    vector<int> order;\n    order.reserve(N);\n\n    using PQItem = pair<long long,int>;\n\n    for (int s : sources_c) {\n        fill(distLL.begin(), distLL.end(), INFLL);\n        fill(parent_v.begin(), parent_v.end(), -1);\n        fill(parent_e.begin(), parent_e.end(), -1);\n        order.clear();\n\n        priority_queue<PQItem, vector<PQItem>, greater<PQItem>> pq;\n        distLL[s] = 0;\n        pq.emplace(0, s);\n\n        while (!pq.empty()) {\n            auto [d, v] = pq.top();\n            pq.pop();\n            if (d != distLL[v]) continue;\n            order.push_back(v);\n            for (const auto &e : g[v]) {\n                int to = e.to;\n                long long nd = d + e.w;\n                if (nd < distLL[to]) {\n                    distLL[to] = nd;\n                    parent_v[to] = v;\n                    parent_e[to] = e.id;\n                    pq.emplace(nd, to);\n                }\n            }\n        }\n\n        // Tree DP to accumulate centrality\n        vector<int> sz(N, 1);\n        for (int i = (int)order.size() - 1; i >= 0; --i) {\n            int v = order[i];\n            int pv = parent_v[v];\n            if (pv == -1) continue;\n            int eid = parent_e[v];\n            central[eid] += sz[v];\n            sz[pv] += sz[v];\n        }\n    }\n\n    // ---------------------- Step 2: Alternative-path detour per edge ---------------------\n    vector<long long> altDiff(M, 1); // altDist - W[e], at least 1\n    const long long INF_COST = 1000000000LL;\n\n    for (int eid = 0; eid < M; eid++) {\n        int src = U[eid];\n        int tgt = V[eid];\n\n        fill(distLL.begin(), distLL.end(), INF_COST);\n        priority_queue<PQItem, vector<PQItem>, greater<PQItem>> pq;\n        distLL[src] = 0;\n        pq.emplace(0, src);\n\n        while (!pq.empty()) {\n            auto [d, v] = pq.top();\n            pq.pop();\n            if (d != distLL[v]) continue;\n            if (v == tgt) break; // reached target with minimal distance\n            for (const auto &ed : g[v]) {\n                if (ed.id == eid) continue; // skip this edge in both directions\n                int to = ed.to;\n                long long nd = d + ed.w;\n                if (nd < distLL[to]) {\n                    distLL[to] = nd;\n                    pq.emplace(nd, to);\n                }\n            }\n        }\n\n        long long alt = distLL[tgt];\n        if (alt >= INF_COST) alt = INF_COST; // should not happen due to 2-edge-connectivity\n        long long delta = alt - (long long)W[eid];\n        if (delta < 1) delta = 1;\n        altDiff[eid] = delta;\n    }\n\n    // ---------------------- Step 3: Edge importance modes & normalization ---------------\n    const int MODES = 3;\n    vector<vector<double>> weightModes(MODES, vector<double>(M));\n\n    vector<double> imp0(M), imp1(M), imp2(M);\n    double max0 = 0.0, max1 = 0.0, max2 = 0.0;\n\n    for (int i = 0; i < M; i++) {\n        double cen  = central[i] + 1.0;\n        double wlen = (double)W[i];\n        double ad   = (double)altDiff[i];\n\n        // Mode 0: central * edge length\n        imp0[i] = cen * wlen;\n        // Mode 1: central * alternative detour\n        imp1[i] = cen * ad;\n        // Mode 2: hybrid: central * (0.5*wlen + 0.5*min(ad, 5*wlen))\n        double ad_lim = min(ad, wlen * 5.0);\n        imp2[i] = cen * (0.5 * wlen + 0.5 * ad_lim);\n\n        max0 = max(max0, imp0[i]);\n        max1 = max(max1, imp1[i]);\n        max2 = max(max2, imp2[i]);\n    }\n\n    auto normScale = [](double mx) {\n        return (mx > 0.0 ? mx / 1000.0 : 1.0);\n    };\n    double sc0 = normScale(max0);\n    double sc1 = normScale(max1);\n    double sc2 = normScale(max2);\n\n    for (int i = 0; i < M; i++) {\n        weightModes[0][i] = imp0[i] / sc0;\n        weightModes[1][i] = imp1[i] / sc1;\n        weightModes[2][i] = imp2[i] / sc2;\n    }\n\n    // ---------------------- Step 4: Capacities per day ----------------------------------\n    vector<int> cap(D);\n    int base = M / D;\n    int rem = M % D;\n    for (int d = 0; d < D; d++) {\n        cap[d] = base + (d < rem ? 1 : 0);\n        // cap[d] <= ceil(M/D) <= K guaranteed\n    }\n\n    // ---------------------- Step 5: Schedule builder (greedy + local search) -----------\n    auto buildSchedule = [&](const vector<double> &weight) -> vector<int> {\n        vector<int> day_cnt(D, 0);\n        vector<double> day_sum(D, 0.0);\n        // vds[v][d] = sum of weights of edges incident to vertex v on day d\n        vector<vector<double>> vds(N, vector<double>(D, 0.0));\n        // vdc[v][d] = count of edges incident to v on day d\n        vector<vector<uint8_t>> vdc(N, vector<uint8_t>(D, 0));\n\n        vector<int> r(M, -1);\n\n        // Initial greedy assignment\n        vector<int> ids(M);\n        iota(ids.begin(), ids.end(), 0);\n        sort(ids.begin(), ids.end(), [&](int a, int b) {\n            return weight[a] > weight[b];\n        });\n\n        const double INIT_ALPHA_W = 6.0; // weight-based concurrency\n        const double INIT_ALPHA_C = 2.0; // count-based concurrency\n        const double INIT_BETA    = 1.0; // day-level balance\n\n        for (int idx = 0; idx < M; idx++) {\n            int e = ids[idx];\n            int u = U[e], v = V[e];\n\n            int bestD = -1;\n            double bestScore = 1e300;\n\n            for (int d = 0; d < D; d++) {\n                if (day_cnt[d] >= cap[d]) continue;\n                double localW = vds[u][d] + vds[v][d];\n                int localC = (int)vdc[u][d] + (int)vdc[v][d];\n                double score = INIT_ALPHA_W * localW\n                             + INIT_ALPHA_C * localC\n                             + INIT_BETA    * day_sum[d];\n                if (score < bestScore) {\n                    bestScore = score;\n                    bestD = d;\n                }\n            }\n\n            if (bestD == -1) {\n                // Fallback (should not happen)\n                for (int d = 0; d < D; d++) {\n                    if (day_cnt[d] < cap[d]) {\n                        bestD = d;\n                        break;\n                    }\n                }\n            }\n\n            r[e] = bestD;\n            day_cnt[bestD]++;\n            day_sum[bestD] += weight[e];\n            vds[u][bestD]  += weight[e];\n            vds[v][bestD]  += weight[e];\n            vdc[u][bestD]++;\n            vdc[v][bestD]++;\n        }\n\n        // Local search: minimize\n        //   ALPHAW2 * sum_{v,d} vds[v][d]^2\n        // + ALPHAC2 * sum_{v,d} vdc[v][d]^2\n        // + BETA2   * sum_d day_sum[d]^2\n        const double ALPHAW2 = 1.0;\n        const double ALPHAC2 = 1.2;\n        const double BETA2   = 0.08;\n\n        int ITER = min(600000, 250 * M);\n        uniform_int_distribution<int> distEdge(0, M - 1);\n\n        for (int it = 0; it < ITER; ++it) {\n            int e1 = distEdge(rng);\n            int e2 = distEdge(rng);\n            if (e1 == e2) continue;\n            int d1 = r[e1], d2 = r[e2];\n            if (d1 == d2) continue;\n\n            int u1 = U[e1], v1 = V[e1];\n            int u2 = U[e2], v2 = V[e2];\n            double w1 = weight[e1], w2 = weight[e2];\n\n            // Day-sum component\n            double S1 = day_sum[d1], S2 = day_sum[d2];\n            double nS1 = S1 - w1 + w2;\n            double nS2 = S2 - w2 + w1;\n            double deltaDay = BETA2 * ((nS1 * nS1 + nS2 * nS2) - (S1 * S1 + S2 * S2));\n\n            // Vertex-day components (weight & count)\n            int vs[8];\n            int ds[8];\n            double dW[8];\n            int dC[8];\n            int cnt = 0;\n\n            auto addChange = [&](int v, int d, double dw, int dc) {\n                for (int i = 0; i < cnt; i++) {\n                    if (vs[i] == v && ds[i] == d) {\n                        dW[i] += dw;\n                        dC[i] += dc;\n                        return;\n                    }\n                }\n                vs[cnt] = v;\n                ds[cnt] = d;\n                dW[cnt] = dw;\n                dC[cnt] = dc;\n                cnt++;\n            };\n\n            // e1: d1 -> d2\n            addChange(u1, d1, -w1, -1);\n            addChange(u1, d2, +w1, +1);\n            addChange(v1, d1, -w1, -1);\n            addChange(v1, d2, +w1, +1);\n            // e2: d2 -> d1\n            addChange(u2, d2, -w2, -1);\n            addChange(u2, d1, +w2, +1);\n            addChange(v2, d2, -w2, -1);\n            addChange(v2, d1, +w2, +1);\n\n            double deltaVertex = 0.0;\n            double newW[8];\n            uint8_t newC[8];\n            bool bad = false;\n            for (int i = 0; i < cnt; i++) {\n                int v = vs[i];\n                int d = ds[i];\n                double oldW = vds[v][d];\n                double nw = oldW + dW[i];\n                int oldC = (int)vdc[v][d];\n                int nc = oldC + dC[i];\n                if (nc < 0 || nc > 50) { // degree small; 50 is safe guard\n                    bad = true;\n                    break;\n                }\n                newW[i] = nw;\n                newC[i] = (uint8_t)nc;\n                deltaVertex += ALPHAW2 * (nw * nw - oldW * oldW)\n                             + ALPHAC2 * (double(nc * nc - oldC * oldC));\n            }\n            if (bad) continue;\n\n            double deltaScore = deltaVertex + deltaDay;\n\n            if (deltaScore < -1e-9) {\n                // Accept swap\n                day_sum[d1] = nS1;\n                day_sum[d2] = nS2;\n                for (int i = 0; i < cnt; i++) {\n                    vds[vs[i]][ds[i]] = newW[i];\n                    vdc[vs[i]][ds[i]] = newC[i];\n                }\n                swap(r[e1], r[e2]);\n            }\n        }\n\n        return r;\n    };\n\n    // ---------------------- Step 6: Build schedules for all modes -----------------------\n    vector<vector<int>> schedules(MODES);\n    for (int m = 0; m < MODES; m++) {\n        schedules[m] = buildSchedule(weightModes[m]);\n    }\n\n    // ---------------------- Step 7: Approximate evaluation of schedules ----------------\n    // Choose evaluation sources: mix important endpoints (by imp1) and random vertices\n    int S_eval_target = min(N, 40);\n    vector<int> evalSources;\n    evalSources.reserve(S_eval_target);\n    vector<char> usedV(N, 0);\n\n    // Sort edges by imp1 (central * altDiff)\n    vector<int> edgeOrd(M);\n    iota(edgeOrd.begin(), edgeOrd.end(), 0);\n    sort(edgeOrd.begin(), edgeOrd.end(), [&](int a, int b) {\n        return imp1[a] > imp1[b];\n    });\n\n    int targetImportant = S_eval_target / 2;\n    for (int ei = 0; ei < M && (int)evalSources.size() < targetImportant; ei++) {\n        int e = edgeOrd[ei];\n        int u = U[e], v = V[e];\n        if (!usedV[u]) {\n            usedV[u] = 1;\n            evalSources.push_back(u);\n            if ((int)evalSources.size() >= targetImportant) break;\n        }\n        if (!usedV[v]) {\n            usedV[v] = 1;\n            evalSources.push_back(v);\n            if ((int)evalSources.size() >= targetImportant) break;\n        }\n    }\n\n    // Fill remaining sources with random vertices (perm order)\n    for (int i = 0; i < N && (int)evalSources.size() < S_eval_target; i++) {\n        int v = perm[i];\n        if (!usedV[v]) {\n            usedV[v] = 1;\n            evalSources.push_back(v);\n        }\n    }\n    // If still not enough (unlikely), fill sequentially\n    for (int v = 0; v < N && (int)evalSources.size() < S_eval_target; v++) {\n        if (!usedV[v]) {\n            usedV[v] = 1;\n            evalSources.push_back(v);\n        }\n    }\n\n    int S_eval = (int)evalSources.size();\n\n    const int INF = 1000000000;\n    vector<vector<int>> baseDist(S_eval, vector<int>(N, INF));\n    for (int si = 0; si < S_eval; si++) {\n        int s = evalSources[si];\n        fill(distLL.begin(), distLL.end(), INFLL);\n        priority_queue<PQItem, vector<PQItem>, greater<PQItem>> pq;\n        distLL[s] = 0;\n        pq.emplace(0, s);\n\n        while (!pq.empty()) {\n            auto [d, v] = pq.top();\n            pq.pop();\n            if (d != distLL[v]) continue;\n            for (const auto &e : g[v]) {\n                int to = e.to;\n                long long nd = d + e.w;\n                if (nd < distLL[to]) {\n                    distLL[to] = nd;\n                    pq.emplace(nd, to);\n                }\n            }\n        }\n        for (int v = 0; v < N; v++) {\n            long long dv = distLL[v];\n            if (dv >= INF_COST) dv = INF_COST;\n            baseDist[si][v] = (int)dv;\n        }\n    }\n\n    auto evaluateSchedule = [&](const vector<int> &r) -> double {\n        vector<long long> distEval(N);\n        double totalDelta = 0.0;\n\n        for (int si = 0; si < S_eval; si++) {\n            int s = evalSources[si];\n            const vector<int> &orig = baseDist[si];\n\n            for (int dday = 0; dday < D; dday++) {\n                fill(distEval.begin(), distEval.end(), (long long)INF);\n                priority_queue<PQItem, vector<PQItem>, greater<PQItem>> pq;\n                distEval[s] = 0;\n                pq.emplace(0, s);\n\n                while (!pq.empty()) {\n                    auto [cd, v] = pq.top();\n                    pq.pop();\n                    if (cd != distEval[v]) continue;\n                    for (const auto &e : g[v]) {\n                        if (r[e.id] == dday) continue; // edge under repair this day\n                        int to = e.to;\n                        long long nd = cd + e.w;\n                        if (nd < distEval[to] && nd < INF) {\n                            distEval[to] = nd;\n                            pq.emplace(nd, to);\n                        }\n                    }\n                }\n\n                for (int v = 0; v < N; v++) {\n                    if (v == s) continue;\n                    int o = orig[v];\n                    long long cur = distEval[v];\n                    int nd = (cur >= INF ? INF : (int)cur);\n                    long long delta = (long long)nd - o;\n                    if (delta < 0) delta = 0; // safety\n                    totalDelta += (double)delta;\n                }\n            }\n        }\n        return totalDelta; // denominator is common across schedules, so omitted\n    };\n\n    int bestIdx = 0;\n    double bestScore = evaluateSchedule(schedules[0]);\n    for (int m = 1; m < MODES; m++) {\n        double sc = evaluateSchedule(schedules[m]);\n        if (sc < bestScore) {\n            bestScore = sc;\n            bestIdx = m;\n        }\n    }\n\n    // ---------------------- Output best schedule ----------------------------------------\n    const vector<int> &best = schedules[bestIdx];\n    for (int i = 0; i < M; i++) {\n        cout << (best[i] + 1);\n        if (i + 1 != M) cout << ' ';\n    }\n    cout << '\\n';\n\n    return 0;\n}","ahc019":"#include <bits/stdc++.h>\nusing namespace std;\n\n// ----------------------------\n// Basic structures\n// ----------------------------\nstruct Coord {\n    int x, y, z;\n};\n\nstruct Rot {\n    int p[3]; // permutation of axes: 0=x,1=y,2=z\n    int s[3]; // sign for each axis: +1 or -1\n};\n\nconst int MAXS = 250; // upper bound for number of shared cubes (safe for D<=14)\nstatic bool adjSmall[MAXS][MAXS]; // adjacency in small puzzle\n\n// ----------------------------\n// Generate all 24 proper rotations (determinant +1) of the cube\n// ----------------------------\nvector<Rot> generate_rotations() {\n    vector<Rot> rots;\n    vector<int> perm = {0, 1, 2};\n    auto parity = [](const vector<int>& p) -> int {\n        int inv = 0;\n        for (int i = 0; i < 3; i++) {\n            for (int j = i + 1; j < 3; j++) {\n                if (p[i] > p[j]) inv++;\n            }\n        }\n        return (inv % 2 == 0) ? 1 : -1;\n    };\n\n    do {\n        int ps = parity(perm); // +1 for even, -1 for odd\n        for (int mask = 0; mask < 8; mask++) {\n            int s0 = (mask & 1) ? -1 : 1;\n            int s1 = (mask & 2) ? -1 : 1;\n            int s2 = (mask & 4) ? -1 : 1;\n            int det = ps * s0 * s1 * s2;\n            if (det == 1) { // proper rotation\n                Rot r;\n                r.p[0] = perm[0]; r.p[1] = perm[1]; r.p[2] = perm[2];\n                r.s[0] = s0;      r.s[1] = s1;      r.s[2] = s2;\n                rots.push_back(r);\n            }\n        }\n    } while (next_permutation(perm.begin(), perm.end()));\n    return rots; // should have size 24\n}\n\n// ----------------------------\n// Canonical shape representation from cell IDs\n// coords are given as cell IDs in [0, D^3)\n// preRot[r][id] = rotated (x,y,z) for rotation r\n// ----------------------------\nvector<array<int,3>> canonical_from_ids(\n    const vector<int>& ids,\n    const vector<vector<array<int,3>>>& preRot\n) {\n    vector<array<int,3>> best;\n    bool first = true;\n    int R = (int)preRot.size();\n    for (int r = 0; r < R; r++) {\n        const auto& tab = preRot[r];\n        vector<array<int,3>> coords;\n        coords.reserve(ids.size());\n        int minx = INT_MAX, miny = INT_MAX, minz = INT_MAX;\n        for (int id : ids) {\n            const auto& q = tab[id];\n            coords.push_back(q);\n            minx = min(minx, q[0]);\n            miny = min(miny, q[1]);\n            minz = min(minz, q[2]);\n        }\n        for (auto &q : coords) {\n            q[0] -= minx;\n            q[1] -= miny;\n            q[2] -= minz;\n        }\n        sort(coords.begin(), coords.end());\n        if (first || coords < best) {\n            best = coords;\n            first = false;\n        }\n    }\n    return best;\n}\n\n// ----------------------------\n// Main\n// ----------------------------\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int D;\n    if (!(cin >> D)) return 0;\n\n    // Read silhouettes: f[t][z][x], r[t][z][y]\n    vector<string> f[2], r[2];\n    for (int t = 0; t < 2; t++) {\n        f[t].resize(D);\n        r[t].resize(D);\n        for (int z = 0; z < D; z++) cin >> f[t][z];\n        for (int z = 0; z < D; z++) cin >> r[t][z];\n    }\n\n    // Build minimal-volume occupancy for each puzzle\n    vector<Coord> cells[2]; // occupied cells per puzzle\n\n    for (int t = 0; t < 2; t++) {\n        for (int z = 0; z < D; z++) {\n            vector<int> rows, cols;\n            for (int x = 0; x < D; x++) if (f[t][z][x] == '1') rows.push_back(x);\n            for (int y = 0; y < D; y++) if (r[t][z][y] == '1') cols.push_back(y);\n            int Rcnt = (int)rows.size();\n            int Ccnt = (int)cols.size();\n            if (Rcnt == 0 || Ccnt == 0) continue; // shouldn't happen by constraints\n\n            if (Rcnt <= Ccnt) {\n                // Use Ccnt cubes, one per column\n                for (int j = 0; j < Ccnt; j++) {\n                    int x = rows[j % Rcnt];\n                    int y = cols[j];\n                    cells[t].push_back({x, y, z});\n                }\n            } else {\n                // Use Rcnt cubes, one per row\n                for (int i = 0; i < Rcnt; i++) {\n                    int x = rows[i];\n                    int y = cols[i % Ccnt];\n                    cells[t].push_back({x, y, z});\n                }\n            }\n        }\n    }\n\n    int V0 = (int)cells[0].size();\n    int V1 = (int)cells[1].size();\n\n    // Decide which puzzle is \"small\" and which is \"big\" by volume\n    int small = 0, big = 1;\n    if (V0 > V1) {\n        small = 1;\n        big = 0;\n        swap(V0, V1);\n    }\n    int S = (int)cells[small].size(); // all cubes in small puzzle\n    int T = (int)cells[big].size();\n\n    // Positions and cell IDs\n    vector<Coord> posSmall(S), posBigAll(T);\n    for (int i = 0; i < S; i++) posSmall[i] = cells[small][i];\n    for (int i = 0; i < T; i++) posBigAll[i] = cells[big][i];\n\n    auto encode = [D](int x, int y, int z) {\n        return x * D * D + y * D + z;\n    };\n    int D3 = D * D * D;\n\n    vector<int> cellIdSmall(S), cellIdBigAll(T);\n    for (int i = 0; i < S; i++) {\n        cellIdSmall[i] = encode(posSmall[i].x, posSmall[i].y, posSmall[i].z);\n    }\n    for (int i = 0; i < T; i++) {\n        cellIdBigAll[i] = encode(posBigAll[i].x, posBigAll[i].y, posBigAll[i].z);\n    }\n\n    // Build adjacency in the small puzzle\n    vector<int> idxSmall(D3, -1);\n    for (int i = 0; i < S; i++) {\n        idxSmall[cellIdSmall[i]] = i;\n    }\n\n    for (int i = 0; i < S; i++)\n        for (int j = 0; j < S; j++)\n            adjSmall[i][j] = false;\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 k = 0; k < S; k++) {\n        int x = posSmall[k].x;\n        int y = posSmall[k].y;\n        int z = posSmall[k].z;\n        for (int d = 0; d < 6; d++) {\n            int nx = x + dx[d];\n            int ny = y + dy[d];\n            int nz = z + dz[d];\n            if (nx < 0 || nx >= D || ny < 0 || ny >= D || nz < 0 || nz >= D) continue;\n            int nid = encode(nx, ny, nz);\n            int j = idxSmall[nid];\n            if (j >= 0) {\n                adjSmall[k][j] = adjSmall[j][k] = true;\n            }\n        }\n    }\n\n    // Convert adjacency to neighbor lists\n    vector<vector<int>> neighbors(S);\n    for (int i = 0; i < S; i++) {\n        for (int j = i + 1; j < S; j++) {\n            if (adjSmall[i][j]) {\n                neighbors[i].push_back(j);\n                neighbors[j].push_back(i);\n            }\n        }\n    }\n\n    // Also build adjacency in the big puzzle (for degree-based mapping)\n    vector<vector<int>> neighborsBig(T);\n    vector<int> idxBig(D3, -1);\n    for (int i = 0; i < T; i++) idxBig[cellIdBigAll[i]] = i;\n    for (int k = 0; k < T; k++) {\n        int x = posBigAll[k].x;\n        int y = posBigAll[k].y;\n        int z = posBigAll[k].z;\n        for (int d = 0; d < 6; d++) {\n            int nx = x + dx[d];\n            int ny = y + dy[d];\n            int nz = z + dz[d];\n            if (nx < 0 || nx >= D || ny < 0 || ny >= D || nz < 0 || nz >= D) continue;\n            int nid = encode(nx, ny, nz);\n            int j = idxBig[nid];\n            if (j >= 0) {\n                neighborsBig[k].push_back(j);\n            }\n        }\n    }\n\n    // Precompute all rotations and rotated coordinates for each cell ID\n    vector<Rot> rots = generate_rotations();\n    int R = (int)rots.size(); // should be 24\n    vector<vector<array<int,3>>> preRot(R, vector<array<int,3>>(D3));\n\n    for (int id = 0; id < D3; id++) {\n        int x = id / (D * D);\n        int rem = id % (D * D);\n        int y = rem / D;\n        int z = rem % D;\n        int src[3] = {x, y, z};\n        for (int rIdx = 0; rIdx < R; rIdx++) {\n            const Rot &rt = rots[rIdx];\n            array<int,3> q;\n            q[0] = rt.s[0] * src[ rt.p[0] ];\n            q[1] = rt.s[1] * src[ rt.p[1] ];\n            q[2] = rt.s[2] * src[ rt.p[2] ];\n            preRot[rIdx][id] = q;\n        }\n    }\n\n    // Initialize RNG with deterministic seed based on input (for reproducibility)\n    uint64_t seed = 1234567u ^ (uint64_t)D;\n    for (int t = 0; t < 2; t++) {\n        for (int z = 0; z < D; z++) {\n            for (int x = 0; x < D; x++) {\n                if (f[t][z][x] == '1') {\n                    seed ^= ((uint64_t)(t+1) << 48) ^ ((uint64_t)(z+1) << 32) ^ ((uint64_t)(x+1) << 16);\n                }\n                if (r[t][z][x] == '1') {\n                    seed ^= ((uint64_t)(t+3) << 40) ^ ((uint64_t)(z+5) << 24) ^ ((uint64_t)(x+7) << 8);\n                }\n            }\n        }\n    }\n    mt19937_64 rng(seed);\n    uniform_real_distribution<double> urd(0.0, 1.0);\n\n    // Helper: shapesMatch for given node set and mapped big IDs\n    auto shapesMatch = [&](const vector<int>& nodes,\n                           const vector<int>& cellIdBigMapped) -> bool {\n        vector<int> idsSmall, idsBig;\n        idsSmall.reserve(nodes.size());\n        idsBig.reserve(nodes.size());\n        for (int idx : nodes) {\n            idsSmall.push_back(cellIdSmall[idx]);\n            idsBig.push_back(cellIdBigMapped[idx]);\n        }\n        auto repSmall = canonical_from_ids(idsSmall, preRot);\n        auto repBig   = canonical_from_ids(idsBig, preRot);\n        return repSmall == repBig;\n    };\n\n    // Deterministic clustering for a given mapping small->big (match[i] = index in big)\n    auto clusterDet = [&](const vector<int>& match)\n        -> pair<double, vector<vector<int>>> {\n        vector<int> cellIdBigMapped(S);\n        for (int i = 0; i < S; i++) {\n            cellIdBigMapped[i] = cellIdBigAll[ match[i] ];\n        }\n\n        vector<char> visited(S, false);\n        vector<vector<int>> clusters;\n        clusters.reserve(S);\n\n        for (int i = 0; i < S; i++) {\n            if (visited[i]) continue;\n\n            vector<int> cluster;\n            cluster.push_back(i);\n            visited[i] = true;\n\n            while (true) {\n                vector<int> cand;\n                for (int u : cluster) {\n                    for (int v : neighbors[u]) {\n                        if (!visited[v]) cand.push_back(v);\n                    }\n                }\n                sort(cand.begin(), cand.end());\n                cand.erase(unique(cand.begin(), cand.end()), cand.end());\n                bool added = false;\n                for (int v : cand) {\n                    vector<int> candidate = cluster;\n                    candidate.push_back(v);\n                    if (shapesMatch(candidate, cellIdBigMapped)) {\n                        cluster.push_back(v);\n                        visited[v] = true;\n                        added = true;\n                    }\n                }\n                if (!added) break;\n            }\n\n            clusters.push_back(cluster);\n        }\n\n        double sumInv = 0.0;\n        for (auto &cl : clusters) {\n            sumInv += 1.0 / (double)cl.size();\n        }\n        return {sumInv, clusters};\n    };\n\n    // Randomized clustering for the same mapping (used as refinement)\n    auto clusterRand = [&](const vector<int>& match)\n        -> pair<double, vector<vector<int>>> {\n        vector<int> cellIdBigMapped(S);\n        for (int i = 0; i < S; i++) {\n            cellIdBigMapped[i] = cellIdBigAll[ match[i] ];\n        }\n\n        vector<char> visited(S, false);\n        vector<vector<int>> clusters;\n        clusters.reserve(S);\n\n        vector<int> order(S);\n        iota(order.begin(), order.end(), 0);\n        shuffle(order.begin(), order.end(), rng);\n\n        for (int idx0 = 0; idx0 < S; idx0++) {\n            int i = order[idx0];\n            if (visited[i]) continue;\n\n            vector<int> cluster;\n            cluster.push_back(i);\n            visited[i] = true;\n\n            while (true) {\n                vector<int> cand;\n                for (int u : cluster) {\n                    for (int v : neighbors[u]) {\n                        if (!visited[v]) cand.push_back(v);\n                    }\n                }\n                sort(cand.begin(), cand.end());\n                cand.erase(unique(cand.begin(), cand.end()), cand.end());\n                if (cand.empty()) break;\n                shuffle(cand.begin(), cand.end(), rng);\n                bool added = false;\n                for (int v : cand) {\n                    vector<int> candidate = cluster;\n                    candidate.push_back(v);\n                    if (shapesMatch(candidate, cellIdBigMapped)) {\n                        cluster.push_back(v);\n                        visited[v] = true;\n                        added = true;\n                    }\n                }\n                if (!added) break;\n            }\n\n            clusters.push_back(cluster);\n        }\n\n        double sumInv = 0.0;\n        for (auto &cl : clusters) {\n            sumInv += 1.0 / (double)cl.size();\n        }\n        return {sumInv, clusters};\n    };\n\n    double bestScore = 1e100;\n    vector<vector<int>> bestClusters;\n    vector<int> bestMatch;\n\n    // Helper: for a mapping, take best of deterministic and one random clustering\n    auto evalMapping = [&](const vector<int>& match) {\n        auto detRes = clusterDet(match);\n        double candScore = detRes.first;\n        auto candClusters = move(detRes.second);\n        auto rndRes = clusterRand(match);\n        if (rndRes.first < candScore) {\n            candScore = rndRes.first;\n            candClusters = move(rndRes.second);\n        }\n        if (candScore < bestScore) {\n            bestScore = candScore;\n            bestClusters = move(candClusters);\n            bestMatch = match;\n        }\n    };\n\n    // ---------- Attempt 1: nearest-neighbor mapping (original space) ----------\n    {\n        vector<int> match(S, -1);\n        vector<char> used(T, false);\n        for (int i = 0; i < S; i++) {\n            const Coord &cs = posSmall[i];\n            int bestJ = -1;\n            int bestDist = INT_MAX;\n            for (int j = 0; j < T; j++) {\n                if (used[j]) continue;\n                const Coord &cb = posBigAll[j];\n                int dist = abs(cs.x - cb.x) + abs(cs.y - cb.y) + abs(cs.z - cb.z);\n                if (dist < bestDist) {\n                    bestDist = dist;\n                    bestJ = j;\n                }\n            }\n            if (bestJ == -1) {\n                bestJ = 0;\n                while (used[bestJ]) bestJ++;\n            }\n            match[i] = bestJ;\n            used[bestJ] = true;\n        }\n        evalMapping(match);\n    }\n\n    // ---------- Attempt 2: lexicographic mapping by (x,y,z) ----------\n    {\n        vector<int> idxS(S), idxB(T);\n        iota(idxS.begin(), idxS.end(), 0);\n        iota(idxB.begin(), idxB.end(), 0);\n        sort(idxS.begin(), idxS.end(), [&](int a, int b) {\n            const Coord &A = posSmall[a], &B = posSmall[b];\n            if (A.x != B.x) return A.x < B.x;\n            if (A.y != B.y) return A.y < B.y;\n            return A.z < B.z;\n        });\n        sort(idxB.begin(), idxB.end(), [&](int a, int b) {\n            const Coord &A = posBigAll[a], &B = posBigAll[b];\n            if (A.x != B.x) return A.x < B.x;\n            if (A.y != B.y) return A.y < B.y;\n            return A.z < B.z;\n        });\n        vector<int> match(S, -1);\n        for (int k = 0; k < S; k++) {\n            match[idxS[k]] = idxB[k];\n        }\n        evalMapping(match);\n    }\n\n    // ---------- Attempt 3: lexicographic mapping by (z,x,y) ----------\n    {\n        vector<int> idxS(S), idxB(T);\n        iota(idxS.begin(), idxS.end(), 0);\n        iota(idxB.begin(), idxB.end(), 0);\n        sort(idxS.begin(), idxS.end(), [&](int a, int b) {\n            const Coord &A = posSmall[a], &B = posSmall[b];\n            if (A.z != B.z) return A.z < B.z;\n            if (A.x != B.x) return A.x < B.x;\n            return A.y < B.y;\n        });\n        sort(idxB.begin(), idxB.end(), [&](int a, int b) {\n            const Coord &A = posBigAll[a], &B = posBigAll[b];\n            if (A.z != B.z) return A.z < B.z;\n            if (A.x != B.x) return A.x < B.x;\n            return A.y < B.y;\n        });\n        vector<int> match(S, -1);\n        for (int k = 0; k < S; k++) {\n            match[idxS[k]] = idxB[k];\n        }\n        evalMapping(match);\n    }\n\n    // ---------- Attempt 3b: lexicographic mapping by (z,y,x) ----------\n    {\n        vector<int> idxS(S), idxB(T);\n        iota(idxS.begin(), idxS.end(), 0);\n        iota(idxB.begin(), idxB.end(), 0);\n        sort(idxS.begin(), idxS.end(), [&](int a, int b) {\n            const Coord &A = posSmall[a], &B = posSmall[b];\n            if (A.z != B.z) return A.z < B.z;\n            if (A.y != B.y) return A.y < B.y;\n            return A.x < B.x;\n        });\n        sort(idxB.begin(), idxB.end(), [&](int a, int b) {\n            const Coord &A = posBigAll[a], &B = posBigAll[b];\n            if (A.z != B.z) return A.z < B.z;\n            if (A.y != B.y) return A.y < B.y;\n            return A.x < B.x;\n        });\n        vector<int> match(S, -1);\n        for (int k = 0; k < S; k++) {\n            match[idxS[k]] = idxB[k];\n        }\n        evalMapping(match);\n    }\n\n    // ---------- Attempt 4: degree-based greedy mapping ----------\n    {\n        vector<int> degSmall(S), degBig(T);\n        for (int i = 0; i < S; i++) degSmall[i] = (int)neighbors[i].size();\n        for (int j = 0; j < T; j++) degBig[j] = (int)neighborsBig[j].size();\n\n        vector<int> idxS(S), idxB(T);\n        iota(idxS.begin(), idxS.end(), 0);\n        iota(idxB.begin(), idxB.end(), 0);\n        sort(idxS.begin(), idxS.end(), [&](int a, int b) {\n            if (degSmall[a] != degSmall[b]) return degSmall[a] > degSmall[b]; // high degree first\n            const Coord &A = posSmall[a], &B = posSmall[b];\n            if (A.x != B.x) return A.x < B.x;\n            if (A.y != B.y) return A.y < B.y;\n            return A.z < B.z;\n        });\n        sort(idxB.begin(), idxB.end(), [&](int a, int b) {\n            if (degBig[a] != degBig[b]) return degBig[a] > degBig[b];\n            const Coord &A = posBigAll[a], &B = posBigAll[b];\n            if (A.x != B.x) return A.x < B.x;\n            if (A.y != B.y) return A.y < B.y;\n            return A.z < B.z;\n        });\n\n        vector<int> match(S, -1);\n        for (int k = 0; k < S; k++) {\n            match[idxS[k]] = idxB[k];\n        }\n\n        evalMapping(match);\n    }\n\n    // ---------- Precompute big centroid for rotation-based mappings ----------\n    double sumBx = 0.0, sumBy = 0.0, sumBz = 0.0;\n    for (int j = 0; j < T; j++) {\n        sumBx += posBigAll[j].x;\n        sumBy += posBigAll[j].y;\n        sumBz += posBigAll[j].z;\n    }\n    double cenBx = sumBx / (double)T;\n    double cenBy = sumBy / (double)T;\n    double cenBz = sumBz / (double)T;\n\n    // ---------- Attempts 5+: rotation-based nearest-neighbor mappings ----------\n    for (int rIdx = 0; rIdx < R; rIdx++) {\n        vector<array<double,3>> rotPos(S);\n        double sumSx = 0.0, sumSy = 0.0, sumSz = 0.0;\n        for (int i = 0; i < S; i++) {\n            auto q = preRot[rIdx][ cellIdSmall[i] ];\n            rotPos[i] = { (double)q[0], (double)q[1], (double)q[2] };\n            sumSx += rotPos[i][0];\n            sumSy += rotPos[i][1];\n            sumSz += rotPos[i][2];\n        }\n        double cenSx = sumSx / (double)S;\n        double cenSy = sumSy / (double)S;\n        double cenSz = sumSz / (double)S;\n        double dx0 = cenBx - cenSx;\n        double dy0 = cenBy - cenSy;\n        double dz0 = cenBz - cenSz;\n\n        vector<int> match(S, -1);\n        vector<char> used(T, false);\n\n        for (int i = 0; i < S; i++) {\n            double tx = rotPos[i][0] + dx0;\n            double ty = rotPos[i][1] + dy0;\n            double tz = rotPos[i][2] + dz0;\n            int bestJ = -1;\n            double bestDist = 1e100;\n            for (int j = 0; j < T; j++) {\n                if (used[j]) continue;\n                const Coord &cb = posBigAll[j];\n                double ddx = cb.x - tx;\n                double ddy = cb.y - ty;\n                double ddz = cb.z - tz;\n                double dist2 = ddx*ddx + ddy*ddy + ddz*ddz;\n                if (dist2 < bestDist) {\n                    bestDist = dist2;\n                    bestJ = j;\n                }\n            }\n            if (bestJ == -1) {\n                bestJ = 0;\n                while (used[bestJ]) bestJ++;\n            }\n            match[i] = bestJ;\n            used[bestJ] = true;\n        }\n\n        evalMapping(match);\n    }\n\n    // ---------- Random mappings ----------\n    const int RANDOM_ATTEMPTS = 12;\n    for (int att = 0; att < RANDOM_ATTEMPTS; att++) {\n        vector<int> smallOrder(S), bigPerm(T);\n        iota(smallOrder.begin(), smallOrder.end(), 0);\n        iota(bigPerm.begin(),  bigPerm.end(),  0);\n        shuffle(smallOrder.begin(), smallOrder.end(), rng);\n        shuffle(bigPerm.begin(),  bigPerm.end(),  rng);\n\n        vector<int> match(S, -1);\n        for (int k = 0; k < S; k++) {\n            int si = smallOrder[k];\n            int bi = bigPerm[k];\n            match[si] = bi;\n        }\n\n        evalMapping(match);\n    }\n\n    // Precompute node \"importance\" based on initial bestClusters (small cluster = more important)\n    vector<int> nodeImportance(S);\n    {\n        vector<int> clusterSize;\n        clusterSize.reserve(bestClusters.size());\n        for (auto &cl : bestClusters) clusterSize.push_back((int)cl.size());\n        for (int cid = 0; cid < (int)bestClusters.size(); cid++) {\n            for (int u : bestClusters[cid]) nodeImportance[u] = clusterSize[cid];\n        }\n    }\n    vector<int> importanceOrder(S);\n    iota(importanceOrder.begin(), importanceOrder.end(), 0);\n    sort(importanceOrder.begin(), importanceOrder.end(),\n         [&](int a, int b){ return nodeImportance[a] < nodeImportance[b]; });\n    int importantCount = max(1, S / 2); // top half nodes with smallest clusters\n\n    // ---------- Local search on mapping (hill-climbing with biased swaps) ----------\n    {\n        double lsScore = bestScore;\n        vector<vector<int>> lsClusters = bestClusters;\n        vector<int> lsMatch = bestMatch;\n\n        int LS_ITERS = 300 + S; // a bit more iterations\n\n        for (int it = 0; it < LS_ITERS; it++) {\n            int a, b;\n            if (it & 1) {\n                // neighbor-biased swap\n                a = importanceOrder[(int)(rng() % importantCount)];\n                if (neighbors[a].empty()) continue;\n                b = neighbors[a][rng() % neighbors[a].size()];\n            } else {\n                // random counterpart\n                a = importanceOrder[(int)(rng() % importantCount)];\n                b = (int)(rng() % S);\n            }\n            if (a == b) continue;\n\n            swap(lsMatch[a], lsMatch[b]);\n            auto res = clusterDet(lsMatch);\n            if (res.first < lsScore) {\n                lsScore = res.first;\n                lsClusters = move(res.second);\n            } else {\n                // revert\n                swap(lsMatch[a], lsMatch[b]);\n            }\n        }\n\n        if (lsScore < bestScore) {\n            bestScore = lsScore;\n            bestClusters = move(lsClusters);\n            bestMatch = lsMatch;\n        }\n    }\n\n    // ---------- Simulated annealing on mapping (very small budget) ----------\n    {\n        double curScore = bestScore;\n        vector<vector<int>> curClusters = bestClusters;\n        vector<int> curMatch = bestMatch;\n\n        double bestScoreSA = curScore;\n        vector<vector<int>> bestClustersSA = curClusters;\n        vector<int> bestMatchSA = curMatch;\n\n        const int SA_ITERS = 50;\n        double T0 = 1.0;\n        double T1 = 0.05;\n\n        for (int it = 0; it < SA_ITERS; it++) {\n            double t = (double)it / (double)SA_ITERS;\n            double T = T0 * pow(T1 / T0, t); // geometric cooling\n\n            int a = importanceOrder[(int)(rng() % importantCount)];\n            int b = (int)(rng() % S);\n            if (a == b) continue;\n\n            swap(curMatch[a], curMatch[b]);\n            auto res = clusterDet(curMatch);\n            double newScore = res.first;\n\n            bool accept = false;\n            if (newScore < curScore) {\n                accept = true;\n            } else {\n                double prob = exp((curScore - newScore) / max(1e-9, T));\n                if (urd(rng) < prob) accept = true;\n            }\n\n            if (accept) {\n                curScore = newScore;\n                curClusters = move(res.second);\n                if (curScore < bestScoreSA) {\n                    bestScoreSA = curScore;\n                    bestClustersSA = curClusters;\n                    bestMatchSA = curMatch;\n                }\n            } else {\n                swap(curMatch[a], curMatch[b]);\n            }\n        }\n\n        if (bestScoreSA < bestScore) {\n            bestScore = bestScoreSA;\n            bestClusters = move(bestClustersSA);\n            bestMatch = bestMatchSA;\n        }\n    }\n\n    // ---------- Randomized re-clustering for the best mapping ----------\n    {\n        double bestScoreRefine = bestScore;\n        vector<vector<int>> bestClustersRefine = bestClusters;\n\n        const int CLUSTER_RANDOM_RETRY = 20;\n        for (int it = 0; it < CLUSTER_RANDOM_RETRY; it++) {\n            auto res = clusterRand(bestMatch);\n            if (res.first < bestScoreRefine) {\n                bestScoreRefine = res.first;\n                bestClustersRefine = move(res.second);\n            }\n        }\n\n        bestScore = bestScoreRefine;\n        bestClusters = move(bestClustersRefine);\n    }\n\n    // ---------- Post-process: merge neighboring clusters for the best mapping ----------\n    {\n        vector<int> cellIdBigMapped(S);\n        for (int i = 0; i < S; i++) {\n            cellIdBigMapped[i] = cellIdBigAll[ bestMatch[i] ];\n        }\n\n        vector<vector<int>> &clusters = bestClusters;\n        vector<int> nodeCluster(S, -1);\n        for (int cid = 0; cid < (int)clusters.size(); cid++) {\n            for (int u : clusters[cid]) nodeCluster[u] = cid;\n        }\n\n        bool changed = true;\n        while (changed) {\n            changed = false;\n            int C = (int)clusters.size();\n            if (C <= 1) break;\n\n            // Build cluster adjacency from node adjacency\n            vector<vector<int>> clNei(C);\n            for (int u = 0; u < S; u++) {\n                int cu = nodeCluster[u];\n                for (int v : neighbors[u]) {\n                    int cv = nodeCluster[v];\n                    if (cu == cv) continue;\n                    if (cu < cv) clNei[cu].push_back(cv);\n                    else clNei[cv].push_back(cu);\n                }\n            }\n            for (int c = 0; c < C; c++) {\n                auto &lst = clNei[c];\n                sort(lst.begin(), lst.end());\n                lst.erase(unique(lst.begin(), lst.end()), lst.end());\n            }\n\n            bool merged = false;\n            for (int cu = 0; cu < C && !merged; cu++) {\n                auto lst = clNei[cu];\n                sort(lst.begin(), lst.end(), [&](int a, int b) {\n                    return clusters[cu].size() + clusters[a].size()\n                         > clusters[cu].size() + clusters[b].size();\n                });\n                for (int cv : lst) {\n                    if (cv <= cu) continue;\n                    vector<int> unionNodes;\n                    unionNodes.reserve(clusters[cu].size() + clusters[cv].size());\n                    unionNodes.insert(unionNodes.end(),\n                                      clusters[cu].begin(), clusters[cu].end());\n                    unionNodes.insert(unionNodes.end(),\n                                      clusters[cv].begin(), clusters[cv].end());\n                    if (!shapesMatch(unionNodes, cellIdBigMapped)) continue;\n\n                    // Merge cv into cu\n                    clusters[cu] = move(unionNodes);\n                    for (int u : clusters[cu]) nodeCluster[u] = cu;\n                    clusters.erase(clusters.begin() + cv);\n                    // Update cluster indices in nodeCluster\n                    for (int u = 0; u < S; u++) {\n                        int cid = nodeCluster[u];\n                        if (cid > cv) nodeCluster[u] = cid - 1;\n                    }\n                    merged = true;\n                    changed = true;\n                    break;\n                }\n            }\n        }\n    }\n\n    // Build final block assignments using bestMatch and bestClusters\n    vector<int> b0(D3, 0), b1(D3, 0);\n    int blockCount = 0;\n\n    auto setCell = [&](int puzzle, const Coord& c, int id) {\n        int idx = encode(c.x, c.y, c.z);\n        if (puzzle == 0) b0[idx] = id;\n        else b1[idx] = id;\n    };\n\n    // Shared blocks from clusters\n    for (const auto& cluster : bestClusters) {\n        ++blockCount;\n        for (int idx : cluster) {\n            const Coord &cs = posSmall[idx];\n            const Coord &cb = posBigAll[ bestMatch[idx] ];\n            setCell(small, cs, blockCount);\n            setCell(big,   cb, blockCount);\n        }\n    }\n\n    // Big-only blocks for cubes in big puzzle that are not shared\n    vector<char> usedBig(T, false);\n    for (int i = 0; i < S; i++) {\n        usedBig[ bestMatch[i] ] = true;\n    }\n    for (int j = 0; j < T; j++) {\n        if (usedBig[j]) continue;\n        ++blockCount;\n        const Coord &cb = posBigAll[j];\n        setCell(big, cb, blockCount);\n    }\n\n    // Output\n    cout << blockCount << '\\n';\n\n    auto output_grid = [&](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 idx = x * D * D + y * D + z;\n                    if (!first) cout << ' ';\n                    first = false;\n                    cout << b[idx];\n                }\n            }\n        }\n        cout << '\\n';\n    };\n\n    // Puzzle 0 grid then puzzle 1 grid\n    output_grid(b0);\n    output_grid(b1);\n\n    return 0;\n}","ahc020":"#include <bits/stdc++.h>\nusing namespace std;\nusing ll = long long;\n\nconst int MAXN = 105;   // N <= 100\nconst int MAXM = 305;   // M <= 300\nconst int MAXK = 5005;  // K <= 5000\nconst ll INFLL = (1LL << 60);\n\n// ----- Graph and data -----\nstruct Edge {\n    int u, v;\n    ll w;\n};\n\nint N, M, K;\nll vx[MAXN], vy[MAXN];\nll ax_arr[MAXK], ay_arr[MAXK];\nEdge edges[MAXM];\nvector<pair<int,int>> adj[MAXN];  // (to, edgeIndex)\n\n// All-pairs shortest paths (Dijkstra from each node)\nll distAll[MAXN][MAXN];    // distAll[s][v]\nint parEdge[MAXN][MAXN];   // parent edge index from s to v\n\n// Residents' candidate stations sorted by squared distance (within radius 5000)\nvector<pair<ll,int>> residentCand[MAXK];\n\n// For greedy coverage: residents each station can cover\nvector<int> stationRes[MAXN];  // stationRes[v] = list of residents k covered by v\n\n// For cost-aware greedy cover: max squared distance to any resident this station can cover\nll stationMaxR2[MAXN];\n\n// ----- Steiner tree / evaluation buffers -----\nll maxd2_arr[MAXN];\nbool used_arr[MAXN];\nbool isReq[MAXN];\nbool usedEdgeUnion[MAXM];\nbool aliveEdge[MAXM];\n\nll keyArr[MAXN];\nint prArr[MAXN];\nbool inArr[MAXN];\nint reqNodesArr[MAXN];\nint metricU[MAXN], metricV[MAXN];\n\n// DSU for MST\nint dsu_p[MAXN], dsu_rnk[MAXN];\nvector<int> ordEdges;  // edges sorted by weight\n\ninline void dsu_reset(int n) {\n    for (int i = 1; i <= n; ++i) {\n        dsu_p[i] = i;\n        dsu_rnk[i] = 0;\n    }\n}\nint dsu_find(int x) {\n    return dsu_p[x] == x ? x : (dsu_p[x] = dsu_find(dsu_p[x]));\n}\nbool dsu_unite(int a, int b) {\n    a = dsu_find(a);\n    b = dsu_find(b);\n    if (a == b) return false;\n    if (dsu_rnk[a] < dsu_rnk[b]) swap(a, b);\n    dsu_p[b] = a;\n    if (dsu_rnk[a] == dsu_rnk[b]) ++dsu_rnk[a];\n    return true;\n}\n\n// Global best solution\nll bestCostGlobal = (1LL << 62);\nint P_best[MAXN];\nchar B_best[MAXM];\nchar open_best[MAXN];   // open set corresponding to best solution\n\n// Temporary buffers for evaluation\nint P_tmp[MAXN];\nchar B_tmp[MAXM];\n\n// Global start time for time-guarded heuristics\nchrono::steady_clock::time_point g_start;\n\n// Evaluate solution for given open[1..N].\n// openFlag[v] = 1 if station v can be used as broadcast center.\n// Assignment: each resident chooses nearest open station (min distance).\n// Returns true if all residents can be covered (each within radius <=5000).\n// On success, fills P_out[1..N], B_out[0..M-1], and cost_out.\nbool evaluate_solution(const char openFlag[], ll &cost_out, int P_out[], char B_out[]) {\n    const ll R2max = 5000LL * 5000LL;\n\n    // Residents -> nearest open station within radius 5000\n    for (int i = 1; i <= N; ++i) {\n        maxd2_arr[i] = 0;\n        used_arr[i] = false;\n    }\n\n    for (int k = 0; k < K; ++k) {\n        bool assigned = false;\n        const auto &cand = residentCand[k];\n        for (size_t idx = 0; idx < cand.size(); ++idx) {\n            ll d2 = cand[idx].first;\n            if (d2 > R2max) break;\n            int v = cand[idx].second;\n            if (openFlag[v]) {\n                assigned = true;\n                used_arr[v] = true;\n                if (maxd2_arr[v] < d2) maxd2_arr[v] = d2;\n                break;\n            }\n        }\n        if (!assigned) {\n            // Some resident cannot be covered\n            return false;\n        }\n    }\n\n    // Compute P_i and broadcasting cost\n    ll broadcastCost = 0;\n    for (int i = 1; i <= N; ++i) {\n        if (maxd2_arr[i] > 0) {\n            double sr = sqrt((double)maxd2_arr[i]);\n            ll r = (ll)sr;\n            if (r * r < maxd2_arr[i]) ++r;\n            if (r > 5000) r = 5000;\n            P_out[i] = (int)r;\n            broadcastCost += r * r;\n        } else {\n            P_out[i] = 0;\n        }\n    }\n\n    // Build required node set: station 1 + all stations with assigned residents\n    for (int i = 1; i <= N; ++i) isReq[i] = false;\n    int R = 0;\n    isReq[1] = true;\n    reqNodesArr[R++] = 1;\n    for (int i = 2; i <= N; ++i) {\n        if (used_arr[i]) {\n            isReq[i] = true;\n            reqNodesArr[R++] = i;\n        }\n    }\n\n    // No edges needed if only root is required\n    for (int j = 0; j < M; ++j) B_out[j] = 0;\n    if (R <= 1) {\n        cost_out = broadcastCost;\n        return true;\n    }\n\n    // Metric MST on required nodes (Prim) using distAll\n    for (int i = 0; i < R; ++i) {\n        keyArr[i] = INFLL;\n        prArr[i] = -1;\n        inArr[i] = false;\n    }\n    keyArr[0] = 0;\n    int metricCnt = 0;\n    for (int it = 0; it < R; ++it) {\n        int u = -1;\n        ll best = INFLL;\n        for (int i = 0; i < R; ++i) if (!inArr[i] && keyArr[i] < best) {\n            best = keyArr[i];\n            u = i;\n        }\n        if (u == -1) break;  // should not happen\n        inArr[u] = true;\n        if (prArr[u] != -1) {\n            metricU[metricCnt] = u;\n            metricV[metricCnt] = prArr[u];\n            ++metricCnt;\n        }\n        int vu = reqNodesArr[u];\n        for (int i = 0; i < R; ++i) if (!inArr[i]) {\n            int vv = reqNodesArr[i];\n            ll w = distAll[vu][vv];\n            if (w < keyArr[i]) {\n                keyArr[i] = w;\n                prArr[i] = u;\n            }\n        }\n    }\n\n    // Union of shortest paths for metric MST edges\n    for (int j = 0; j < M; ++j) usedEdgeUnion[j] = false;\n    for (int idx = 0; idx < metricCnt; ++idx) {\n        int a = reqNodesArr[metricU[idx]];\n        int b = reqNodesArr[metricV[idx]];\n        int cur = b;\n        while (cur != a) {\n            int eid = parEdge[a][cur];\n            if (eid < 0) break;  // safety\n            usedEdgeUnion[eid] = true;\n            const Edge &E = edges[eid];\n            cur = E.u ^ E.v ^ cur;\n        }\n    }\n\n    // MST over union edges (Steiner tree approximation)\n    dsu_reset(N);\n    for (int j = 0; j < M; ++j) aliveEdge[j] = false;\n    for (int idx = 0; idx < (int)ordEdges.size(); ++idx) {\n        int e = ordEdges[idx];\n        if (!usedEdgeUnion[e]) continue;\n        int u = edges[e].u;\n        int v = edges[e].v;\n        if (dsu_unite(u, v)) {\n            aliveEdge[e] = true;\n        }\n    }\n\n    // Additional leaf-pruning on this MST to remove unnecessary Steiner leaves\n    {\n        static int deg[MAXN];\n        for (int i = 1; i <= N; ++i) deg[i] = 0;\n        for (int e = 0; e < M; ++e) if (aliveEdge[e]) {\n            int u = edges[e].u, v = edges[e].v;\n            ++deg[u];\n            ++deg[v];\n        }\n        queue<int> q;\n        for (int i = 1; i <= N; ++i) {\n            if (!isReq[i] && deg[i] == 1) q.push(i);\n        }\n        while (!q.empty()) {\n            int v = q.front(); q.pop();\n            if (isReq[v]) continue;\n            if (deg[v] != 1) continue;\n            for (auto &pr : adj[v]) {\n                int to = pr.first;\n                int eid = pr.second;\n                if (aliveEdge[eid]) {\n                    aliveEdge[eid] = false;\n                    --deg[v];\n                    --deg[to];\n                    if (!isReq[to] && deg[to] == 1) q.push(to);\n                    break;\n                }\n            }\n        }\n    }\n\n    ll edgeCost = 0;\n    for (int j = 0; j < M; ++j) {\n        if (aliveEdge[j]) edgeCost += edges[j].w;\n    }\n\n    for (int j = 0; j < M; ++j) {\n        B_out[j] = aliveEdge[j] ? 1 : 0;\n    }\n\n    cost_out = broadcastCost + edgeCost;\n    return true;\n}\n\n// Greedy removal: try to close stations in 'order'.\n// open[] is modified in place, curCost is updated if closures accepted.\n// covCount[k] is number of open stations covering resident k (consistent with open[]).\nvoid greedy_removal(char open[], ll &curCost, const vector<int> &order, int covCount[]) {\n    for (int idx = 0; idx < (int)order.size(); ++idx) {\n        int v = order[idx];\n        if (!open[v]) continue;\n\n        // Quick coverage check: if some resident is only covered by v, can't close v\n        bool fail = false;\n        const auto &resList = stationRes[v];\n        for (int i = 0; i < (int)resList.size(); ++i) {\n            int k = resList[i];\n            if (covCount[k] == 1) {\n                fail = true;\n                break;\n            }\n        }\n        if (fail) continue;\n\n        // Tentatively close v\n        open[v] = 0;\n        for (int i = 0; i < (int)resList.size(); ++i) {\n            int k = resList[i];\n            --covCount[k];\n        }\n\n        ll cost2;\n        if (!evaluate_solution(open, cost2, P_tmp, B_tmp)) {\n            // Should not happen, but revert safely\n            open[v] = 1;\n            for (int i = 0; i < (int)resList.size(); ++i) {\n                int k = resList[i];\n                ++covCount[k];\n            }\n            continue;\n        }\n\n        // Update global best\n        if (cost2 < bestCostGlobal) {\n            bestCostGlobal = cost2;\n            for (int i = 1; i <= N; ++i) {\n                P_best[i] = P_tmp[i];\n                open_best[i] = open[i];\n            }\n            for (int j = 0; j < M; ++j) B_best[j] = B_tmp[j];\n        }\n\n        if (cost2 <= curCost) {\n            curCost = cost2;  // keep v closed\n        } else {\n            // Revert closure\n            open[v] = 1;\n            for (int i = 0; i < (int)resList.size(); ++i) {\n                int k = resList[i];\n                ++covCount[k];\n            }\n        }\n    }\n}\n\n// Greedy cover: choose a small set of stations covering all residents (ignoring edge cost).\n// openCov[v] = 1 for chosen stations.\nvoid build_greedy_cover(char openCov[]) {\n    vector<char> covered(K, 0);\n    int uncovered = K;\n    for (int i = 1; i <= N; ++i) openCov[i] = 0;\n\n    while (uncovered > 0) {\n        int bestStation = -1;\n        int bestGain = -1;\n        for (int v = 1; v <= N; ++v) if (!openCov[v]) {\n            int gain = 0;\n            const auto &lis = stationRes[v];\n            for (int idx = 0; idx < (int)lis.size(); ++idx) {\n                int k = lis[idx];\n                if (!covered[k]) ++gain;\n            }\n            if (gain > bestGain) {\n                bestGain = gain;\n                bestStation = v;\n            }\n        }\n        if (bestStation == -1) break;  // safety\n        openCov[bestStation] = 1;\n        const auto &lis = stationRes[bestStation];\n        for (int idx = 0; idx < (int)lis.size(); ++idx) {\n            int k = lis[idx];\n            if (!covered[k]) {\n                covered[k] = 1;\n                --uncovered;\n            }\n        }\n    }\n}\n\n// Cost-aware greedy cover: choose stations considering approximate edge + broadcast cost.\nvoid build_cost_greedy_cover(char openCov[], const ll distFrom1[]) {\n    vector<char> covered(K, 0);\n    int uncovered = K;\n    for (int i = 1; i <= N; ++i) openCov[i] = 0;\n\n    const double ALPHA = 0.3;  // weight for edge distance; (1-ALPHA) for radius^2\n\n    while (uncovered > 0) {\n        int bestStation = -1;\n        double bestScore = 1e100;\n\n        for (int v = 1; v <= N; ++v) if (!openCov[v]) {\n            int gain = 0;\n            const auto &lis = stationRes[v];\n            for (int idx = 0; idx < (int)lis.size(); ++idx) {\n                int k = lis[idx];\n                if (!covered[k]) ++gain;\n            }\n            if (gain <= 0) continue;\n\n            double approxCost =\n                (double)distFrom1[v] * ALPHA +\n                (double)stationMaxR2[v] * (1.0 - ALPHA);\n            double score = approxCost / gain;\n            if (score < bestScore) {\n                bestScore = score;\n                bestStation = v;\n            }\n        }\n        if (bestStation == -1) break;  // safety\n        openCov[bestStation] = 1;\n        const auto &lis = stationRes[bestStation];\n        for (int idx = 0; idx < (int)lis.size(); ++idx) {\n            int k = lis[idx];\n            if (!covered[k]) {\n                covered[k] = 1;\n                --uncovered;\n            }\n        }\n    }\n}\n\n// Simulated annealing on open[] and covCount[] starting from curCost.\nvoid simulated_annealing(char open[], int covCount[], ll &curCost, int steps, mt19937_64 &rng) {\n    uniform_int_distribution<int> distV(1, N);\n    uniform_real_distribution<double> distReal(0.0, 1.0);\n\n    const double T0 = 5e6;\n    const double T1 = 5e3;\n\n    for (int step = 0; step < steps; ++step) {\n        if (chrono::duration<double>(chrono::steady_clock::now() - g_start).count() > 1.9)\n            break;\n\n        int v = distV(rng);\n        const auto &resList = stationRes[v];\n\n        bool closing = (open[v] != 0);\n        if (closing) {\n            bool fail = false;\n            for (int i = 0; i < (int)resList.size(); ++i) {\n                int k = resList[i];\n                if (covCount[k] == 1) {\n                    fail = true;\n                    break;\n                }\n            }\n            if (fail) continue;\n\n            open[v] = 0;\n            for (int i = 0; i < (int)resList.size(); ++i) {\n                int k = resList[i];\n                --covCount[k];\n            }\n\n            ll newCost;\n            if (!evaluate_solution(open, newCost, P_tmp, B_tmp)) {\n                open[v] = 1;\n                for (int i = 0; i < (int)resList.size(); ++i) {\n                    int k = resList[i];\n                    ++covCount[k];\n                }\n                continue;\n            }\n\n            if (newCost < bestCostGlobal) {\n                bestCostGlobal = newCost;\n                for (int i = 1; i <= N; ++i) {\n                    P_best[i] = P_tmp[i];\n                    open_best[i] = open[i];\n                }\n                for (int j = 0; j < M; ++j) B_best[j] = B_tmp[j];\n            }\n\n            ll delta = newCost - curCost;\n            double t = (double)step / (double)steps;\n            double T = T0 * pow(T1 / T0, t);\n            if (delta <= 0) {\n                curCost = newCost;\n            } else {\n                double prob = exp(- (double)delta / T);\n                if (distReal(rng) < prob) {\n                    curCost = newCost;\n                } else {\n                    open[v] = 1;\n                    for (int i = 0; i < (int)resList.size(); ++i) {\n                        int k = resList[i];\n                        ++covCount[k];\n                    }\n                }\n            }\n        } else {\n            open[v] = 1;\n            for (int i = 0; i < (int)resList.size(); ++i) {\n                int k = resList[i];\n                ++covCount[k];\n            }\n\n            ll newCost;\n            if (!evaluate_solution(open, newCost, P_tmp, B_tmp)) {\n                open[v] = 0;\n                for (int i = 0; i < (int)resList.size(); ++i) {\n                    int k = resList[i];\n                    --covCount[k];\n                }\n                continue;\n            }\n\n            if (newCost < bestCostGlobal) {\n                bestCostGlobal = newCost;\n                for (int i = 1; i <= N; ++i) {\n                    P_best[i] = P_tmp[i];\n                    open_best[i] = open[i];\n                }\n                for (int j = 0; j < M; ++j) B_best[j] = B_tmp[j];\n            }\n\n            ll delta = newCost - curCost;\n            double t = (double)step / (double)steps;\n            double T = T0 * pow(T1 / T0, t);\n            if (delta <= 0) {\n                curCost = newCost;\n            } else {\n                double prob = exp(- (double)delta / T);\n                if (distReal(rng) < prob) {\n                    curCost = newCost;\n                } else {\n                    open[v] = 0;\n                    for (int i = 0; i < (int)resList.size(); ++i) {\n                        int k = resList[i];\n                        --covCount[k];\n                    }\n                }\n            }\n        }\n    }\n}\n\n// Final local search: single-station toggles around global best open set.\nvoid final_local_search(const vector<int>& order) {\n    if (chrono::duration<double>(chrono::steady_clock::now() - g_start).count() > 1.95)\n        return;\n\n    static char openLoc[MAXN];\n    for (int i = 1; i <= N; ++i) openLoc[i] = open_best[i];\n    ll curCost = bestCostGlobal;\n\n    bool improved = true;\n    while (improved) {\n        if (chrono::duration<double>(chrono::steady_clock::now() - g_start).count() > 1.98)\n            break;\n        improved = false;\n\n        for (int v : order) {\n            if (chrono::duration<double>(chrono::steady_clock::now() - g_start).count() > 1.98)\n                break;\n            char old = openLoc[v];\n            openLoc[v] ^= 1;\n            ll cost;\n            if (evaluate_solution(openLoc, cost, P_tmp, B_tmp) && cost < curCost) {\n                curCost = cost;\n                improved = true;\n                if (cost < bestCostGlobal) {\n                    bestCostGlobal = cost;\n                    for (int i = 1; i <= N; ++i) {\n                        P_best[i] = P_tmp[i];\n                        open_best[i] = openLoc[i];\n                    }\n                    for (int j = 0; j < M; ++j) B_best[j] = B_tmp[j];\n                }\n            } else {\n                openLoc[v] = old;\n            }\n        }\n    }\n}\n\n// Post-processing: improve broadcast radii P_i for final best edges B_best.\nvoid post_optimize_broadcast(mt19937_64 &rng) {\n    if (chrono::duration<double>(chrono::steady_clock::now() - g_start).count() > 1.95)\n        return;\n\n    ll edgeCost = 0;\n    for (int j = 0; j < M; ++j) {\n        if (B_best[j]) edgeCost += edges[j].w;\n    }\n\n    vector<char> reachable(N + 1, 0);\n    vector<int> q;\n    q.reserve(N);\n    reachable[1] = 1;\n    q.push_back(1);\n    for (int qi = 0; qi < (int)q.size(); ++qi) {\n        int v = q[qi];\n        for (auto &pr : adj[v]) {\n            int to = pr.first;\n            int eid = pr.second;\n            if (!B_best[eid]) continue;\n            if (!reachable[to]) {\n                reachable[to] = 1;\n                q.push_back(to);\n            }\n        }\n    }\n\n    vector<vector<pair<ll,int>>> candReach(K);\n    const ll R2max = 5000LL * 5000LL;\n    for (int k = 0; k < K; ++k) {\n        auto &rc = candReach[k];\n        rc.clear();\n        for (auto &pr : residentCand[k]) {\n            ll d2 = pr.first;\n            int v = pr.second;\n            if (d2 > R2max) break;\n            if (reachable[v]) rc.push_back(pr);\n        }\n        if (rc.empty()) {\n            return;\n        }\n    }\n\n    vector<multiset<ll>> stationSets(N + 1);\n    vector<int> assigned(K);\n    vector<ll> distAssign(K);\n    vector<ll> maxd2(N + 1, 0);\n    vector<int> Pcur(N + 1, 0);\n\n    auto calcP = [](ll m) -> int {\n        if (m == 0) return 0;\n        double sr = sqrt((double)m);\n        ll r = (ll)sr;\n        if (r * r < m) ++r;\n        if (r > 5000) r = 5000;\n        return (int)r;\n    };\n\n    for (int k = 0; k < K; ++k) {\n        auto &rc = candReach[k];\n        auto [d2, s] = rc[0];\n        assigned[k] = s;\n        distAssign[k] = d2;\n        stationSets[s].insert(d2);\n    }\n\n    ll broadcastCost = 0;\n    for (int i = 1; i <= N; ++i) {\n        if (!stationSets[i].empty()) {\n            maxd2[i] = *stationSets[i].rbegin();\n            Pcur[i] = calcP(maxd2[i]);\n            broadcastCost += (ll)Pcur[i] * Pcur[i];\n        } else {\n            maxd2[i] = 0;\n            Pcur[i] = 0;\n        }\n    }\n\n    ll totalCost = broadcastCost + edgeCost;\n    const int PASSES = 2;\n    vector<int> perm(K);\n    iota(perm.begin(), perm.end(), 0);\n\n    for (int pass = 0; pass < PASSES; ++pass) {\n        if (chrono::duration<double>(chrono::steady_clock::now() - g_start).count() > 1.98)\n            break;\n\n        shuffle(perm.begin(), perm.end(), rng);\n        bool any = false;\n\n        for (int idx = 0; idx < K; ++idx) {\n            int k = perm[idx];\n            int s0 = assigned[k];\n            ll d0 = distAssign[k];\n            auto &rc = candReach[k];\n\n            ll bestDelta = 0;\n            int bestS = -1;\n            ll bestNewMax0 = 0, bestNewMax1 = 0;\n            int bestNewP0 = 0, bestNewP1 = 0;\n\n            int trials = (int)rc.size();\n            if (trials > 3) trials = 3;\n\n            for (int t = 0; t < trials; ++t) {\n                int s1 = rc[t].second;\n                ll d1 = rc[t].first;\n                if (s1 == s0) continue;\n\n                ll oldMax0 = maxd2[s0];\n                ll newMax0;\n                auto &S0 = stationSets[s0];\n                if (d0 < oldMax0) {\n                    newMax0 = oldMax0;\n                } else {\n                    auto it0 = S0.find(d0);\n                    if (it0 == S0.end()) continue;\n                    S0.erase(it0);\n                    newMax0 = S0.empty() ? 0 : *S0.rbegin();\n                    S0.insert(d0);\n                }\n\n                ll oldMax1 = maxd2[s1];\n                ll newMax1 = oldMax1;\n                if (d1 > oldMax1) newMax1 = d1;\n\n                ll oldP0 = Pcur[s0], oldP1 = Pcur[s1];\n                ll oldC = oldP0 * oldP0 + oldP1 * oldP1;\n\n                int newP0 = calcP(newMax0);\n                int newP1 = calcP(newMax1);\n                ll newC = (ll)newP0 * newP0 + (ll)newP1 * newP1;\n\n                ll delta = newC - oldC;\n                if (delta < bestDelta) {\n                    bestDelta = delta;\n                    bestS = s1;\n                    bestNewMax0 = newMax0;\n                    bestNewMax1 = newMax1;\n                    bestNewP0 = newP0;\n                    bestNewP1 = newP1;\n                }\n            }\n\n            if (bestS != -1) {\n                int s1 = bestS;\n                ll d1 = 0;\n                for (auto &pr : rc) {\n                    if (pr.second == s1) {\n                        d1 = pr.first;\n                        break;\n                    }\n                }\n\n                auto &S0 = stationSets[s0];\n                auto it0 = S0.find(d0);\n                if (it0 != S0.end()) S0.erase(it0);\n\n                auto &S1 = stationSets[s1];\n                S1.insert(d1);\n\n                assigned[k] = s1;\n                distAssign[k] = d1;\n\n                broadcastCost += bestDelta;\n                maxd2[s0] = bestNewMax0;\n                maxd2[s1] = bestNewMax1;\n                Pcur[s0] = bestNewP0;\n                Pcur[s1] = bestNewP1;\n\n                any = true;\n            }\n        }\n\n        if (!any) break;\n    }\n\n    totalCost = broadcastCost + edgeCost;\n    if (totalCost < bestCostGlobal) {\n        bestCostGlobal = totalCost;\n        for (int i = 1; i <= N; ++i) {\n            P_best[i] = Pcur[i];\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    g_start = chrono::steady_clock::now();\n\n    cin >> N >> M >> K;\n    for (int i = 1; i <= N; ++i) {\n        cin >> vx[i] >> vy[i];\n    }\n    for (int j = 0; j < M; ++j) {\n        int u, v;\n        ll w;\n        cin >> u >> v >> w;\n        edges[j] = {u, v, w};\n    }\n    for (int k = 0; k < K; ++k) {\n        cin >> ax_arr[k] >> ay_arr[k];\n    }\n\n    for (int i = 1; i <= N; ++i) adj[i].clear();\n    for (int j = 0; j < M; ++j) {\n        int u = edges[j].u;\n        int v = edges[j].v;\n        adj[u].push_back({v, j});\n        adj[v].push_back({u, j});\n    }\n\n    // All-pairs shortest paths\n    for (int s = 1; s <= N; ++s) {\n        for (int i = 1; i <= N; ++i) {\n            distAll[s][i] = INFLL;\n            parEdge[s][i] = -1;\n        }\n        distAll[s][s] = 0;\n        priority_queue<pair<ll,int>, vector<pair<ll,int>>, greater<pair<ll,int>>> pq;\n        pq.push({0, s});\n        while (!pq.empty()) {\n            auto [d, v] = pq.top();\n            pq.pop();\n            if (d != distAll[s][v]) continue;\n            for (auto &pr : adj[v]) {\n                int to = pr.first;\n                int eidx = pr.second;\n                ll nd = d + edges[eidx].w;\n                if (nd < distAll[s][to]) {\n                    distAll[s][to] = nd;\n                    parEdge[s][to] = eidx;\n                    pq.push({nd, to});\n                }\n            }\n        }\n    }\n\n    ll distFrom1[MAXN];\n    for (int i = 1; i <= N; ++i) {\n        distFrom1[i] = distAll[1][i];\n    }\n\n    const ll R2max = 5000LL * 5000LL;\n    for (int k = 0; k < K; ++k) {\n        auto &cand = residentCand[k];\n        cand.clear();\n        cand.reserve(N);\n        for (int v = 1; v <= N; ++v) {\n            ll dx = vx[v] - ax_arr[k];\n            ll dy = vy[v] - ay_arr[k];\n            ll d2 = dx * dx + dy * dy;\n            if (d2 <= R2max) {\n                cand.emplace_back(d2, v);\n            }\n        }\n        sort(cand.begin(), cand.end(),\n             [](const pair<ll,int> &a, const pair<ll,int> &b){ return a.first < b.first; });\n    }\n\n    for (int v = 1; v <= N; ++v) stationRes[v].clear();\n    for (int k = 0; k < K; ++k) {\n        const auto &cand = residentCand[k];\n        for (auto &pr : cand) {\n            int v = pr.second;\n            stationRes[v].push_back(k);\n        }\n    }\n\n    for (int v = 1; v <= N; ++v) stationMaxR2[v] = 0;\n    for (int k = 0; k < K; ++k) {\n        const auto &cand = residentCand[k];\n        for (auto &pr : cand) {\n            ll d2 = pr.first;\n            int v = pr.second;\n            if (stationMaxR2[v] < d2) stationMaxR2[v] = d2;\n        }\n    }\n\n    ordEdges.resize(M);\n    iota(ordEdges.begin(), ordEdges.end(), 0);\n    sort(ordEdges.begin(), ordEdges.end(),\n         [&](int a, int b){ return edges[a].w < edges[b].w; });\n\n    vector<int> order;\n    order.reserve(N);\n    for (int i = 1; i <= N; ++i) order.push_back(i);\n    sort(order.begin(), order.end(),\n         [&](int a, int b){ return distFrom1[a] > distFrom1[b]; });\n\n    mt19937_64 rng(20231118ULL);\n\n    static int covCount1[MAXK], covCount2[MAXK], covCount3[MAXK];\n\n    // Scenario 1\n    static char open1[MAXN];\n    for (int i = 1; i <= N; ++i) open1[i] = 1;\n    for (int k = 0; k < K; ++k) {\n        covCount1[k] = (int)residentCand[k].size();\n    }\n\n    ll cost1;\n    bool ok1 = evaluate_solution(open1, cost1, P_tmp, B_tmp);\n    if (!ok1) {\n        for (int i = 1; i <= N; ++i) P_best[i] = 5000;\n        for (int j = 0; j < M; ++j) B_best[j] = 1;\n        cout << P_best[1];\n        for (int i = 2; i <= N; ++i) cout << ' ' << P_best[i];\n        cout << '\\n';\n        if (M > 0) {\n            cout << (int)B_best[0];\n            for (int j = 1; j < M; ++j) cout << ' ' << (int)B_best[j];\n        }\n        cout << '\\n';\n        return 0;\n    }\n    bestCostGlobal = cost1;\n    for (int i = 1; i <= N; ++i) {\n        P_best[i] = P_tmp[i];\n        open_best[i] = open1[i];\n    }\n    for (int j = 0; j < M; ++j) B_best[j] = B_tmp[j];\n\n    greedy_removal(open1, cost1, order, covCount1);\n\n    // Scenario 2\n    static char open2[MAXN];\n    build_greedy_cover(open2);\n    for (int k = 0; k < K; ++k) {\n        int cnt = 0;\n        const auto &cand = residentCand[k];\n        for (auto &pr : cand) {\n            int v = pr.second;\n            if (open2[v]) ++cnt;\n        }\n        covCount2[k] = cnt;\n    }\n    ll cost2;\n    bool ok2 = evaluate_solution(open2, cost2, P_tmp, B_tmp);\n    if (ok2) {\n        if (cost2 < bestCostGlobal) {\n            bestCostGlobal = cost2;\n            for (int i = 1; i <= N; ++i) {\n                P_best[i] = P_tmp[i];\n                open_best[i] = open2[i];\n            }\n            for (int j = 0; j < M; ++j) B_best[j] = B_tmp[j];\n        }\n        greedy_removal(open2, cost2, order, covCount2);\n    } else {\n        for (int i = 1; i <= N; ++i) open2[i] = open1[i];\n        for (int k = 0; k < K; ++k) covCount2[k] = covCount1[k];\n        cost2 = cost1;\n    }\n\n    // Scenario 3\n    static char open3[MAXN];\n    build_cost_greedy_cover(open3, distFrom1);\n    for (int k = 0; k < K; ++k) {\n        int cnt = 0;\n        const auto &cand = residentCand[k];\n        for (auto &pr : cand) {\n            int v = pr.second;\n            if (open3[v]) ++cnt;\n        }\n        covCount3[k] = cnt;\n    }\n    ll cost3;\n    bool ok3 = evaluate_solution(open3, cost3, P_tmp, B_tmp);\n    if (ok3) {\n        if (cost3 < bestCostGlobal) {\n            bestCostGlobal = cost3;\n            for (int i = 1; i <= N; ++i) {\n                P_best[i] = P_tmp[i];\n                open_best[i] = open3[i];\n            }\n            for (int j = 0; j < M; ++j) B_best[j] = B_tmp[j];\n        }\n        greedy_removal(open3, cost3, order, covCount3);\n    } else {\n        for (int i = 1; i <= N; ++i) open3[i] = open1[i];\n        for (int k = 0; k < K; ++k) covCount3[k] = covCount1[k];\n        cost3 = cost1;\n    }\n\n    // SA from best scenario\n    char *openStart = open1;\n    int  *covStart  = covCount1;\n    ll curCost      = cost1;\n    if (cost2 < curCost) {\n        openStart = open2;\n        covStart  = covCount2;\n        curCost   = cost2;\n    }\n    if (cost3 < curCost) {\n        openStart = open3;\n        covStart  = covCount3;\n        curCost   = cost3;\n    }\n    const int SA_STEPS_TOTAL = 6000;\n    simulated_annealing(openStart, covStart, curCost, SA_STEPS_TOTAL, rng);\n\n    // Final local search on open_best\n    static int covCountBest[MAXK];\n    for (int k = 0; k < K; ++k) {\n        int cnt = 0;\n        const auto &cand = residentCand[k];\n        for (auto &pr : cand) {\n            int v = pr.second;\n            if (open_best[v]) ++cnt;\n        }\n        covCountBest[k] = cnt;\n    }\n    ll dummyCost = bestCostGlobal;\n    greedy_removal(open_best, dummyCost, order, covCountBest);\n    final_local_search(order);\n\n    post_optimize_broadcast(rng);\n\n    cout << P_best[1];\n    for (int i = 2; i <= N; ++i) {\n        cout << ' ' << P_best[i];\n    }\n    cout << '\\n';\n\n    if (M > 0) {\n        cout << (int)B_best[0];\n        for (int j = 1; j < M; ++j) {\n            cout << ' ' << (int)B_best[j];\n        }\n    }\n    cout << '\\n';\n\n    return 0;\n}","ahc021":"#include <bits/stdc++.h>\nusing namespace std;\n\n// ---------------- Structures ----------------\n\nstruct Edge {\n    int u, v; // node indices\n};\n\nstruct Op {\n    short x1, y1, x2, y2; // coordinates of swapped cells\n};\n\n// ---------------- RNG (xorshift) ----------------\n\nstruct XorShift {\n    uint64_t x;\n    XorShift(uint64_t seed = 123456789) : x(seed) {}\n    uint64_t operator()() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return x;\n    }\n    int next_int(int n) { // 0..n-1\n        return (int)(operator()() % (uint64_t)n);\n    }\n};\n\n// ---------------- Violation computation ----------------\n\nint computeE(const vector<int> &a, const vector<Edge> &dEdges) {\n    int E = 0;\n    for (const auto &e : dEdges) {\n        if (a[e.u] > a[e.v]) ++E;\n    }\n    return E;\n}\n\n// Precomputed \u0394E for an adjacent edge using only affected DAG edges\ninline int calc_delta_adj_edge(\n    int eIdx,\n    const vector<int> &a,\n    const vector<Edge> &dEdges,\n    const vector<Edge> &adjEdges,\n    const vector<vector<int>> &adj2dag\n) {\n    const Edge &ae = adjEdges[eIdx];\n    int u = ae.u;\n    int v = ae.v;\n    const auto &lst = adj2dag[eIdx];\n\n    int delta = 0;\n    int valU = a[u], valV = a[v];\n\n    for (int deid : lst) {\n        const Edge &de = dEdges[deid];\n        int aIdx = de.u;\n        int bIdx = de.v;\n\n        int beforeA = a[aIdx];\n        int beforeB = a[bIdx];\n        bool before = (beforeA > beforeB);\n\n        int afterA = (aIdx == u ? valV : (aIdx == v ? valU : beforeA));\n        int afterB = (bIdx == u ? valV : (bIdx == v ? valU : beforeB));\n        bool after = (afterA > afterB);\n\n        delta += (int)after - (int)before;\n    }\n    return delta;\n}\n\n// ---------------- One heuristic run ----------------\n\nvoid run_single(const vector<int> &initial,\n                const vector<Edge> &dEdges,\n                const vector<Edge> &adjEdges,\n                const vector<vector<int>> &nodeAdjEdges,\n                const vector<vector<int>> &adj2dag,\n                const vector<int> &posX,\n                const vector<int> &posY,\n                XorShift &rng,\n                vector<Op> &opsOut,\n                int &EOut) {\n    const int maxK = 10000;\n    vector<int> a = initial;\n\n    vector<Op> ops;\n    ops.reserve(maxK);\n\n    int K = 0;\n    int E = computeE(a, dEdges);\n\n    // ---------- Stage 1: coarse bubbling along parent-child DAG edges ----------\n    const int limitStage1       = maxK * 8 / 10; // up to 8000 swaps\n    const int E_threshold       = 30;            // stop Stage1 once E is small\n    const int recalc_interval_1 = 256;           // periodically recompute E\n\n    if (E > 0) {\n        int dM = (int)dEdges.size();\n        bool done = false;\n        while (K < limitStage1 && !done) {\n            bool swappedPass = false;\n            int start = rng.next_int(dM);\n\n            for (int t = 0; t < dM && K < limitStage1; ++t) {\n                const Edge &ed = dEdges[(start + t) % dM];\n                int u = ed.u;\n                int v = ed.v;\n                if (a[u] > a[v]) {\n                    swap(a[u], a[v]);\n                    ops.push_back(Op{(short)posX[u], (short)posY[u],\n                                     (short)posX[v], (short)posY[v]});\n                    ++K;\n                    swappedPass = true;\n\n                    if ((K % recalc_interval_1 == 0) || K >= limitStage1) {\n                        E = computeE(a, dEdges);\n                        if (E == 0 || E <= E_threshold || K >= limitStage1) {\n                            done = true;\n                            break;\n                        }\n                    }\n                }\n            }\n            if (!swappedPass) {\n                // No violating parent-child edge => E = 0\n                E = 0;\n                done = true;\n                break;\n            }\n        }\n    }\n\n    // ---------- Stage 2: PQ-based best-improvement + random kicks ----------\n    if (E != 0 && K < maxK) {\n        E = computeE(a, dEdges); // ensure accurate\n        int M = (int)adjEdges.size();\n\n        vector<int> curDelta(M);\n        using PQItem = pair<int,int>;\n        priority_queue<PQItem, vector<PQItem>, greater<PQItem>> pq;\n\n        // Initialize all \u0394E\n        for (int ei = 0; ei < M; ++ei) {\n            int d = calc_delta_adj_edge(ei, a, dEdges, adjEdges, adj2dag);\n            curDelta[ei] = d;\n            pq.push({d, ei});\n        }\n\n        const int maxKickMoves  = 25;\n        const int maxKickDelta  = 4;\n\n        int kicksUsed = 0;\n\n        auto apply_swap_and_update = [&](int edgeIdx, int delta) {\n            const Edge &edge = adjEdges[edgeIdx];\n            int u = edge.u;\n            int v = edge.v;\n\n            // Perform swap\n            swap(a[u], a[v]);\n            ops.push_back(Op{(short)posX[u], (short)posY[u],\n                             (short)posX[v], (short)posY[v]});\n            ++K;\n            E += delta;\n\n            // Update incident adjacent edges\n            auto update_edge = [&](int ei) {\n                int d = calc_delta_adj_edge(ei, a, dEdges, adjEdges, adj2dag);\n                curDelta[ei] = d;\n                pq.push({d, ei});\n            };\n            for (int ei : nodeAdjEdges[u]) update_edge(ei);\n            for (int ei : nodeAdjEdges[v]) update_edge(ei);\n        };\n\n        while (K < maxK && E > 0) {\n            // Get best (most negative) up-to-date \u0394E\n            PQItem top;\n            bool found = false;\n            while (!pq.empty()) {\n                top = pq.top();\n                int d = top.first;\n                int idx = top.second;\n                if (curDelta[idx] != d) {\n                    pq.pop();\n                    continue;\n                }\n                found = true;\n                break;\n            }\n            if (!found) break;\n\n            int bestDelta = top.first;\n            int bestIdx   = top.second;\n\n            if (bestDelta < 0) {\n                // improvement\n                apply_swap_and_update(bestIdx, bestDelta);\n                continue;\n            }\n\n            // No improving swap -> random kicks\n            if (kicksUsed >= maxKickMoves || bestDelta > maxKickDelta) break;\n\n            apply_swap_and_update(bestIdx, bestDelta);\n            if (bestDelta > 0) ++kicksUsed;\n        }\n    }\n\n    EOut = computeE(a, dEdges);\n    opsOut.swap(ops);\n}\n\n// ---------------- Main ----------------\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    const int N = 30;\n    const int numNodes = N * (N + 1) / 2;\n\n    // Read input and build id / coordinate mapping\n    vector<int> a0(numNodes);\n    vector<int> posX(numNodes), posY(numNodes);\n    vector<vector<int>> id(N);\n    int cur = 0;\n    for (int x = 0; x < N; ++x) {\n        id[x].resize(x + 1);\n        for (int y = 0; y <= x; ++y) {\n            id[x][y] = cur;\n            posX[cur] = x;\n            posY[cur] = y;\n            int v;\n            cin >> v;\n            a0[cur] = v;\n            ++cur;\n        }\n    }\n\n    // Build DAG edges (parent -> child)\n    vector<Edge> dEdges;\n    dEdges.reserve(2 * (N - 1) * N / 2);\n    for (int x = 0; x < N - 1; ++x) {\n        for (int y = 0; y <= x; ++y) {\n            int p = id[x][y];\n            int c1 = id[x + 1][y];\n            int c2 = id[x + 1][y + 1];\n            dEdges.push_back(Edge{p, c1});\n            dEdges.push_back(Edge{p, c2});\n        }\n    }\n\n    // For each node, list incident DAG edges\n    int dM = (int)dEdges.size();\n    vector<vector<int>> nodeEdgeIds(numNodes);\n    for (int ei = 0; ei < dM; ++ei) {\n        int u = dEdges[ei].u;\n        int v = dEdges[ei].v;\n        nodeEdgeIds[u].push_back(ei);\n        nodeEdgeIds[v].push_back(ei);\n    }\n\n    // Build adjacency edges of triangular grid (undirected) + nodeAdjEdges\n    const int dx[6] = {-1, -1, 0, 0, 1, 1};\n    const int dy[6] = {-1, 0, -1, 1, 0, 1};\n\n    vector<Edge> adjEdges;\n    adjEdges.reserve(3 * numNodes);\n    vector<vector<int>> nodeAdjEdges(numNodes);\n\n    for (int x = 0; x < N; ++x) {\n        for (int y = 0; y <= x; ++y) {\n            int u = id[x][y];\n            for (int dir = 0; dir < 6; ++dir) {\n                int nx = x + dx[dir];\n                int ny = y + dy[dir];\n                if (nx < 0 || nx >= N) continue;\n                if (ny < 0 || ny > nx) continue;\n                int v = id[nx][ny];\n                if (v > u) {\n                    int idxEdge = (int)adjEdges.size();\n                    adjEdges.push_back(Edge{u, v});\n                    nodeAdjEdges[u].push_back(idxEdge);\n                    nodeAdjEdges[v].push_back(idxEdge);\n                }\n            }\n        }\n    }\n\n    int M = (int)adjEdges.size();\n\n    // Precompute, for each adjacent edge, the list of DAG edges affected by swapping its endpoints\n    vector<vector<int>> adj2dag(M);\n    for (int ei = 0; ei < M; ++ei) {\n        int u = adjEdges[ei].u;\n        int v = adjEdges[ei].v;\n        vector<int> lst;\n        for (int idE : nodeEdgeIds[u]) lst.push_back(idE);\n        for (int idE : nodeEdgeIds[v]) {\n            bool dup = false;\n            for (int x : lst) {\n                if (x == idE) { dup = true; break; }\n            }\n            if (!dup) lst.push_back(idE);\n        }\n        adj2dag[ei] = std::move(lst);\n    }\n\n    // RNG\n    uint64_t seed = chrono::steady_clock::now().time_since_epoch().count();\n    XorShift rng(seed);\n\n    // Time-limited multiple restarts; keep the best result\n    const double TIME_LIMIT = 1.9; // seconds (slightly increased for more restarts)\n    const int MAX_RESTARTS_LIMIT = 1000;\n    auto t0 = chrono::steady_clock::now();\n\n    vector<Op> bestOps;\n    int bestE = INT_MAX;\n    int bestK = INT_MAX;\n\n    for (int iter = 0; iter < MAX_RESTARTS_LIMIT; ++iter) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - t0).count();\n        if (elapsed > TIME_LIMIT) break;\n\n        vector<Op> curOps;\n        int curE;\n        run_single(a0, dEdges, adjEdges, nodeAdjEdges, adj2dag,\n                   posX, posY, rng, curOps, curE);\n        int curK = (int)curOps.size();\n\n        if (curE < bestE || (curE == bestE && curK < bestK)) {\n            bestE = curE;\n            bestK = curK;\n            bestOps = std::move(curOps);\n        }\n    }\n\n    // Output best sequence found\n    cout << bestOps.size() << '\\n';\n    for (const auto &op : bestOps) {\n        cout << op.x1 << ' ' << op.y1 << ' '\n             << op.x2 << ' ' << op.y2 << '\\n';\n    }\n\n    return 0;\n}","toyota2023summer-final":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Cell {\n    int r, c, dist;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int D, N;\n    if (!(cin >> D >> N)) return 0;\n\n    const int er = 0;\n    const int ec = (D - 1) / 2;\n\n    vector<vector<bool>> isObstacle(D, vector<bool>(D, false));\n    for (int k = 0; k < N; ++k) {\n        int r, c;\n        cin >> r >> c;\n        isObstacle[r][c] = true;\n    }\n\n    // 1. Static BFS distances from entrance (considering only obstacles).\n    vector<vector<int>> dist(D, vector<int>(D, -1));\n    {\n        queue<pair<int,int>> q;\n        dist[er][ec] = 0;\n        q.push({er, ec});\n        const int dr[4] = {1, -1, 0, 0};\n        const int dc[4] = {0, 0, 1, -1};\n        while (!q.empty()) {\n            auto [r, c] = q.front();\n            q.pop();\n            for (int d = 0; d < 4; ++d) {\n                int nr = r + dr[d];\n                int nc = c + dc[d];\n                if (nr < 0 || nr >= D || nc < 0 || nc >= D) continue;\n                if (isObstacle[nr][nc]) continue;\n                if (dist[nr][nc] != -1) continue;\n                dist[nr][nc] = dist[r][c] + 1;\n                q.push({nr, nc});\n            }\n        }\n    }\n\n    // 2. Collect storeable cells (non-entrance, non-obstacle) with distances.\n    vector<Cell> cells;\n    cells.reserve(D * D);\n    for (int r = 0; r < D; ++r) {\n        for (int c = 0; c < D; ++c) {\n            if (r == er && c == ec) continue;\n            if (isObstacle[r][c]) continue;\n            cells.push_back({r, c, dist[r][c]});\n        }\n    }\n    int M = (int)cells.size(); // D^2 - 1 - N\n\n    // 3. Sort cells by distance from entrance, then row, then column.\n    sort(cells.begin(), cells.end(), [](const Cell &a, const Cell &b) {\n        if (a.dist != b.dist) return a.dist < b.dist;\n        if (a.r != b.r) return a.r < b.r;\n        return a.c < b.c;\n    });\n\n    // Occupancy and labels.\n    vector<vector<bool>> hasContainer(D, vector<bool>(D, false));\n    vector<vector<int>>  labelGrid(D, vector<int>(D, -1));\n    vector<bool> usedIndex(M, false);          // whether cells[i] already has a container\n    vector<int> assignedIdxOfLabel(M, -1);     // index of cell for each label (if assigned)\n\n    // BFS to count reachable empty cells (excluding entrance) from entrance,\n    // with current hasContainer + isObstacle.\n    auto bfs_count_reachable_empty = [&]() -> int {\n        vector<vector<char>> vis(D, vector<char>(D, 0));\n        queue<pair<int,int>> q;\n        vis[er][ec] = 1;\n        q.push({er, ec});\n        const int dr[4] = {1, -1, 0, 0};\n        const int dc[4] = {0, 0, 1, -1};\n\n        while (!q.empty()) {\n            auto [r, c] = q.front();\n            q.pop();\n            for (int d = 0; d < 4; ++d) {\n                int nr = r + dr[d];\n                int nc = c + dc[d];\n                if (nr < 0 || nr >= D || nc < 0 || nc >= D) continue;\n                if (vis[nr][nc]) continue;\n                if (isObstacle[nr][nc]) continue;\n                if (hasContainer[nr][nc]) continue;\n                vis[nr][nc] = 1;\n                q.push({nr, nc});\n            }\n        }\n\n        int cnt = 0;\n        for (int r = 0; r < D; ++r) {\n            for (int c = 0; c < D; ++c) {\n                if (r == er && c == ec) continue;\n                if (isObstacle[r][c]) continue;\n                if (hasContainer[r][c]) continue;\n                if (vis[r][c]) ++cnt;\n            }\n        }\n        return cnt;\n    };\n\n    auto is_safe_index = [&](int idx, int placed) -> bool {\n        const Cell &cell = cells[idx];\n        int r = cell.r, c = cell.c;\n        hasContainer[r][c] = true;\n        int reachableEmpty = bfs_count_reachable_empty();\n        hasContainer[r][c] = false;\n        int emptiesAfter = M - (placed + 1);\n        return reachableEmpty == emptiesAfter;\n    };\n\n    // 4. Storage phase: choose safe index minimizing weighted crossings with assigned labels.\n    //    We weight \"smaller labels placed deeper\" more heavily.\n    for (int step = 0; step < M; ++step) {\n        int t;\n        cin >> t;\n\n        int bestIdx   = -1;\n        int bestInv   = INT_MAX;\n        int bestDelta = INT_MAX;\n\n        for (int i = 0; i < M; ++i) {\n            if (usedIndex[i]) continue;\n            if (!is_safe_index(i, step)) continue;\n\n            int cross_small_right = 0;\n            int cross_large_left  = 0;\n\n            // Smaller labels placed deeper than i.\n            for (int l = 0; l < t; ++l) {\n                int idxL = assignedIdxOfLabel[l];\n                if (idxL != -1 && idxL > i) ++cross_small_right;\n            }\n            // Larger labels placed shallower than i.\n            for (int l = t + 1; l < M; ++l) {\n                int idxL = assignedIdxOfLabel[l];\n                if (idxL != -1 && idxL < i) ++cross_large_left;\n            }\n\n            // Weight smaller-label-deeper crossings more heavily.\n            int inv   = 2 * cross_small_right + cross_large_left;\n            int delta = abs(i - t);\n\n            if (inv < bestInv ||\n                (inv == bestInv && delta < bestDelta)) {\n                bestInv   = inv;\n                bestDelta = delta;\n                bestIdx   = i;\n            }\n        }\n\n        // Fallback: if somehow no safe index is found (should be extremely rare),\n        // pick any free index.\n        if (bestIdx == -1) {\n            for (int i = 0; i < M; ++i) {\n                if (!usedIndex[i]) {\n                    bestIdx = i;\n                    break;\n                }\n            }\n        }\n\n        usedIndex[bestIdx] = true;\n        assignedIdxOfLabel[t] = bestIdx;\n\n        int r = cells[bestIdx].r;\n        int c = cells[bestIdx].c;\n        hasContainer[r][c] = true;\n        labelGrid[r][c] = t;\n\n        cout << r << ' ' << c << '\\n' << flush;\n    }\n\n    // 5. Retrieval phase: always remove the smallest label currently accessible.\n    auto bfs_reachable_empty = [&](vector<vector<char>> &vis) {\n        vis.assign(D, vector<char>(D, 0));\n        queue<pair<int,int>> q;\n        vis[er][ec] = 1;\n        q.push({er, ec});\n        const int dr[4] = {1, -1, 0, 0};\n        const int dc[4] = {0, 0, 1, -1};\n        while (!q.empty()) {\n            auto [r, c] = q.front();\n            q.pop();\n            for (int d = 0; d < 4; ++d) {\n                int nr = r + dr[d];\n                int nc = c + dc[d];\n                if (nr < 0 || nr >= D || nc < 0 || nc >= D) continue;\n                if (vis[nr][nc]) continue;\n                if (isObstacle[nr][nc]) continue;\n                if (hasContainer[nr][nc]) continue;\n                vis[nr][nc] = 1;\n                q.push({nr, nc});\n            }\n        }\n    };\n\n    const int dr4[4] = {1, -1, 0, 0};\n    const int dc4[4] = {0, 0, 1, -1};\n    vector<vector<char>> vis;\n\n    for (int step = 0; step < M; ++step) {\n        bfs_reachable_empty(vis);\n\n        int bestLabel = INT_MAX;\n        int bestR = -1, bestC = -1;\n\n        for (int r = 0; r < D; ++r) {\n            for (int c = 0; c < D; ++c) {\n                if (!hasContainer[r][c]) continue;\n                bool accessible = false;\n                for (int d = 0; d < 4; ++d) {\n                    int nr = r + dr4[d];\n                    int nc = c + dc4[d];\n                    if (nr < 0 || nr >= D || nc < 0 || nc >= D) continue;\n                    if (isObstacle[nr][nc]) continue;\n                    if (hasContainer[nr][nc]) continue; // neighbor must be empty\n                    if (vis[nr][nc]) {\n                        accessible = true;\n                        break;\n                    }\n                }\n                if (!accessible) continue;\n                int lbl = labelGrid[r][c];\n                if (lbl < bestLabel) {\n                    bestLabel = lbl;\n                    bestR = r;\n                    bestC = c;\n                }\n            }\n        }\n\n        // Fallback (should not happen if storage kept empties connected).\n        if (bestR == -1) {\n            for (int r = 0; r < D && bestR == -1; ++r)\n                for (int c = 0; c < D && bestR == -1; ++c)\n                    if (hasContainer[r][c]) {\n                        bestR = r;\n                        bestC = c;\n                    }\n        }\n\n        cout << bestR << ' ' << bestC << '\\n';\n        hasContainer[bestR][bestC] = false;\n        labelGrid[bestR][bestC] = -1;\n    }\n\n    cout.flush();\n    return 0;\n}","ahc024":"#include <bits/stdc++.h>\nusing namespace std;\n\n// Constants\nconst int MAXM = 100;\nconst int MAXN = 50;\n\nint n, m; // n = 50, m = 100\n\n// Original grid\nvector<vector<int>> orig_grid;\n\n// Original adjacency matrix: adj_orig[a][b] is true iff colors a and b are adjacent in the original map\nbool adj_orig[MAXM + 1][MAXM + 1];\n\n// Current adjacency as edge counts (for each unordered pair a<b): number of edges between colors a and b\nint edgeCount[MAXM + 1][MAXM + 1];\n\n// Number of outside-adjacency edges for each cell (i,j)\nint outsideAdjEdges[MAXN + 1][MAXN + 1];\n\n// Whether color c may touch 0 (i.e., had adjacency with 0 in original)\nbool allowedZeroAdj[MAXM + 1];\n\n// Directions for 4-neighborhood\nconst int DX[4] = {1, -1, 0, 0};\nconst int DY[4] = {0, 0, 1, -1};\n\n// Compute adjacency matrix for a given grid (used only for the original grid)\nvoid computeAdj(const vector<vector<int>> &g, bool adj[MAXM + 1][MAXM + 1]) {\n    for (int i = 0; i <= m; i++) {\n        for (int j = 0; j <= m; j++) {\n            adj[i][j] = false;\n        }\n    }\n\n    // Internal adjacency in the grid\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            int a = g[i][j];\n            if (i + 1 < n) {\n                int b = g[i + 1][j];\n                if (a != b) adj[a][b] = adj[b][a] = true;\n            }\n            if (j + 1 < n) {\n                int b = g[i][j + 1];\n                if (a != b) adj[a][b] = adj[b][a] = true;\n            }\n        }\n    }\n\n    // Adjacency with outside (color 0) via boundary cells\n    for (int i = 0; i < n; i++) {\n        int c1 = g[i][0];\n        if (c1 != 0) adj[0][c1] = adj[c1][0] = true;\n        int c2 = g[i][n - 1];\n        if (c2 != 0) adj[0][c2] = adj[c2][0] = true;\n    }\n    for (int j = 1; j < n - 1; j++) {\n        int c1 = g[0][j];\n        if (c1 != 0) adj[0][c1] = adj[c1][0] = true;\n        int c2 = g[n - 1][j];\n        if (c2 != 0) adj[0][c2] = adj[c2][0] = true;\n    }\n}\n\n// Initialize edgeCount[a][b] from a given grid\nvoid initAdjCounts(const vector<vector<int>> &g) {\n    for (int i = 0; i <= m; i++) {\n        for (int j = 0; j <= m; j++) {\n            edgeCount[i][j] = 0;\n        }\n    }\n\n    // Internal edges in the grid\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            int a = g[i][j];\n            if (i + 1 < n) {\n                int b = g[i + 1][j];\n                if (a != b) {\n                    int x = min(a, b), y = max(a, b);\n                    edgeCount[x][y]++;\n                }\n            }\n            if (j + 1 < n) {\n                int b = g[i][j + 1];\n                if (a != b) {\n                    int x = min(a, b), y = max(a, b);\n                    edgeCount[x][y]++;\n                }\n            }\n        }\n    }\n\n    // Outside adjacency (between color 0 and each boundary cell's color)\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            int c = g[i][j];\n            int outE = outsideAdjEdges[i][j];\n            if (outE > 0 && c != 0) {\n                int x = 0, y = c; // 0 < c\n                edgeCount[x][y] += outE;\n            }\n        }\n    }\n}\n\n// Check that after removing cell (x, y) from color 'col',\n// the remaining cells of 'col' stay connected.\n//\n// grid[x][y] must already be recolored to something != col before calling.\nbool checkColorConnectivityAfterRemoval(int x, int y, int col, const vector<vector<int>> &grid) {\n    // Collect same-color neighbors of (x, y)\n    pair<int,int> nbrs[4];\n    int k = 0;\n    for (int dir = 0; dir < 4; dir++) {\n        int nx = x + DX[dir];\n        int ny = y + DY[dir];\n        if (nx < 0 || nx >= n || ny < 0 || ny >= n) continue;\n        if (grid[nx][ny] == col) {\n            nbrs[k++] = {nx, ny};\n        }\n    }\n    if (k <= 1) {\n        // Vertex with degree <=1 in its color component cannot be articulation\n        return true;\n    }\n\n    // BFS from first neighbor, check if we can reach all other neighbors\n    static vector<char> vis;\n    int N = n * n;\n    if ((int)vis.size() != N) vis.assign(N, 0);\n    else fill(vis.begin(), vis.end(), 0);\n\n    auto idx_of = [&](int xx, int yy) { return xx * n + yy; };\n\n    queue<pair<int,int>> q;\n    q.push(nbrs[0]);\n    vis[idx_of(nbrs[0].first, nbrs[0].second)] = 1;\n\n    bool reached[4] = {false,false,false,false};\n    reached[0] = true;\n    int reachedCnt = 1;\n\n    while (!q.empty() && reachedCnt < k) {\n        auto [cx, cy] = q.front(); q.pop();\n        for (int dir = 0; dir < 4; dir++) {\n            int nx = cx + DX[dir];\n            int ny = cy + DY[dir];\n            if (nx < 0 || nx >= n || ny < 0 || ny >= n) continue;\n            if (grid[nx][ny] != col) continue;\n            int idx = idx_of(nx, ny);\n            if (vis[idx]) continue;\n            vis[idx] = 1;\n            q.emplace(nx, ny);\n\n            // Check if this is one of the neighbors of (x,y)\n            for (int t = 1; t < k; t++) {\n                if (!reached[t] && nbrs[t].first == nx && nbrs[t].second == ny) {\n                    reached[t] = true;\n                    reachedCnt++;\n                    break;\n                }\n            }\n        }\n    }\n    return (reachedCnt == k);\n}\n\n// Try to change cell (x, y) from its current color to 0.\nbool tryChangeToZero(int x, int y,\n                     vector<vector<int>> &grid,\n                     vector<int> &countColor,\n                     mt19937_64 &rng) {\n    int oldCol = grid[x][y];\n    if (oldCol == 0) return false;\n    if (countColor[oldCol] <= 1) return false; // don't delete last cell of a color\n\n    // Condition for 0 connectivity: new 0 must be on boundary or adjacent to an existing 0\n    bool boundary = (x == 0 || x == n - 1 || y == 0 || y == n - 1);\n    bool adjZero = false;\n    if (!boundary) {\n        for (int dir = 0; dir < 4; dir++) {\n            int nx = x + DX[dir];\n            int ny = y + DY[dir];\n            if (nx < 0 || nx >= n || ny < 0 || ny >= n) continue;\n            if (grid[nx][ny] == 0) {\n                adjZero = true;\n                break;\n            }\n        }\n    }\n    if (!boundary && !adjZero) return false;\n\n    // Quick filter: no new adjacency between 0 and colors that originally didn't touch 0\n    for (int dir = 0; dir < 4; dir++) {\n        int nx = x + DX[dir];\n        int ny = y + DY[dir];\n        if (nx < 0 || nx >= n || ny < 0 || ny >= n) continue;\n        int d = grid[nx][ny];\n        if (!allowedZeroAdj[d]) {\n            return false;\n        }\n    }\n\n    // Count same-color neighbors (for potential connectivity check)\n    pair<int,int> nbrs[4];\n    int k = 0;\n    for (int dir = 0; dir < 4; dir++) {\n        int nx = x + DX[dir];\n        int ny = y + DY[dir];\n        if (nx < 0 || nx >= n || ny < 0 || ny >= n) continue;\n        if (grid[nx][ny] == oldCol) {\n            nbrs[k++] = {nx, ny};\n        }\n    }\n\n    // Tentatively recolor to 0\n    grid[x][y] = 0;\n    countColor[oldCol]--;\n    countColor[0]++;\n\n    bool ok = true;\n\n    // If degree in color component >= 2, check connectivity via neighbor test\n    if (k >= 2) {\n        if (!checkColorConnectivityAfterRemoval(x, y, oldCol, grid)) {\n            ok = false;\n        }\n    }\n\n    if (!ok) {\n        grid[x][y] = oldCol;\n        countColor[oldCol]++;\n        countColor[0]--;\n        return false;\n    }\n\n    // Incremental adjacency update\n    struct Delta { int a, b, d; };\n    static vector<Delta> deltas;\n    deltas.clear();\n\n    auto addDelta = [&](int a, int b, int delta) {\n        if (a == b) return; // we don't track same-color adjacency\n        if (a > b) swap(a, b);\n        for (auto &dd : deltas) {\n            if (dd.a == a && dd.b == b) {\n                dd.d += delta;\n                return;\n            }\n        }\n        deltas.push_back({a, b, delta});\n    };\n\n    // Internal neighbors: adjust oldCol-d and 0-d\n    for (int dir = 0; dir < 4; dir++) {\n        int nx = x + DX[dir];\n        int ny = y + DY[dir];\n        if (nx < 0 || nx >= n || ny < 0 || ny >= n) continue;\n        int d = grid[nx][ny]; // after recolor: grid[x][y] = 0\n\n        // Remove old adjacency oldCol-d if existed\n        if (d != oldCol) {\n            int a = min(oldCol, d), b = max(oldCol, d);\n            addDelta(a, b, -1);\n        }\n        // Add new adjacency 0-d if d != 0\n        if (d != 0) {\n            int a = 0, b = d;\n            addDelta(a, b, +1);\n        }\n    }\n\n    // Outside adjacency edges: oldCol had 'outE' adjacency edges with 0, now 0-0\n    int outE = outsideAdjEdges[x][y];\n    if (outE > 0) {\n        int a = 0, b = oldCol;\n        addDelta(a, b, -outE);\n    }\n\n    // Apply deltas to edgeCount\n    for (auto &dd : deltas) {\n        edgeCount[dd.a][dd.b] += dd.d;\n    }\n\n    // Check adjacency for affected pairs only\n    for (auto &dd : deltas) {\n        int a = dd.a, b = dd.b;\n        bool curAdj = (edgeCount[a][b] > 0);\n        if (curAdj != adj_orig[a][b]) {\n            ok = false;\n            break;\n        }\n    }\n\n    if (!ok) {\n        // Revert edge counts\n        for (auto &dd : deltas) {\n            edgeCount[dd.a][dd.b] -= dd.d;\n        }\n        // Revert color\n        grid[x][y] = oldCol;\n        countColor[oldCol]++;\n        countColor[0]--;\n        return false;\n    }\n\n    // Successful recolor\n    return true;\n}\n\n// Try to recolor cell (x, y) from its current color to newCol (both >0).\n// Keeps adjacency matrix (via edgeCount) and connectivity of oldCol.\nbool tryRecolorToColor(int x, int y, int newCol,\n                       vector<vector<int>> &grid,\n                       vector<int> &countColor) {\n    int oldCol = grid[x][y];\n    if (oldCol == newCol) return false;\n    if (oldCol == 0 || newCol == 0) return false;\n    if (countColor[oldCol] <= 1) return false; // keep at least one cell per color\n\n    // Quick adjacency filter: must not create adjacency newCol-e if adj_orig[newCol][e] is false\n    // (for any neighbor e where newCol != e).\n    for (int dir = 0; dir < 4; dir++) {\n        int nx = x + DX[dir];\n        int ny = y + DY[dir];\n        if (nx < 0 || nx >= n || ny < 0 || ny >= n) continue;\n        int e = grid[nx][ny];\n        if (e != newCol && !adj_orig[newCol][e]) return false;\n    }\n    // Also check adjacency with outside: if this cell has outside edges, then 0-newCol must be allowed\n    int outE = outsideAdjEdges[x][y];\n    if (outE > 0 && !adj_orig[0][newCol]) return false;\n\n    // Count same-color neighbors for connectivity test\n    pair<int,int> nbrs[4];\n    int k = 0;\n    for (int dir = 0; dir < 4; dir++) {\n        int nx = x + DX[dir];\n        int ny = y + DY[dir];\n        if (nx < 0 || nx >= n || ny < 0 || ny >= n) continue;\n        if (grid[nx][ny] == oldCol) {\n            nbrs[k++] = {nx, ny};\n        }\n    }\n\n    // Tentatively recolor\n    grid[x][y] = newCol;\n    countColor[oldCol]--;\n    countColor[newCol]++;\n\n    bool ok = true;\n\n    // If degree in oldCol component >= 2, check connectivity\n    if (k >= 2) {\n        if (!checkColorConnectivityAfterRemoval(x, y, oldCol, grid)) {\n            ok = false;\n        }\n    }\n\n    if (!ok) {\n        grid[x][y] = oldCol;\n        countColor[oldCol]++;\n        countColor[newCol]--;\n        return false;\n    }\n\n    // Incremental adjacency update for recolor oldCol -> newCol\n    struct Delta { int a, b, d; };\n    static vector<Delta> deltas;\n    deltas.clear();\n\n    auto addDelta = [&](int a, int b, int delta) {\n        if (a == b) return; // we don't track same-color adjacency\n        if (a > b) swap(a, b);\n        for (auto &dd : deltas) {\n            if (dd.a == a && dd.b == b) {\n                dd.d += delta;\n                return;\n            }\n        }\n        deltas.push_back({a, b, delta});\n    };\n\n    // Internal neighbors\n    for (int dir = 0; dir < 4; dir++) {\n        int nx = x + DX[dir];\n        int ny = y + DY[dir];\n        if (nx < 0 || nx >= n || ny < 0 || ny >= n) continue;\n        int e = grid[nx][ny]; // after recolor: grid[x][y] = newCol\n\n        // Remove old adjacency oldCol-e if existed\n        if (e != oldCol) {\n            int a = min(oldCol, e), b = max(oldCol, e);\n            addDelta(a, b, -1);\n        }\n        // Add new adjacency newCol-e if e != newCol\n        if (e != newCol) {\n            int a = min(newCol, e), b = max(newCol, e);\n            addDelta(a, b, +1);\n        }\n    }\n\n    // Outside adjacency: oldCol loses, newCol gains\n    if (outE > 0) {\n        int a1 = 0, b1 = oldCol;\n        addDelta(a1, b1, -outE);\n        int a2 = 0, b2 = newCol;\n        addDelta(a2, b2, +outE);\n    }\n\n    // Apply deltas\n    for (auto &dd : deltas) {\n        edgeCount[dd.a][dd.b] += dd.d;\n    }\n\n    // Check adjacency for affected pairs\n    for (auto &dd : deltas) {\n        int a = dd.a, b = dd.b;\n        bool curAdj = (edgeCount[a][b] > 0);\n        if (curAdj != adj_orig[a][b]) {\n            ok = false;\n            break;\n        }\n    }\n\n    if (!ok) {\n        // Revert edge counts\n        for (auto &dd : deltas) {\n            edgeCount[dd.a][dd.b] -= dd.d;\n        }\n        // Revert recolor\n        grid[x][y] = oldCol;\n        countColor[oldCol]++;\n        countColor[newCol]--;\n        return false;\n    }\n\n    return true;\n}\n\n// Run one greedy pass starting from the original grid, with a given RNG seed and time limit.\n// Returns the number of 0 cells in the resulting grid, and writes that grid into out_grid.\nint solve_one(uint64_t seed, double timeLimit,\n              vector<vector<int>> &out_grid) {\n    // Initialize current grid and color counts from original\n    vector<vector<int>> cur_grid = orig_grid;\n    vector<int> countColor(m + 1, 0);\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            countColor[cur_grid[i][j]]++;\n        }\n    }\n\n    // Initialize edge counts\n    initAdjCounts(cur_grid);\n\n    // RNG for this run\n    mt19937_64 rng(seed);\n\n    auto start_time = chrono::steady_clock::now();\n    const double TIME_LIMIT = timeLimit;\n    const double RECOLOR_FRAC = 0.25; // fraction of run time for recolor phase\n\n    int Ncells = n * n;\n    vector<char> inQueue(Ncells, 0);\n\n    // ---- Phase 1: recolor \"interior\" colors into \"outer\" colors ----\n    {\n        double recLimit = TIME_LIMIT * RECOLOR_FRAC;\n        bool changed = true;\n\n        static vector<int> order;\n        order.resize(Ncells);\n\n        while (changed) {\n            auto now = chrono::steady_clock::now();\n            double elapsed = chrono::duration<double>(now - start_time).count();\n            if (elapsed > recLimit) break;\n\n            changed = false;\n\n            iota(order.begin(), order.end(), 0);\n            shuffle(order.begin(), order.end(), rng);\n\n            for (int idx : order) {\n                auto now2 = chrono::steady_clock::now();\n                double elapsed2 = chrono::duration<double>(now2 - start_time).count();\n                if (elapsed2 > recLimit) break;\n\n                int x = idx / n;\n                int y = idx % n;\n                int c = cur_grid[x][y];\n                if (c == 0) continue;\n                // Only recolor colors that are not allowed to touch 0 originally\n                if (allowedZeroAdj[c]) continue;\n\n                // Try recolor to one of neighboring colors that are allowedZeroAdj\n                int dirs[4] = {0,1,2,3};\n                for (int i = 3; i > 0; --i) {\n                    int j = (int)(rng() % (i + 1));\n                    swap(dirs[i], dirs[j]);\n                }\n\n                bool done = false;\n                for (int t = 0; t < 4 && !done; t++) {\n                    int dir = dirs[t];\n                    int nx = x + DX[dir];\n                    int ny = y + DY[dir];\n                    if (nx < 0 || nx >= n || ny < 0 || ny >= n) continue;\n                    int d = cur_grid[nx][ny];\n                    if (d <= 0) continue;\n                    if (!allowedZeroAdj[d]) continue; // target must be \"outer\" color\n\n                    if (tryRecolorToColor(x, y, d, cur_grid, countColor)) {\n                        changed = true;\n                        done = true;\n                    }\n                }\n            }\n        }\n    }\n\n    // ---- Phase 2: greedy removal to 0 ----\n    {\n        bool improved = true;\n\n        struct Cand {\n            int idx;\n            uint8_t degSame;\n            uint64_t rnd;\n        };\n\n        while (improved) {\n            auto now = chrono::steady_clock::now();\n            double elapsed = chrono::duration<double>(now - start_time).count();\n            if (elapsed > TIME_LIMIT) break;\n\n            improved = false;\n            vector<Cand> cands;\n            cands.reserve(Ncells);\n\n            // Collect frontier cells: non-zero cells that are on boundary or adjacent to 0\n            for (int x = 0; x < n; x++) {\n                for (int y = 0; y < n; y++) {\n                    if (cur_grid[x][y] == 0) continue;\n                    bool boundary = (x == 0 || x == n - 1 || y == 0 || y == n - 1);\n                    bool adjZero = false;\n                    if (!boundary) {\n                        for (int dir = 0; dir < 4; dir++) {\n                            int nx = x + DX[dir];\n                            int ny = y + DY[dir];\n                            if (nx < 0 || nx >= n || ny < 0 || ny >= n) continue;\n                            if (cur_grid[nx][ny] == 0) {\n                                adjZero = true;\n                                break;\n                            }\n                        }\n                    }\n                    if (boundary || adjZero) {\n                        // compute same-color neighbor count (for heuristic ordering)\n                        int c = cur_grid[x][y];\n                        int degSame = 0;\n                        for (int dir = 0; dir < 4; dir++) {\n                            int nx = x + DX[dir];\n                            int ny = y + DY[dir];\n                            if (nx < 0 || nx >= n || ny < 0 || ny >= n) continue;\n                            if (cur_grid[nx][ny] == c) degSame++;\n                        }\n                        Cand cd;\n                        cd.idx = x * n + y;\n                        cd.degSame = (uint8_t)degSame;\n                        cd.rnd = rng();\n                        cands.push_back(cd);\n                    }\n                }\n            }\n\n            if (cands.empty()) break;\n\n            // Sort candidates by increasing same-color degree (peel \"thin\" parts first),\n            // tie-broken randomly.\n            sort(cands.begin(), cands.end(), [](const Cand &a, const Cand &b) {\n                if (a.degSame != b.degSame) return a.degSame < b.degSame;\n                return a.rnd < b.rnd;\n            });\n\n            fill(inQueue.begin(), inQueue.end(), 0);\n            deque<int> q;\n            for (auto &cd : cands) {\n                int idx = cd.idx;\n                if (!inQueue[idx]) {\n                    inQueue[idx] = 1;\n                    q.push_back(idx);\n                }\n            }\n\n            int iter = 0;\n            while (!q.empty()) {\n                if ((iter & 0xFF) == 0) { // time check every 256 steps\n                    auto now2 = chrono::steady_clock::now();\n                    double elapsed2 = chrono::duration<double>(now2 - start_time).count();\n                    if (elapsed2 > TIME_LIMIT) break;\n                }\n                iter++;\n\n                int idx = q.front();\n                q.pop_front();\n                inQueue[idx] = 0;\n                int x = idx / n;\n                int y = idx % n;\n                if (cur_grid[x][y] == 0) continue;\n\n                if (tryChangeToZero(x, y, cur_grid, countColor, rng)) {\n                    improved = true;\n                    // Neighbors may now become removable\n                    for (int dir = 0; dir < 4; dir++) {\n                        int nx = x + DX[dir];\n                        int ny = y + DY[dir];\n                        if (nx < 0 || nx >= n || ny < 0 || ny >= n) continue;\n                        if (cur_grid[nx][ny] == 0) continue;\n                        int idx2 = nx * n + ny;\n                        if (!inQueue[idx2]) {\n                            inQueue[idx2] = 1;\n                            if (rng() & 1) q.push_front(idx2);\n                            else q.push_back(idx2);\n                        }\n                    }\n                }\n            }\n        }\n    }\n\n    // Count zeros and return\n    int zeros = 0;\n    for (int i = 0; i < n; i++)\n        for (int j = 0; j < n; j++)\n            if (cur_grid[i][j] == 0) zeros++;\n\n    out_grid = move(cur_grid);\n    return zeros;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> n >> m;\n    orig_grid.assign(n, vector<int>(n));\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            cin >> orig_grid[i][j];\n        }\n    }\n\n    // Precompute outside adjacency edges for each cell\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            int cnt = 0;\n            if (i == 0) cnt++;\n            if (i == n - 1) cnt++;\n            if (j == 0) cnt++;\n            if (j == n - 1) cnt++;\n            outsideAdjEdges[i][j] = cnt;\n        }\n    }\n\n    // Compute original adjacency matrix\n    computeAdj(orig_grid, adj_orig);\n\n    // Colors that may touch 0\n    for (int c = 0; c <= m; c++) {\n        allowedZeroAdj[c] = adj_orig[0][c];\n    }\n    allowedZeroAdj[0] = true;\n\n    // Base seed from current time (for diversification between submissions)\n    uint64_t base_seed = chrono::steady_clock::now().time_since_epoch().count();\n\n    int bestZeros = 0;  // original has 0 zeros inside\n    vector<vector<int>> bestGrid = orig_grid;\n\n    // Multi-start: run several independent greedy passes from original\n    const int MAX_RUNS = 9;\n    const double RUN_LIMIT = 0.22; // seconds per run (total ~2.0s upper bound)\n\n    for (int r = 0; r < MAX_RUNS; r++) {\n        vector<vector<int>> candidateGrid;\n        uint64_t seed = base_seed + 1234567ULL * (r + 1);\n\n        int z = solve_one(seed, RUN_LIMIT, candidateGrid);\n        if (z > bestZeros) {\n            bestZeros = z;\n            bestGrid = move(candidateGrid);\n        }\n    }\n\n    // Output best grid\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            if (j) cout << ' ';\n            cout << bestGrid[i][j];\n        }\n        cout << '\\n';\n    }\n\n    return 0;\n}","ahc025":"#include <bits/stdc++.h>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, D, Q;\n    if (!(cin >> N >> D >> Q)) return 0;\n\n    // Precompute expected order statistics for Exp(lambda) (ascending)\n    const double lambda = 1e-5;\n    vector<double> wAsc(N);\n    double acc = 0.0;\n    for (int k = 1; k <= N; ++k) {\n        acc += 1.0 / (lambda * (N - k + 1));\n        wAsc[k - 1] = acc;\n    }\n    double wmax = 1e5 * (double) N / (double) D;\n    for (int i = 0; i < N; ++i) {\n        if (wAsc[i] > wmax) wAsc[i] = wmax;\n    }\n\n    // Compute worst-case number of comparisons needed for full binary-insertion sort\n    int qSortNeeded = 0;\n    if (N >= 2) {\n        for (int i = 1; i < N; ++i) {\n            int len = i;\n            int steps = 0;\n            while ((1 << steps) < len + 1) steps++;\n            qSortNeeded += steps;\n        }\n    }\n    bool useSort = (N >= 2 && Q >= qSortNeeded);\n\n    vector<double> weight(N, 1.0);  // approximate weights to be filled\n\n    if (useSort) {\n        // ---- Mode 1: Full comparison sort using binary-search insertion ----\n        vector<int> sorted;\n        sorted.reserve(N);\n        sorted.push_back(0);\n\n        int qUsed = 0;\n        for (int i = 1; i < N; ++i) {\n            int lo = 0, hi = (int)sorted.size();\n            while (lo < hi) {\n                int mid = (lo + hi) >> 1;\n                int j = sorted[mid];\n\n                // Compare item i vs j: 1 on each side\n                cout << 1 << ' ' << 1 << ' ' << i << ' ' << j << '\\n';\n                cout.flush();\n                string res;\n                if (!(cin >> res)) return 0;\n                ++qUsed;\n\n                // We want sorted in descending order: heaviest first\n                if (res[0] == '>') {\n                    // i heavier -> should come before j\n                    hi = mid;\n                } else {\n                    // i not heavier -> after j\n                    lo = mid + 1;\n                }\n            }\n            sorted.insert(sorted.begin() + lo, i);\n        }\n\n        // Use remaining queries as dummy\n        int remaining = Q - qUsed;\n        for (int t = 0; t < remaining; ++t) {\n            cout << 1 << ' ' << 1 << ' ' << 0 << ' ' << 1 << '\\n';\n            cout.flush();\n            string res;\n            if (!(cin >> res)) return 0;\n        }\n\n        // Map sorted order to weights: heaviest -> largest wAsc\n        for (int pos = 0; pos < N; ++pos) {\n            int item = sorted[pos];\n            double w_est = wAsc[N - 1 - pos];\n            weight[item] = w_est;\n        }\n\n    } else {\n        // ---- Mode 2: Logistic rating with single-phase balanced random queries ----\n        vector<int> A(Q), B(Q), Y(Q);\n        vector<int> matchCount(N, 0);\n        static bool used[100][100];\n        memset(used, 0, sizeof(used));\n\n        mt19937 rng(712367821);\n        vector<int> order(N);\n        iota(order.begin(), order.end(), 0);\n\n        // Query phase\n        for (int q = 0; q < Q; ++q) {\n            // Choose a pair (a, b) that keeps match counts balanced and avoids repeats\n            sort(order.begin(), order.end(), [&](int i, int j) {\n                if (matchCount[i] != matchCount[j]) return matchCount[i] < matchCount[j];\n                return i < j;\n            });\n\n            int a = -1, b = -1;\n            bool found = false;\n            int K = min(N, 10);\n\n            // Try to find a new pair among the K least-used items\n            for (int attempt = 0; attempt < K * 5 && !found; ++attempt) {\n                int ui = rng() % K;\n                int vi = rng() % K;\n                if (ui == vi) continue;\n                int i = order[ui];\n                int j = order[vi];\n                if (i > j) swap(i, j);\n                if (!used[i][j]) {\n                    a = i;\n                    b = j;\n                    found = true;\n                }\n            }\n\n            // Fallback: random pairs avoiding used ones if possible\n            if (!found) {\n                for (int attempt = 0; attempt < N * N && !found; ++attempt) {\n                    int i = rng() % N;\n                    int j = rng() % N;\n                    if (i == j) continue;\n                    if (i > j) swap(i, j);\n                    if (!used[i][j]) {\n                        a = i;\n                        b = j;\n                        found = true;\n                    }\n                }\n            }\n\n            // If all pairs are used (very unlikely), just pick any pair\n            if (!found) {\n                do {\n                    a = rng() % N;\n                    b = rng() % N;\n                } while (a == b);\n                if (a > b) swap(a, b);\n            }\n\n            used[a][b] = used[b][a] = true;\n            matchCount[a]++;\n            matchCount[b]++;\n            A[q] = a;\n            B[q] = b;\n\n            // Output query\n            cout << 1 << ' ' << 1 << ' ' << a << ' ' << b << '\\n';\n            cout.flush();\n\n            // Read result\n            string res;\n            if (!(cin >> res)) return 0;\n            if (res[0] == '>') {\n                Y[q] = +1;  // A heavier than B\n            } else if (res[0] == '<') {\n                Y[q] = -1;  // B heavier than A\n            } else {\n                Y[q] = 0;   // '=' (very rare)\n            }\n        }\n\n        // Bradley\u2013Terry style logistic regression to compute ratings r[i]\n        vector<double> r(N, 0.0);\n        const int ITER = 80;\n        const double base_eta = 0.5;\n\n        bool hasInfo = false;\n        for (int q = 0; q < Q; ++q) if (Y[q] != 0) { hasInfo = true; break; }\n\n        if (hasInfo) {\n            for (int iter = 0; iter < ITER; ++iter) {\n                double eta = base_eta / (1.0 + 0.1 * iter);\n                for (int q = 0; q < Q; ++q) {\n                    int y = Y[q];\n                    if (y == 0) continue;  // skip ties\n                    int a = A[q], b = B[q];\n                    double s = r[a] - r[b];\n                    double z = (double) y * s;\n\n                    if (z > 40.0) continue; // saturation\n\n                    double g;\n                    if (z < -40.0) {\n                        g = (double) y;  // ~ y / (1 + 0) = y\n                    } else {\n                        g = (double) y / (1.0 + std::exp(z));\n                    }\n                    double step = eta * g;\n                    r[a] += step;\n                    r[b] -= step;\n                }\n            }\n        }\n\n        // Map ratings to approximate weights via wAsc\n        vector<int> idx(N);\n        iota(idx.begin(), idx.end(), 0);\n        sort(idx.begin(), idx.end(), [&](int i, int j) {\n            if (r[i] != r[j]) return r[i] > r[j];\n            return i < j;\n        });\n\n        if (hasInfo) {\n            for (int pos = 0; pos < N; ++pos) {\n                int item = idx[pos];\n                double w_est = wAsc[N - 1 - pos];\n                weight[item] = w_est;\n            }\n        } else {\n            for (int i = 0; i < N; ++i) weight[i] = 1.0;\n        }\n    }\n\n    // ---- Partitioning: greedy initialization (largest weight first) ----\n    vector<int> assign(N, -1);\n    vector<double> binSum(D, 0.0);\n\n    vector<int> ord(N);\n    iota(ord.begin(), ord.end(), 0);\n    sort(ord.begin(), ord.end(), [&](int i, int j) {\n        if (weight[i] != weight[j]) return weight[i] > weight[j];\n        return i < j;\n    });\n\n    for (int id : ord) {\n        int bestBin = 0;\n        double bestSum = binSum[0];\n        for (int k = 1; k < D; ++k) {\n            if (binSum[k] < bestSum) {\n                bestSum = binSum[k];\n                bestBin = k;\n            }\n        }\n        assign[id] = bestBin;\n        binSum[bestBin] += weight[id];\n    }\n\n    // ---- Local search helpers ----\n    double totalW = 0.0;\n    for (double x : weight) totalW += x;\n    double target = totalW / D;\n    const double EPS = 1e-9;\n    const int MAX_ITERS_FIRST = 10000;\n    const int MAX_ITERS_BEST = 200;\n\n    auto compute_cost = [&](const vector<double>& bs) -> double {\n        double c = 0.0;\n        for (int k = 0; k < D; ++k) {\n            double d = bs[k] - target;\n            c += d * d;\n        }\n        return c;\n    };\n\n    auto local_search_first = [&](vector<int>& asg, vector<double>& bs) -> double {\n        double cost = compute_cost(bs);\n        int guard = 0;\n        while (true) {\n            bool improved = false;\n\n            // Single-item moves, first improvement\n            for (int i = 0; i < N && !improved; ++i) {\n                int ai = asg[i];\n                double wi = weight[i];\n                double sa = bs[ai];\n                double oldA = (sa - target) * (sa - target);\n                for (int k = 0; k < D; ++k) {\n                    if (k == ai) continue;\n                    double sb = bs[k];\n                    double oldB = (sb - target) * (sb - target);\n                    double newSa = sa - wi;\n                    double newSb = sb + wi;\n                    double newA = (newSa - target) * (newSa - target);\n                    double newB = (newSb - target) * (newSb - target);\n                    double oldPart = oldA + oldB;\n                    double newPart = newA + newB;\n                    if (newPart + EPS < oldPart) {\n                        bs[ai] = newSa;\n                        bs[k] = newSb;\n                        asg[i] = k;\n                        cost += (newPart - oldPart);\n                        improved = true;\n                        break;\n                    }\n                }\n            }\n\n            // Pair swaps, first improvement\n            if (!improved) {\n                for (int i = 0; i < N && !improved; ++i) {\n                    for (int j = i + 1; j < N; ++j) {\n                        int ai = asg[i];\n                        int aj = asg[j];\n                        if (ai == aj) continue;\n                        double wi = weight[i];\n                        double wj = weight[j];\n                        double sa = bs[ai];\n                        double sb = bs[aj];\n                        double oldA = (sa - target) * (sa - target);\n                        double oldB = (sb - target) * (sb - target);\n                        double newSa = sa - wi + wj;\n                        double newSb = sb - wj + wi;\n                        double newA = (newSa - target) * (newSa - target);\n                        double newB = (newSb - target) * (newSb - target);\n                        double oldPart = oldA + oldB;\n                        double newPart = newA + newB;\n                        if (newPart + EPS < oldPart) {\n                            bs[ai] = newSa;\n                            bs[aj] = newSb;\n                            swap(asg[i], asg[j]);\n                            cost += (newPart - oldPart);\n                            improved = true;\n                            break;\n                        }\n                    }\n                }\n            }\n\n            if (!improved) break;\n            if (++guard > MAX_ITERS_FIRST) break;\n        }\n        return cost;\n    };\n\n    auto local_search_best = [&](vector<int>& asg, vector<double>& bs) -> double {\n        double cost = compute_cost(bs);\n        for (int iter = 0; iter < MAX_ITERS_BEST; ++iter) {\n            double bestDelta = 0.0;\n            int bestType = 0; // 0 = none, 1 = move, 2 = swap\n            int bi1 = -1, bi2 = -1, bbin = -1;\n\n            // Try all single-item moves\n            for (int i = 0; i < N; ++i) {\n                int ai = asg[i];\n                double wi = weight[i];\n                double sa = bs[ai];\n                double oldA = (sa - target) * (sa - target);\n                for (int k = 0; k < D; ++k) {\n                    if (k == ai) continue;\n                    double sb = bs[k];\n                    double oldB = (sb - target) * (sb - target);\n                    double newSa = sa - wi;\n                    double newSb = sb + wi;\n                    double newA = (newSa - target) * (newSa - target);\n                    double newB = (newSb - target) * (newSb - target);\n                    double oldPart = oldA + oldB;\n                    double newPart = newA + newB;\n                    double delta = newPart - oldPart;\n                    if (delta < bestDelta - EPS) {\n                        bestDelta = delta;\n                        bestType = 1;\n                        bi1 = i;\n                        bbin = k;\n                    }\n                }\n            }\n\n            // Try all pair swaps\n            for (int i = 0; i < N; ++i) {\n                for (int j = i + 1; j < N; ++j) {\n                    int ai = asg[i];\n                    int aj = asg[j];\n                    if (ai == aj) continue;\n                    double wi = weight[i];\n                    double wj = weight[j];\n                    double sa = bs[ai];\n                    double sb = bs[aj];\n                    double oldA = (sa - target) * (sa - target);\n                    double oldB = (sb - target) * (sb - target);\n                    double newSa = sa - wi + wj;\n                    double newSb = sb - wj + wi;\n                    double newA = (newSa - target) * (newSa - target);\n                    double newB = (newSb - target) * (newSb - target);\n                    double oldPart = oldA + oldB;\n                    double newPart = newA + newB;\n                    double delta = newPart - oldPart;\n                    if (delta < bestDelta - EPS) {\n                        bestDelta = delta;\n                        bestType = 2;\n                        bi1 = i;\n                        bi2 = j;\n                    }\n                }\n            }\n\n            if (bestType == 0) break; // no improving move\n\n            if (bestType == 1) {\n                int i = bi1;\n                int ai = asg[i];\n                int k = bbin;\n                double wi = weight[i];\n                double sa = bs[ai];\n                double sb = bs[k];\n                double oldA = (sa - target) * (sa - target);\n                double oldB = (sb - target) * (sb - target);\n                double newSa = sa - wi;\n                double newSb = sb + wi;\n                double newA = (newSa - target) * (newSa - target);\n                double newB = (newSb - target) * (newSb - target);\n                double oldPart = oldA + oldB;\n                double newPart = newA + newB;\n                bs[ai] = newSa;\n                bs[k] = newSb;\n                asg[i] = k;\n                cost += (newPart - oldPart);\n            } else {\n                int i = bi1;\n                int j = bi2;\n                int ai = asg[i];\n                int aj = asg[j];\n                double wi = weight[i];\n                double wj = weight[j];\n                double sa = bs[ai];\n                double sb = bs[aj];\n                double oldA = (sa - target) * (sa - target);\n                double oldB = (sb - target) * (sb - target);\n                double newSa = sa - wi + wj;\n                double newSb = sb - wj + wi;\n                double newA = (newSa - target) * (newSa - target);\n                double newB = (newSb - target) * (newSb - target);\n                double oldPart = oldA + oldB;\n                double newPart = newA + newB;\n                bs[ai] = newSa;\n                bs[aj] = newSb;\n                swap(asg[i], asg[j]);\n                cost += (newPart - oldPart);\n            }\n        }\n        return cost;\n    };\n\n    // ---- Run local search ----\n    bool sortedMode = useSort;\n\n    // Save greedy result\n    vector<int> assignGreedy = assign;\n    vector<double> binSumGreedy = binSum;\n\n    if (!sortedMode) {\n        // Mode 2 (logistic): keep original first-improvement local search\n        local_search_first(assign, binSum);\n    } else {\n        // Mode 1 (exact sort): try both first-improvement and best-improvement, keep better\n        vector<int> a1 = assignGreedy;\n        vector<double> s1 = binSumGreedy;\n        double c1 = local_search_first(a1, s1);\n\n        vector<int> a2 = assignGreedy;\n        vector<double> s2 = binSumGreedy;\n        double c2 = local_search_best(a2, s2);\n\n        if (c2 + 1e-9 < c1) {\n            assign.swap(a2);\n            binSum.swap(s2);\n        } else {\n            assign.swap(a1);\n            binSum.swap(s1);\n        }\n    }\n\n    // ---- Final output: assignments d_0 ... d_{N-1} ----\n    for (int i = 0; i < N; ++i) {\n        if (i) cout << ' ';\n        cout << assign[i];\n    }\n    cout << '\\n';\n    cout.flush();\n\n    return 0;\n}","ahc026":"#include <bits/stdc++.h>\nusing namespace std;\n\n// Simple xorshift RNG\nstruct XorShift {\n    unsigned long long x;\n    XorShift(unsigned long long seed = 88172645463325252ULL) : x(seed) {}\n    unsigned long long next() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return x;\n    }\n};\n\nstatic const int MAXV = 205;\n\n// Fenwick tree / BIT for counting values in a stack\nstruct BIT {\n    int n;\n    int bit[MAXV];\n\n    void init(int n_) {\n        n = n_;\n        memset(bit, 0, sizeof(bit));\n    }\n\n    void add(int idx, int delta) {\n        for (int i = idx; i <= n; i += i & -i) {\n            bit[i] += delta;\n        }\n    }\n\n    int sumPrefix(int idx) const {\n        if (idx <= 0) return 0;\n        if (idx > n) idx = n;\n        int s = 0;\n        for (int i = idx; i > 0; i -= i & -i) {\n            s += bit[i];\n        }\n        return s;\n    }\n};\n\n// One simulation run with given parameters/weights.\n// bestEnergyLimit: if partial energy reaches/exceeds this, abort the run early.\nstatic pair<long long, vector<pair<int,int>>>\nrunOnce(const vector<vector<int>>& initStacks,\n        const vector<int>& initStackOf,\n        const vector<int>& initPosInStack,\n        const vector<BIT>& initBits,\n        int n, int m,\n        long long bestEnergyLimit,\n        int wPairs, int wSize,\n        int mode,        // 0: pairs only; 1: pairs + smallCount; 2: pairs + nearPairs\n        int wSmall,      // weight for smallCount (mode 1)\n        int smallOffset, // smallCount threshold offset\n        int wNear,       // weight for nearPairs (mode 2)\n        int nearOffset,  // nearPairs threshold offset\n        XorShift& rng)\n{\n    vector<vector<int>> stacks = initStacks;\n    vector<int> stackOf = initStackOf;\n    vector<int> posInStack = initPosInStack;\n    vector<BIT> bits = initBits;\n\n    vector<pair<int,int>> ops;\n    ops.reserve(2 * n + 10);\n    long long energy = 0;\n\n    vector<int> groupVals;\n    groupVals.reserve(n);\n\n    const long long INF = (long long)4e18;\n\n    for (int v = 1; v <= n; v++) {\n        int s = stackOf[v];\n        int idx = posInStack[v];\n\n        // If v is not at the top, move the suffix above it\n        if (idx != (int)stacks[s].size() - 1) {\n            int startIdx = idx + 1;\n            int lenG = (int)stacks[s].size() - startIdx;\n\n            groupVals.clear();\n            groupVals.reserve(lenG);\n            for (int i = startIdx; i < (int)stacks[s].size(); i++) {\n                groupVals.push_back(stacks[s][i]);\n            }\n\n            int dest = -1;\n            long long bestScore = (1LL << 60);\n\n            // Choose destination stack using pair-based heuristics\n            for (int t = 0; t < m; t++) {\n                if (t == s) continue;\n                const BIT &bt = bits[t];\n\n                long long pairs = 0;\n                long long nearPairs = 0;\n\n                int thrNear = (mode == 2 ? min(n, v + nearOffset) : 0);\n\n                for (int x : groupVals) {\n                    int sp = bt.sumPrefix(x - 1);  // #u in T with u < x\n                    pairs += sp;\n\n                    if (mode == 2 && wNear != 0) {\n                        int limit = x - 1;\n                        if (limit > thrNear) limit = thrNear;\n                        if (limit > 0) {\n                            if (limit == x - 1) {\n                                nearPairs += sp;\n                            } else {\n                                nearPairs += bt.sumPrefix(limit);\n                            }\n                        }\n                    }\n                }\n\n                long long score = (long long)wPairs * pairs\n                                  + (long long)wSize * (int)stacks[t].size();\n\n                if (mode == 1 && wSmall != 0) {\n                    int thrSmall = min(n, v + smallOffset);\n                    int smallCount = bt.sumPrefix(thrSmall); // elements <= thrSmall\n                    score += (long long)wSmall * smallCount;\n                }\n\n                if (mode == 2 && wNear != 0) {\n                    score += (long long)wNear * nearPairs;\n                }\n\n                // small random noise for tie-breaking\n                score = score * 16 + (rng.next() & 15);\n\n                if (score < bestScore) {\n                    bestScore = score;\n                    dest = t;\n                }\n            }\n\n            if (dest == -1) {\n                // Fallback (should not happen as m >= 2)\n                dest = (s + 1) % m;\n            }\n\n            int pivot = stacks[s][startIdx];\n            ops.emplace_back(pivot, dest + 1);  // operation 1\n\n            energy += lenG + 1;\n            if (energy >= bestEnergyLimit) {\n                // This run cannot beat the current best\n                return {INF, {}};\n            }\n\n            // Perform move: update stacks, positions, and BITs\n            auto &Ss = stacks[s];\n            auto &Dt = stacks[dest];\n            int oldSize = (int)Ss.size();\n            for (int i = startIdx; i < oldSize; i++) {\n                int box = Ss[i];\n                bits[s].add(box, -1);\n                bits[dest].add(box, 1);\n                stackOf[box] = dest;\n                posInStack[box] = (int)Dt.size();\n                Dt.push_back(box);\n            }\n            Ss.resize(startIdx);\n        }\n\n        // Now v should be on top; remove it\n        s = stackOf[v];\n        auto &S = stacks[s];\n        ops.emplace_back(v, 0);  // operation 2\n        bits[s].add(v, -1);\n        S.pop_back();\n        stackOf[v] = -1;\n        posInStack[v] = -1;\n    }\n\n    return {energy, std::move(ops)};\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int n, m;\n    if (!(cin >> n >> m)) return 0;\n\n    vector<vector<int>> initStacks(m);\n    vector<int> initStackOf(n + 1);\n    vector<int> initPosInStack(n + 1);\n    vector<BIT> initBits(m);\n\n    int perStack = n / m;\n    for (int i = 0; i < m; i++) {\n        initStacks[i].resize(perStack);\n        initBits[i].init(n);\n        for (int j = 0; j < perStack; j++) {\n            int x;\n            cin >> x;\n            initStacks[i][j] = x;\n            initStackOf[x] = i;\n            initPosInStack[x] = j;\n            initBits[i].add(x, 1);\n        }\n    }\n\n    XorShift rng((unsigned long long)chrono::steady_clock::now()\n                     .time_since_epoch().count());\n\n    auto start = chrono::steady_clock::now();\n    auto endTime = start + chrono::milliseconds(1900);  // time guard\n\n    const long long INF = (long long)4e18;\n    long long bestEnergy = INF;\n    vector<pair<int,int>> bestOps;\n\n    int runId = 0;\n    while (true) {\n        int wPairs, wSize;\n        int mode;\n        int wSmall = 0, smallOffset = 0;\n        int wNear = 0, nearOffset = 0;\n\n        if (runId == 0) {\n            // Baseline parameters: simple pairs + size (best known)\n            mode = 0;\n            wPairs = 3;\n            wSize  = 1;\n        } else if (runId == 1) {\n            // Fixed \"small penalty\" variant\n            mode = 1;\n            wPairs = 3;\n            wSize  = 1;\n            wSmall = 2;\n            smallOffset = 20;\n        } else if (runId == 2) {\n            // Fixed \"nearPairs\" variant\n            mode = 2;\n            wPairs = 2;\n            wSize  = 1;\n            wNear  = 3;\n            nearOffset = 20;\n        } else {\n            // Randomized parameters and scoring mode\n            int rmode = (int)(rng.next() % 3); // 0, 1 or 2\n            mode = rmode;\n            if (mode == 0) {\n                // Simple model (pairs + size)\n                wPairs = 1 + (int)(rng.next() % 6);   // 1..6\n                wSize  = (int)(rng.next() % 7) - 2;   // -2..4\n            } else if (mode == 1) {\n                // With small-count penalty\n                wPairs = 2 + (int)(rng.next() % 6);   // 2..7\n                wSize  = (int)(rng.next() % 5);       // 0..4\n                wSmall = 1 + (int)(rng.next() % 5);   // 1..5\n                smallOffset = 10 + (int)(rng.next() % 31); // 10..40\n            } else {\n                // With nearPairs penalty\n                wPairs = 1 + (int)(rng.next() % 5);   // 1..5\n                wSize  = (int)(rng.next() % 5);       // 0..4\n                wNear  = 1 + (int)(rng.next() % 6);   // 1..6\n                nearOffset = 10 + (int)(rng.next() % 31); // 10..40\n            }\n        }\n\n        auto res = runOnce(initStacks, initStackOf, initPosInStack,\n                           initBits, n, m,\n                           bestEnergy,\n                           wPairs, wSize,\n                           mode, wSmall, smallOffset,\n                           wNear, nearOffset,\n                           rng);\n        if (res.first < bestEnergy) {\n            bestEnergy = res.first;\n            bestOps = std::move(res.second);\n        }\n\n        runId++;\n        if (chrono::steady_clock::now() > endTime) break;\n    }\n\n    // Output best sequence of operations\n    for (auto &op : bestOps) {\n        cout << op.first << ' ' << op.second << '\\n';\n    }\n\n    return 0;\n}","ahc027":"#include <bits/stdc++.h>\nusing namespace std;\n\n// ---------- RNG (xorshift) ----------\nstatic uint64_t rng_state = 123456789ULL;\n\nstatic inline uint64_t xorshift64() {\n    uint64_t x = rng_state;\n    x ^= x << 7;\n    x ^= x >> 9;\n    rng_state = x;\n    return x;\n}\n\nstatic inline double rand_double() {\n    // [0,1)\n    return (xorshift64() & ((1ULL << 53) - 1)) * (1.0 / (1ULL << 53));\n}\n\n// ---------- Global structures ----------\nstruct Edge {\n    int to;\n    char dir; // 'U', 'D', 'L', 'R'\n};\n\nint N;\nint V; // N*N\nvector<string> hgrid; // (N-1) x N, between (i,j) and (i+1,j)\nvector<string> vgrid; // N x (N-1), between (i,j) and (i,j+1)\nvector<int> dflat;    // size V\nvector<vector<Edge>> adj;\n\nvector<int> dist_bfs;\nvector<int> parent_bfs;\nvector<char> pdir_bfs;        // direction parent -> node in BFS tree\nvector<vector<int>> children; // BFS tree children\n\nstring coverMoves;            // covering route (DFS over BFS tree)\nconstexpr int L_MAX = 100000;\n\n// ---------- Utility ----------\ninline char revdir(char c) {\n    if (c == 'U') return 'D';\n    if (c == 'D') return 'U';\n    if (c == 'L') return 'R';\n    return 'L'; // 'R'\n}\n\n// ---------- DFS on BFS tree to build covering tour ----------\nvoid dfs_cover(int u) {\n    for (int v : children[u]) {\n        char dir = pdir_bfs[v]; // parent -> child\n        coverMoves.push_back(dir);\n        dfs_cover(v);\n        coverMoves.push_back(revdir(dir)); // back to parent\n    }\n}\n\n// ---------- Append shortest path root -> v (using BFS tree) ----------\nvoid append_path_root_to(int v, string &route) {\n    const int root = 0;\n    if (v == root) return;\n    vector<char> tmp;\n    int cur = v;\n    while (cur != root) {\n        tmp.push_back(pdir_bfs[cur]); // parent -> cur\n        cur = parent_bfs[cur];\n    }\n    for (int i = (int)tmp.size() - 1; i >= 0; --i) {\n        route.push_back(tmp[i]);\n    }\n}\n\n// ---------- Append shortest path cur -> root (using BFS tree) ----------\nvoid append_path_to_root(int cur, string &route) {\n    const int root = 0;\n    while (cur != root) {\n        char c = revdir(pdir_bfs[cur]); // cur -> parent\n        route.push_back(c);\n        cur = parent_bfs[cur];\n    }\n}\n\n// ---------- Evaluate a route: exact average dirtiness ----------\nlong double evaluate_route(const string &route) {\n    int L = (int)route.size();\n    if (L == 0) return 0.0L;\n\n    static vector<int> firstVisit, lastVisit;\n    static vector<unsigned long long> sumLen2;\n\n    if ((int)firstVisit.size() != V) {\n        firstVisit.assign(V, 0);\n        lastVisit.assign(V, 0);\n        sumLen2.assign(V, 0ULL);\n    } else {\n        fill(firstVisit.begin(), firstVisit.end(), 0);\n        fill(lastVisit.begin(), lastVisit.end(), 0);\n        fill(sumLen2.begin(), sumLen2.end(), 0ULL);\n    }\n\n    int ci = 0, cj = 0; // start at (0,0)\n    for (int t = 1; t <= L; ++t) {\n        char mv = route[t - 1];\n        if      (mv == 'U') --ci;\n        else if (mv == 'D') ++ci;\n        else if (mv == 'L') --cj;\n        else                ++cj; // 'R'\n        int id = ci * N + cj;\n\n        if (lastVisit[id] == 0) {\n            firstVisit[id] = t;\n            lastVisit[id] = t;\n        } else {\n            int len = t - lastVisit[id];\n            unsigned long long l = (unsigned long long)len;\n            sumLen2[id] += l * (l - 1ULL);\n            lastVisit[id] = t;\n        }\n    }\n\n    unsigned long long totalScore = 0ULL;\n    for (int id = 0; id < V; ++id) {\n        if (lastVisit[id] == 0) continue; // covering ensures all visited\n        int len = (firstVisit[id] + L) - lastVisit[id];\n        unsigned long long l = (unsigned long long)len;\n        sumLen2[id] += l * (l - 1ULL);\n\n        unsigned long long contrib = sumLen2[id] * (unsigned long long)dflat[id];\n        contrib >>= 1; // divide by 2 (len*(len-1) always even)\n        totalScore += contrib;\n    }\n\n    return (long double)totalScore / (long double)L;\n}\n\n// ---------- Build random-walk segment: plain biased ----------\nvoid build_segment_plain(int anchor, const vector<double> &weight,\n                         int S_max, vector<char> &segMoves, vector<int> &segPos) {\n    segMoves.resize(S_max);\n    segPos.resize(S_max);\n    int pos = anchor;\n    for (int step = 0; step < S_max; ++step) {\n        auto &nb = adj[pos];\n        int deg = (int)nb.size();\n        if (deg == 0) {\n            // Should not happen in connected grid, but just in case\n            segMoves.resize(step);\n            segPos.resize(step);\n            return;\n        }\n        double sumw = 0.0;\n        for (const auto &e : nb) sumw += weight[e.to];\n        double r = rand_double() * sumw;\n        double acc = 0.0;\n        int chosen = deg - 1;\n        for (int k = 0; k < deg; ++k) {\n            acc += weight[nb[k].to];\n            if (acc >= r) { chosen = k; break; }\n        }\n        const auto &e = nb[chosen];\n        segMoves[step] = e.dir;\n        pos = e.to;\n        segPos[step] = pos;\n    }\n}\n\n// ---------- Build random-walk segment: anchored biased ----------\nvoid build_segment_anchored(int anchor, const vector<double> &weight,\n                            int S_max, const vector<int> &distA,\n                            vector<char> &segMoves, vector<int> &segPos) {\n    const int R = 4;\n    segMoves.resize(S_max);\n    segPos.resize(S_max);\n    int pos = anchor;\n    for (int step = 0; step < S_max; ++step) {\n        auto &nb = adj[pos];\n        int deg = (int)nb.size();\n        if (deg == 0) {\n            segMoves.resize(step);\n            segPos.resize(step);\n            return;\n        }\n\n        int da = distA[pos];\n        int chosen = -1;\n        if (da <= R && da >= 0) {\n            // inside region: prefer staying inside R, but allow outside\n            double sumw = 0.0;\n            for (const auto &e : nb) {\n                int dv = distA[e.to];\n                double factor = (dv <= R && dv >= 0) ? 1.0 : 0.3;\n                sumw += weight[e.to] * factor;\n            }\n            if (sumw <= 0.0) {\n                for (const auto &e : nb) sumw += weight[e.to];\n            }\n            double r = rand_double() * sumw;\n            double acc = 0.0;\n            for (int k = 0; k < deg; ++k) {\n                int dv = distA[nb[k].to];\n                double factor = (dv <= R && dv >= 0) ? 1.0 : 0.3;\n                double w = weight[nb[k].to] * factor;\n                if (sumw <= 0.0) w = weight[nb[k].to];\n                acc += w;\n                if (acc >= r) { chosen = k; break; }\n            }\n            if (chosen == -1) chosen = deg - 1;\n        } else {\n            // outside region: strongly prefer moving closer to anchor\n            int bestDist = INT_MAX;\n            for (const auto &e : nb) {\n                int dv = distA[e.to];\n                if (dv >= 0 && dv < bestDist) bestDist = dv;\n            }\n            vector<int> cand;\n            for (int k = 0; k < deg; ++k) {\n                int dv = distA[nb[k].to];\n                if (dv == bestDist) cand.push_back(k);\n            }\n            if (cand.empty()) {\n                double sumw = 0.0;\n                for (const auto &e : nb) sumw += weight[e.to];\n                double r = rand_double() * sumw;\n                double acc = 0.0;\n                for (int k = 0; k < deg; ++k) {\n                    acc += weight[nb[k].to];\n                    if (acc >= r) { chosen = k; break; }\n                }\n                if (chosen == -1) chosen = deg - 1;\n            } else {\n                double sumw = 0.0;\n                for (int idx : cand) sumw += weight[nb[idx].to];\n                double r = rand_double() * sumw;\n                double acc = 0.0;\n                int chosenIdx = cand.back();\n                for (int idx : cand) {\n                    acc += weight[nb[idx].to];\n                    if (acc >= r) { chosenIdx = idx; break; }\n                }\n                chosen = chosenIdx;\n            }\n        }\n\n        const auto &e = nb[chosen];\n        segMoves[step] = e.dir;\n        pos = e.to;\n        segPos[step] = pos;\n    }\n}\n\n// ---------- BFS from a given start ----------\nvector<int> bfs_from(int s) {\n    vector<int> dist(V, -1);\n    queue<int> q;\n    dist[s] = 0;\n    q.push(s);\n    while (!q.empty()) {\n        int u = q.front(); q.pop();\n        for (const auto &e : adj[u]) {\n            int v = e.to;\n            if (dist[v] == -1) {\n                dist[v] = dist[u] + 1;\n                q.push(v);\n            }\n        }\n    }\n    return dist;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N;\n    hgrid.resize(N - 1);\n    for (int i = 0; i < N - 1; ++i) cin >> hgrid[i];\n    vgrid.resize(N);\n    for (int i = 0; i < N; ++i) cin >> vgrid[i];\n\n    V = N * N;\n    dflat.assign(V, 0);\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int x;\n            cin >> x;\n            dflat[i * N + j] = x;\n        }\n    }\n\n    // Per-instance RNG seeding based on input\n    {\n        uint64_t seed = 123456789ULL;\n        seed ^= (uint64_t)N * 1000003ULL;\n        seed ^= (uint64_t)dflat[0] * 0x9e3779b97f4a7c15ULL;\n        seed ^= (uint64_t)dflat[V - 1] * 0x94d049bb133111ebULL;\n        uint64_t sumD = 0;\n        for (int v : dflat) sumD += (uint64_t)v;\n        seed ^= sumD * 0x2545F4914F6CDD1DULL;\n        rng_state = seed;\n    }\n\n    // Build adjacency list\n    adj.assign(V, {});\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int id = i * N + j;\n            // Up\n            if (i > 0 && hgrid[i - 1][j] == '0') {\n                int to = (i - 1) * N + j;\n                adj[id].push_back({to, 'U'});\n            }\n            // Down\n            if (i < N - 1 && hgrid[i][j] == '0') {\n                int to = (i + 1) * N + j;\n                adj[id].push_back({to, 'D'});\n            }\n            // Left\n            if (j > 0 && vgrid[i][j - 1] == '0') {\n                int to = i * N + (j - 1);\n                adj[id].push_back({to, 'L'});\n            }\n            // Right\n            if (j < N - 1 && vgrid[i][j] == '0') {\n                int to = i * N + (j + 1);\n                adj[id].push_back({to, 'R'});\n            }\n        }\n    }\n\n    // Sort adjacency so neighbors with larger d come first\n    for (int u = 0; u < V; ++u) {\n        sort(adj[u].begin(), adj[u].end(),\n             [&](const Edge &a, const Edge &b) {\n                 return dflat[a.to] > dflat[b.to];\n             });\n    }\n\n    // BFS from root to build BFS tree and distances\n    const int root = 0;\n    dist_bfs.assign(V, -1);\n    parent_bfs.assign(V, -1);\n    pdir_bfs.assign(V, 0);\n    queue<int> q;\n    dist_bfs[root] = 0;\n    parent_bfs[root] = root;\n    q.push(root);\n    while (!q.empty()) {\n        int u = q.front(); q.pop();\n        for (const auto &e : adj[u]) {\n            int v = e.to;\n            if (dist_bfs[v] == -1) {\n                dist_bfs[v] = dist_bfs[u] + 1;\n                parent_bfs[v] = u;\n                pdir_bfs[v] = e.dir; // parent -> v\n                q.push(v);\n            }\n        }\n    }\n\n    int Dmax = 0;\n    for (int i = 0; i < V; ++i) {\n        if (dist_bfs[i] > Dmax) Dmax = dist_bfs[i];\n    }\n\n    // Build BFS tree children list\n    children.assign(V, {});\n    for (int v = 0; v < V; ++v) {\n        if (v == root) continue;\n        int p = parent_bfs[v];\n        if (p >= 0 && p < V) {\n            children[p].push_back(v);\n        }\n    }\n    // Sort children by descending d for slightly better covering\n    for (int u = 0; u < V; ++u) {\n        sort(children[u].begin(), children[u].end(),\n             [&](int a, int b) {\n                 return dflat[a] > dflat[b];\n             });\n    }\n\n    // Build covering tour (edge-doubling DFS)\n    coverMoves.clear();\n    dfs_cover(root);\n\n    // Build anchor list: root + top-K1 high-d cells\n    int K1 = min(V, 25);\n    vector<int> idx(V);\n    iota(idx.begin(), idx.end(), 0);\n    sort(idx.begin(), idx.end(),\n         [&](int a, int b) {\n             return dflat[a] > dflat[b];\n         });\n    vector<int> anchors;\n    anchors.reserve(K1 + 1);\n    anchors.push_back(root);\n    for (int id : idx) {\n        if ((int)anchors.size() >= K1 + 1) break;\n        if (id == root) continue;\n        anchors.push_back(id);\n    }\n\n    int A = (int)anchors.size();\n    int anchorAnchCount = min(A, 10); // anchors for anchored walks\n\n    // Exponent set for weights\n    vector<double> exps = {0.5, 1.0};\n    int E = (int)exps.size();\n\n    // Precompute weights for each exponent\n    vector<vector<double>> weights(E, vector<double>(V));\n    for (int ei = 0; ei < E; ++ei) {\n        double p = exps[ei];\n        for (int i = 0; i < V; ++i) {\n            weights[ei][i] = pow((double)dflat[i], p);\n        }\n    }\n\n    // Precompute BFS distances from first anchorAnchCount anchors\n    vector<vector<int>> distFromAnchor(anchorAnchCount);\n    for (int ai = 0; ai < anchorAnchCount; ++ai) {\n        distFromAnchor[ai] = bfs_from(anchors[ai]);\n    }\n\n    string bestRoute;\n    long double bestScore = numeric_limits<long double>::infinity();\n\n    // Baseline: covering tour only\n    {\n        string baseRoute = coverMoves;\n        long double sc = evaluate_route(baseRoute);\n        if (sc < bestScore) {\n            bestScore = sc;\n            bestRoute = std::move(baseRoute);\n        }\n    }\n\n    // Buffers for segments\n    vector<char> segMoves;\n    vector<int>  segPos;\n\n    // For each anchor and exponent, build plain and (optionally) anchored segments and test multiple S\n    for (int ai = 0; ai < A; ++ai) {\n        int anchor = anchors[ai];\n\n        // Build prefix route cover + root->anchor once\n        string prefix = coverMoves;\n        append_path_root_to(anchor, prefix);\n        int prefixLen = (int)prefix.size();\n        int S_max_base = L_MAX - prefixLen - Dmax;\n        if (S_max_base < 0) S_max_base = 0;\n\n        for (int ei = 0; ei < E; ++ei) {\n            const auto &w = weights[ei];\n\n            // ---- Plain segment ----\n            if (S_max_base == 0) {\n                // No room for random steps: just prefix + back\n                string route = prefix;\n                append_path_to_root(anchor, route);\n                long double sc = evaluate_route(route);\n                if (sc < bestScore) {\n                    bestScore = sc;\n                    bestRoute = std::move(route);\n                }\n            } else {\n                build_segment_plain(anchor, w, S_max_base, segMoves, segPos);\n\n                // Candidate S values: 0, S_max/4, S_max/2, S_max\n                vector<int> Ss;\n                Ss.push_back(0);\n                int Smax = (int)segMoves.size();\n                int s1 = Smax / 4;\n                int s2 = Smax / 2;\n                int s3 = Smax;\n                auto addS = [&](int s) {\n                    if (s < 0) return;\n                    if (s > Smax) s = Smax;\n                    if (s < 0) return;\n                    if (find(Ss.begin(), Ss.end(), s) == Ss.end()) Ss.push_back(s);\n                };\n                addS(s1);\n                addS(s2);\n                addS(s3);\n\n                for (int S : Ss) {\n                    string route = prefix;\n                    int finalPos = anchor;\n                    if (S > 0) {\n                        route.append(segMoves.begin(), segMoves.begin() + S);\n                        finalPos = segPos[S - 1];\n                    }\n                    append_path_to_root(finalPos, route);\n                    // route length guaranteed <= L_MAX\n                    long double sc = evaluate_route(route);\n                    if (sc < bestScore) {\n                        bestScore = sc;\n                        bestRoute = std::move(route);\n                    }\n                }\n            }\n\n            // ---- Anchored segment (for top anchors) ----\n            if (ai < anchorAnchCount) {\n                const auto &distA = distFromAnchor[ai];\n                if (S_max_base == 0) {\n                    string route = prefix;\n                    append_path_to_root(anchor, route);\n                    long double sc = evaluate_route(route);\n                    if (sc < bestScore) {\n                        bestScore = sc;\n                        bestRoute = std::move(route);\n                    }\n                } else {\n                    build_segment_anchored(anchor, w, S_max_base, distA, segMoves, segPos);\n\n                    vector<int> Ss;\n                    Ss.push_back(0);\n                    int Smax = (int)segMoves.size();\n                    int s1 = Smax / 4;\n                    int s2 = Smax / 2;\n                    int s3 = Smax;\n                    auto addS = [&](int s) {\n                        if (s < 0) return;\n                        if (s > Smax) s = Smax;\n                        if (s < 0) return;\n                        if (find(Ss.begin(), Ss.end(), s) == Ss.end()) Ss.push_back(s);\n                    };\n                    addS(s1);\n                    addS(s2);\n                    addS(s3);\n\n                    for (int S : Ss) {\n                        string route = prefix;\n                        int finalPos = anchor;\n                        if (S > 0) {\n                            route.append(segMoves.begin(), segMoves.begin() + S);\n                            finalPos = segPos[S - 1];\n                        }\n                        append_path_to_root(finalPos, route);\n                        long double sc = evaluate_route(route);\n                        if (sc < bestScore) {\n                            bestScore = sc;\n                            bestRoute = std::move(route);\n                        }\n                    }\n                }\n            }\n        }\n    }\n\n    cout << bestRoute << '\\n';\n    return 0;\n}","ahc028":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int INF = 1e9;\n\n// ---------- Overlap & superstring ----------\n\n// Compute overlap length: max k in [0..4] such that\n// suffix of a of length k == prefix of b of length k.\nint compute_overlap(const string &a, const string &b) {\n    const int L = 5;\n    for (int k = L - 1; k >= 1; --k) { // k = 4..1\n        bool ok = true;\n        for (int i = 0; i < k; ++i) {\n            if (a[L - k + i] != b[i]) {\n                ok = false;\n                break;\n            }\n        }\n        if (ok) return k;\n    }\n    return 0;\n}\n\n// Build superstring S from permutation path\nstring build_superstring(const vector<int> &path,\n                         const vector<string> &words,\n                         const vector<vector<int>> &ov) {\n    int M = (int)path.size();\n    string S = words[path[0]];\n    for (int i = 1; i < M; ++i) {\n        int prev = path[i - 1];\n        int cur  = path[i];\n        int k = ov[prev][cur];\n        S.append(words[cur].begin() + k, words[cur].end());\n    }\n    return S;\n}\n\n// ---------- Keyboard DP ----------\n\n// DP cost computation without parent reconstruction\nint compute_cost_no_parent(\n    const string &S,\n    const vector<vector<int>> &dist,\n    const vector<vector<int>> &cellsByLetter,\n    int startIdx\n) {\n    int L = (int)S.size();\n    if (L == 0) return 0;\n    int G = (int)dist.size();\n\n    vector<int> dpPrev(G, INF), dpCur(G, INF);\n    vector<int> prevCells, curCells;\n    prevCells.reserve(G);\n    curCells.reserve(G);\n\n    int c0 = S[0] - 'A';\n    const auto &cand0 = cellsByLetter[c0];\n    prevCells.clear();\n    for (int cell : cand0) {\n        dpPrev[cell] = dist[startIdx][cell];\n        prevCells.push_back(cell);\n    }\n\n    for (int pos = 1; pos < L; ++pos) {\n        int c = S[pos] - 'A';\n        const auto &cand = cellsByLetter[c];\n        curCells.clear();\n\n        for (int b : cand) {\n            int best = INF;\n            for (int a : prevCells) {\n                int val = dpPrev[a] + dist[a][b];\n                if (val < best) best = val;\n            }\n            dpCur[b] = best;\n            curCells.push_back(b);\n        }\n\n        dpPrev.swap(dpCur);\n        prevCells.swap(curCells);\n    }\n\n    int bestCost = INF;\n    for (int a : prevCells) {\n        if (dpPrev[a] < bestCost) bestCost = dpPrev[a];\n    }\n    return bestCost;\n}\n\n// DP with parent reconstruction: returns sequence of cell indices\nvector<int> compute_path_with_parent(\n    const string &S,\n    const vector<vector<int>> &dist,\n    const vector<vector<int>> &cellsByLetter,\n    int startIdx\n) {\n    int L = (int)S.size();\n    int G = (int)dist.size();\n    vector<int> result(L);\n    if (L == 0) return result;\n\n    vector<vector<int>> parent(L, vector<int>(G, -1));\n    vector<int> dpPrev(G, INF), dpCur(G, INF);\n    vector<int> prevCells, curCells;\n    prevCells.reserve(G);\n    curCells.reserve(G);\n\n    int c0 = S[0] - 'A';\n    const auto &cand0 = cellsByLetter[c0];\n    prevCells.clear();\n    for (int cell : cand0) {\n        dpPrev[cell] = dist[startIdx][cell];\n        parent[0][cell] = startIdx;\n        prevCells.push_back(cell);\n    }\n\n    for (int pos = 1; pos < L; ++pos) {\n        int c = S[pos] - 'A';\n        const auto &cand = cellsByLetter[c];\n        curCells.clear();\n\n        for (int b : cand) {\n            int best = INF;\n            int bestPrevCell = -1;\n            for (int a : prevCells) {\n                int val = dpPrev[a] + dist[a][b];\n                if (val < best) {\n                    best = val;\n                    bestPrevCell = a;\n                }\n            }\n            dpCur[b] = best;\n            parent[pos][b] = bestPrevCell;\n            curCells.push_back(b);\n        }\n\n        dpPrev.swap(dpCur);\n        prevCells.swap(curCells);\n    }\n\n    int bestCost = INF;\n    int bestLastCell = -1;\n    for (int a : prevCells) {\n        if (dpPrev[a] < bestCost) {\n            bestCost = dpPrev[a];\n            bestLastCell = a;\n        }\n    }\n\n    int cell = bestLastCell;\n    for (int pos = L - 1; pos >= 0; --pos) {\n        result[pos] = cell;\n        cell = parent[pos][cell]; // for pos=0 this becomes startIdx; ignored later\n    }\n\n    return result;\n}\n\n// ---------- Local search (pure overlap) ----------\n\n// Adjacent-swap local search maximizing total overlap sum\nint local_search_adjacent_swaps(vector<int> &path,\n                                const vector<vector<int>> &ov) {\n    int M = (int)path.size();\n    if (M <= 1) return 0;\n\n    vector<int> edgeOv(max(0, M - 1));\n    int totalOv = 0;\n    for (int i = 0; i + 1 < M; ++i) {\n        int val = ov[path[i]][path[i + 1]];\n        edgeOv[i] = val;\n        totalOv += val;\n    }\n\n    if (M <= 2) {\n        return totalOv;\n    }\n\n    bool improved = true;\n    while (improved) {\n        improved = false;\n        for (int i = 0; i < M - 1; ++i) {\n            int delta = 0;\n            if (i == 0) {\n                int A = path[0];\n                int B = path[1];\n                int C = path[2];\n\n                int old1 = ov[A][B];\n                int old2 = ov[B][C];\n\n                int new1 = ov[B][A];\n                int new2 = ov[A][C];\n\n                delta = (new1 + new2) - (old1 + old2);\n                if (delta > 0) {\n                    swap(path[0], path[1]);\n                    edgeOv[0] = new1;\n                    edgeOv[1] = new2;\n                    totalOv += delta;\n                    improved = true;\n                }\n            } else if (i == M - 2) {\n                int D = path[M - 3];\n                int A = path[M - 2];\n                int B = path[M - 1];\n\n                int old1 = ov[D][A];\n                int old2 = ov[A][B];\n\n                int new1 = ov[D][B];\n                int new2 = ov[B][A];\n\n                delta = (new1 + new2) - (old1 + old2);\n                if (delta > 0) {\n                    swap(path[M - 2], path[M - 1]);\n                    edgeOv[M - 3] = new1;\n                    edgeOv[M - 2] = new2;\n                    totalOv += delta;\n                    improved = true;\n                }\n            } else {\n                int D = path[i - 1];\n                int A = path[i];\n                int B = path[i + 1];\n                int C = path[i + 2];\n\n                int old1 = ov[D][A];\n                int old2 = ov[A][B];\n                int old3 = ov[B][C];\n\n                int new1 = ov[D][B];\n                int new2 = ov[B][A];\n                int new3 = ov[A][C];\n\n                delta = (new1 + new2 + new3) - (old1 + old2 + old3);\n                if (delta > 0) {\n                    swap(path[i], path[i + 1]);\n                    edgeOv[i - 1] = new1;\n                    edgeOv[i]     = new2;\n                    edgeOv[i + 1] = new3;\n                    totalOv += delta;\n                    improved = true;\n                }\n            }\n        }\n    }\n    return totalOv;\n}\n\n// ---------- Local search (overlap + approximate cost) ----------\n\n// Adjacent-swap local search with combined objective:\n// score(path) = overlapSum * OVERLAP_WEIGHT - approxCost(path)\n// approxCost(path) = startWordCost[path[0]] + sum approxEdge[path[i]][path[i+1]]\nint local_search_adjacent_swaps_obj(\n    vector<int> &path,\n    const vector<vector<int>> &ov,\n    const vector<vector<int>> &approxEdge,\n    const vector<int> &startWordCost,\n    int OVERLAP_WEIGHT\n) {\n    int M = (int)path.size();\n    if (M == 0) return 0;\n    if (M == 1) {\n        int TOTov = 0;\n        int TOTapprox = startWordCost[path[0]];\n        return TOTov * OVERLAP_WEIGHT - TOTapprox;\n    }\n    vector<int> edgeOv(max(0, M - 1));\n    vector<int> edgeApprox(max(0, M - 1));\n\n    int TOTov = 0;\n    int TOTapproxEdge = 0;\n    for (int i = 0; i + 1 < M; ++i) {\n        int a = path[i];\n        int b = path[i + 1];\n        int o = ov[a][b];\n        edgeOv[i] = o;\n        TOTov += o;\n\n        int ae = approxEdge[a][b];\n        edgeApprox[i] = ae;\n        TOTapproxEdge += ae;\n    }\n    int TOTapproxFirst = startWordCost[path[0]];\n    int TOTapprox = TOTapproxFirst + TOTapproxEdge;\n    int TOTscore = TOTov * OVERLAP_WEIGHT - TOTapprox;\n\n    if (M <= 2) {\n        return TOTscore;\n    }\n\n    bool improved = true;\n    while (improved) {\n        improved = false;\n        for (int i = 0; i < M - 1; ++i) {\n            int deltaOv = 0;\n            int deltaApproxEdge = 0;\n            int deltaApproxFirst = 0;\n\n            if (i == 0) {\n                // P[0],P[1],P[2] => A,B,C\n                int A = path[0];\n                int B = path[1];\n                int C = path[2];\n\n                int old1 = ov[A][B];\n                int old2 = ov[B][C];\n                int new1 = ov[B][A];\n                int new2 = ov[A][C];\n                deltaOv = (new1 + new2) - (old1 + old2);\n\n                int oldE1 = approxEdge[A][B];\n                int oldE2 = approxEdge[B][C];\n                int newE1 = approxEdge[B][A];\n                int newE2 = approxEdge[A][C];\n                deltaApproxEdge = (newE1 + newE2) - (oldE1 + oldE2);\n\n                deltaApproxFirst = startWordCost[B] - startWordCost[A];\n            } else if (i == M - 2) {\n                // P[M-3],P[M-2],P[M-1] => D,A,B\n                int D = path[M - 3];\n                int A = path[M - 2];\n                int B = path[M - 1];\n\n                int old1 = ov[D][A];\n                int old2 = ov[A][B];\n                int new1 = ov[D][B];\n                int new2 = ov[B][A];\n                deltaOv = (new1 + new2) - (old1 + old2);\n\n                int oldE1 = approxEdge[D][A];\n                int oldE2 = approxEdge[A][B];\n                int newE1 = approxEdge[D][B];\n                int newE2 = approxEdge[B][A];\n                deltaApproxEdge = (newE1 + newE2) - (oldE1 + oldE2);\n            } else {\n                // P[i-1],P[i],P[i+1],P[i+2] => D,A,B,C\n                int D = path[i - 1];\n                int A = path[i];\n                int B = path[i + 1];\n                int C = path[i + 2];\n\n                int old1 = ov[D][A];\n                int old2 = ov[A][B];\n                int old3 = ov[B][C];\n                int new1 = ov[D][B];\n                int new2 = ov[B][A];\n                int new3 = ov[A][C];\n                deltaOv = (new1 + new2 + new3) - (old1 + old2 + old3);\n\n                int oldE1 = approxEdge[D][A];\n                int oldE2 = approxEdge[A][B];\n                int oldE3 = approxEdge[B][C];\n                int newE1 = approxEdge[D][B];\n                int newE2 = approxEdge[B][A];\n                int newE3 = approxEdge[A][C];\n                deltaApproxEdge = (newE1 + newE2 + newE3) - (oldE1 + oldE2 + oldE3);\n            }\n\n            int deltaScore = deltaOv * OVERLAP_WEIGHT - (deltaApproxFirst + deltaApproxEdge);\n            if (deltaScore > 0) {\n                swap(path[i], path[i + 1]);\n                TOTscore += deltaScore;\n                TOTov += deltaOv;\n                TOTapproxEdge += deltaApproxEdge;\n                TOTapproxFirst += deltaApproxFirst;\n\n                if (i == 0) {\n                    int A = path[0];\n                    int B = path[1];\n                    int C = path[2];\n                    edgeOv[0] = ov[A][B];\n                    edgeOv[1] = ov[B][C];\n                    edgeApprox[0] = approxEdge[A][B];\n                    edgeApprox[1] = approxEdge[B][C];\n                } else if (i == M - 2) {\n                    int D = path[M - 3];\n                    int A = path[M - 2];\n                    int B = path[M - 1];\n                    edgeOv[M - 3] = ov[D][A];\n                    edgeOv[M - 2] = ov[A][B];\n                    edgeApprox[M - 3] = approxEdge[D][A];\n                    edgeApprox[M - 2] = approxEdge[A][B];\n                } else {\n                    int D = path[i - 1];\n                    int A = path[i];\n                    int B = path[i + 1];\n                    int C = path[i + 2];\n                    edgeOv[i - 1] = ov[D][A];\n                    edgeOv[i]     = ov[A][B];\n                    edgeOv[i + 1] = ov[B][C];\n                    edgeApprox[i - 1] = approxEdge[D][A];\n                    edgeApprox[i]     = approxEdge[A][B];\n                    edgeApprox[i + 1] = approxEdge[B][C];\n                }\n\n                improved = true;\n            }\n        }\n    }\n    return TOTscore;\n}\n\n// Relocation local search: move one word Xi to follow Aj, only if overlap sum improves.\n// After each accepted move, recompute DP cost and update global best string if improved.\nvoid relocate_local_search_T(\n    vector<int> path,                 // work on a copy\n    const vector<vector<int>> &ov,\n    const vector<string> &words,\n    const vector<vector<int>> &dist,\n    const vector<vector<int>> &cellsByLetter,\n    int startIdx,\n    int &globalBestT,\n    string &globalBestS\n) {\n    int M = (int)path.size();\n    if (M <= 2) return;\n\n    int totalOv = 0;\n    for (int i = 0; i + 1 < M; ++i) {\n        totalOv += ov[path[i]][path[i + 1]];\n    }\n\n    bool improved = true;\n    while (improved) {\n        improved = false;\n        for (int i = 0; i < M; ++i) {\n            int Xi = path[i];\n            int Li = (i > 0 ? path[i - 1] : -1);\n            int Ri = (i + 1 < M ? path[i + 1] : -1);\n\n            int wLiX  = (i > 0       ? ov[Li][Xi] : 0);\n            int wXRi  = (i + 1 < M   ? ov[Xi][Ri] : 0);\n            int wLiRi = (i > 0 && i + 1 < M ? ov[Li][Ri] : 0);\n\n            for (int j = 0; j < M; ++j) {\n                if (j == i || j == i - 1) continue;\n                int Aj = path[j];\n                int Bj = (j + 1 < M ? path[j + 1] : -1);\n\n                int wAjBj = (j + 1 < M ? ov[Aj][Bj] : 0);\n                int wAjX  = ov[Aj][Xi];\n                int wXBj  = (j + 1 < M ? ov[Xi][Bj] : 0);\n\n                int delta = 0;\n                // remove Xi from its position\n                if (i > 0)        delta -= wLiX;\n                if (i + 1 < M)    delta -= wXRi;\n                if (i > 0 && i + 1 < M) delta += wLiRi;\n                // break insertion edge Aj->Bj\n                if (j + 1 < M)    delta -= wAjBj;\n                // add new edges Aj->Xi and Xi->Bj\n                delta += wAjX;\n                if (j + 1 < M)    delta += wXBj;\n\n                if (delta > 0) {\n                    totalOv += delta;\n\n                    int from = i;\n                    int to = j + 1;\n                    if (from < to) {\n                        path.erase(path.begin() + from);\n                        --to;\n                        path.insert(path.begin() + to, Xi);\n                    } else {\n                        path.erase(path.begin() + from);\n                        path.insert(path.begin() + to, Xi);\n                    }\n\n                    string S = build_superstring(path, words, ov);\n                    int T = compute_cost_no_parent(S, dist, cellsByLetter, startIdx);\n                    if (T < globalBestT) {\n                        globalBestT = T;\n                        globalBestS = move(S);\n                    }\n\n                    improved = true;\n                    goto NEXT_ITER;\n                }\n            }\n        }\n        NEXT_ITER:;\n    }\n}\n\n// Compute approximate path cost from start by letter-based estimate\nint approx_path_cost(\n    const vector<int> &path,\n    const vector<vector<int>> &approxEdge,\n    const vector<int> &startWordCost\n) {\n    int M = (int)path.size();\n    if (M == 0) return 0;\n    int cost = startWordCost[path[0]];\n    for (int i = 0; i + 1 < M; ++i) {\n        cost += approxEdge[path[i]][path[i + 1]];\n    }\n    return cost;\n}\n\n// DP-guided random local search on permutation, with light simulated annealing\n// Uses approximate cost to skip clearly bad neighbors, so DP is evaluated less often.\nvoid refine_by_DP(\n    const vector<int> &basePath,\n    int initialT,\n    const vector<string> &words,\n    const vector<vector<int>> &ov,\n    const vector<vector<int>> &dist,\n    const vector<vector<int>> &cellsByLetter,\n    int startIdx,\n    const vector<vector<int>> &approxEdge,\n    const vector<int> &startWordCost,\n    int &globalBestT,\n    string &globalBestS,\n    mt19937 &rng,\n    int iterations\n) {\n    int M = (int)basePath.size();\n    if (M <= 1) return;\n\n    vector<int> currentPath = basePath;\n    string currentS = build_superstring(currentPath, words, ov);\n    int currentT = initialT;\n    int currentApprox = approx_path_cost(currentPath, approxEdge, startWordCost);\n\n    if (currentT < globalBestT) {\n        globalBestT = currentT;\n        globalBestS = currentS;\n    }\n\n    uniform_int_distribution<int> moveTypeDist(0, 1);\n    const double T0 = 60.0;\n    const double T1 = 1.0;\n    const int APPROX_MARGIN = 5;  // threshold for approximate gating\n\n    for (int it = 0; it < iterations; ++it) {\n        vector<int> candPath = currentPath;\n\n        int moveType = moveTypeDist(rng);\n        if (moveType == 0) {\n            // swap two positions\n            if (M < 2) continue;\n            int i = rng() % M;\n            int j = rng() % M;\n            if (i == j) continue;\n            swap(candPath[i], candPath[j]);\n        } else {\n            // relocate: remove at i, insert at j\n            if (M < 2) continue;\n            int i = rng() % M;\n            int j = rng() % M;\n            if (i == j) continue;\n            int Xi = candPath[i];\n            candPath.erase(candPath.begin() + i);\n            if (j > i) --j;\n            candPath.insert(candPath.begin() + j, Xi);\n        }\n\n        // Approximate gating: only evaluate DP if approximate cost looks promising\n        int candApprox = approx_path_cost(candPath, approxEdge, startWordCost);\n        if (candApprox > currentApprox + APPROX_MARGIN) {\n            continue; // likely bad; skip DP computation\n        }\n\n        string candS = build_superstring(candPath, words, ov);\n        int candT = compute_cost_no_parent(candS, dist, cellsByLetter, startIdx);\n\n        double temp = T0 + (T1 - T0) * (double)it / max(1, iterations - 1);\n        bool accept = false;\n        if (candT <= currentT) {\n            accept = true;\n        } else {\n            double delta = (double)(currentT - candT);\n            double prob = exp(delta / temp);\n            double u = (rng() + 0.5) / (double)rng.max();\n            if (u < prob) accept = true;\n        }\n\n        if (accept) {\n            currentT = candT;\n            currentApprox = candApprox;\n            currentPath.swap(candPath);\n            currentS.swap(candS);\n            if (candT < globalBestT) {\n                globalBestT = candT;\n                globalBestS = currentS;\n            }\n        }\n    }\n}\n\nstruct PathInfo {\n    vector<int> path;\n    int T;\n};\n\n// ---------- Main ----------\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M;\n    if (!(cin >> N >> M)) return 0;\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> words(M);\n    for (int i = 0; i < M; ++i) cin >> words[i];\n\n    int G = N * N;\n    int startIdx = si * N + sj;\n\n    // Precompute cell coordinates\n    vector<pair<int,int>> coord(G);\n    for (int idx = 0; idx < G; ++idx) {\n        coord[idx] = {idx / N, idx % N};\n    }\n\n    // Cells by letter\n    vector<vector<int>> cellsByLetter(26);\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            char c = grid[i][j];\n            int idx = i * N + j;\n            cellsByLetter[c - 'A'].push_back(idx);\n        }\n    }\n\n    // Distance matrix between cells\n    vector<vector<int>> dist(G, vector<int>(G));\n    for (int a = 0; a < G; ++a) {\n        int ax = coord[a].first;\n        int ay = coord[a].second;\n        for (int b = 0; b < G; ++b) {\n            int bx = coord[b].first;\n            int by = coord[b].second;\n            dist[a][b] = abs(ax - bx) + abs(ay - by) + 1;\n        }\n    }\n\n    // Overlap matrix between words\n    vector<vector<int>> ov(M, vector<int>(M, 0));\n    for (int i = 0; i < M; ++i) {\n        for (int j = 0; j < M; ++j) {\n            if (i == j) continue;\n            ov[i][j] = compute_overlap(words[i], words[j]);\n        }\n    }\n\n    // Approximate letter-to-letter cost: minimal distance between any cells with those letters\n    vector<vector<int>> letterCost(26, vector<int>(26, INF));\n    for (int x = 0; x < 26; ++x) {\n        if (cellsByLetter[x].empty()) continue;\n        for (int y = 0; y < 26; ++y) {\n            if (cellsByLetter[y].empty()) continue;\n            int best = INF;\n            for (int a : cellsByLetter[x]) {\n                for (int b : cellsByLetter[y]) {\n                    int d = dist[a][b];\n                    if (d < best) best = d;\n                }\n            }\n            letterCost[x][y] = best;\n        }\n    }\n\n    // Approximate edge cost between words: from last char of i to first new char of j\n    vector<vector<int>> approxEdge(M, vector<int>(M, 0));\n    for (int i = 0; i < M; ++i) {\n        char last = words[i][4];\n        int lc = last - 'A';\n        for (int j = 0; j < M; ++j) {\n            if (i == j) continue;\n            int k = ov[i][j];\n            char firstNew = words[j][k];\n            int fc = firstNew - 'A';\n            approxEdge[i][j] = letterCost[lc][fc];\n        }\n    }\n\n    // Approximate starting cost per word: from initial position to first letter\n    vector<int> startWordCost(M, INF);\n    for (int i = 0; i < M; ++i) {\n        int c = words[i][0] - 'A';\n        int best = INF;\n        for (int cell : cellsByLetter[c]) {\n            int d = dist[startIdx][cell];\n            if (d < best) best = d;\n        }\n        startWordCost[i] = best;\n    }\n\n    // Good starting words by approximate start cost\n    vector<int> startOrder(M);\n    iota(startOrder.begin(), startOrder.end(), 0);\n    sort(startOrder.begin(), startOrder.end(), [&](int a, int b) {\n        return startWordCost[a] < startWordCost[b];\n    });\n    int TOP_START = min(M, 40);\n    vector<int> goodStartWords(startOrder.begin(), startOrder.begin() + TOP_START);\n\n    mt19937 rng(712367821);\n\n    // Time management (per test)\n    using Clock = chrono::steady_clock;\n    auto t0 = Clock::now();\n    const double TOTAL_LIMIT = 1.9;   // seconds\n    const double RESTART_LIMIT = 1.1; // time budget for restarts\n\n    const int MAX_RESTARTS    = 1200; // hard cap; time-gated anyway\n    const int NUM_TOP_PATHS   = 4;    // how many top paths to refine by DP\n    const int LOCAL_ITERS_DP  = 280;  // iterations per DP-guided local search\n    const int OVERLAP_WEIGHT  = 6;    // weight for overlap vs approxEdge\n    const int EDGE_MARGIN     = 3;    // margin for near-best edges in combined score\n\n    int globalBestT = INF;\n    string globalBestS;\n\n    vector<PathInfo> topPaths;\n    topPaths.reserve(NUM_TOP_PATHS + 2);\n\n    vector<int> bestPathByT;\n    int bestT = INF;\n\n    vector<int> bestPathByOv;\n    int bestOv = -1;\n\n    vector<int> path(M);\n    vector<char> used(M);\n\n    // Multiple restarts: greedy by overlap/combined + adjacent swap LS\n    int restartsDone = 0;\n    for (int r = 0; r < MAX_RESTARTS; ++r) {\n        // Time check for restarts (every 8 iterations)\n        if ((r & 7) == 0) {\n            auto now = Clock::now();\n            double elapsed = chrono::duration<double>(now - t0).count();\n            if (elapsed > RESTART_LIMIT) break;\n        }\n\n        fill(used.begin(), used.end(), 0);\n\n        int startNode;\n        if (r < MAX_RESTARTS / 2) {\n            startNode = goodStartWords[rng() % TOP_START];\n        } else {\n            startNode = rng() % M;\n        }\n        path[0] = startNode;\n        used[startNode] = 1;\n\n        bool useCombined = (r & 1);\n\n        // Greedy construction\n        for (int pos = 1; pos < M; ++pos) {\n            int u = path[pos - 1];\n            int chosen = -1;\n\n            if (!useCombined) {\n                // Pure overlap, tie-break by approxEdge\n                int bestOverlap = -1;\n                int bestCost = INF;\n                vector<int> cands;\n                cands.reserve(M);\n\n                for (int v = 0; v < M; ++v) {\n                    if (used[v]) continue;\n                    int o = ov[u][v];\n                    int c = approxEdge[u][v];\n\n                    if (o > bestOverlap) {\n                        bestOverlap = o;\n                        bestCost = c;\n                        cands.clear();\n                        cands.push_back(v);\n                    } else if (o == bestOverlap) {\n                        if (c < bestCost) {\n                            bestCost = c;\n                            cands.clear();\n                            cands.push_back(v);\n                        } else if (c == bestCost) {\n                            cands.push_back(v);\n                        }\n                    }\n                }\n\n                chosen = cands[rng() % cands.size()];\n            } else {\n                // Combined objective: score = OVERLAP_WEIGHT * overlap - approxEdge\n                int bestScore = -INF;\n                vector<int> cands;\n                cands.reserve(M);\n\n                for (int v = 0; v < M; ++v) {\n                    if (used[v]) continue;\n                    int o = ov[u][v];\n                    int c = approxEdge[u][v];\n                    int score = OVERLAP_WEIGHT * o - c;\n\n                    if (score > bestScore) {\n                        bestScore = score;\n                        cands.clear();\n                        cands.push_back(v);\n                    } else if (score >= bestScore - EDGE_MARGIN) {\n                        cands.push_back(v);\n                    }\n                }\n\n                chosen = cands[rng() % cands.size()];\n            }\n\n            path[pos] = chosen;\n            used[chosen] = 1;\n        }\n\n        // Overlap-based local search by adjacent swaps\n        int TOTov = local_search_adjacent_swaps(path, ov);\n\n        // Build superstring and evaluate true DP cost\n        string S = build_superstring(path, words, ov);\n        int T = compute_cost_no_parent(S, dist, cellsByLetter, startIdx);\n\n        if (TOTov > bestOv) {\n            bestOv = TOTov;\n            bestPathByOv = path;\n        }\n        if (T < bestT) {\n            bestT = T;\n            bestPathByT = path;\n        }\n        if (T < globalBestT) {\n            globalBestT = T;\n            globalBestS = S;\n        }\n\n        PathInfo info{path, T};\n        topPaths.push_back(info);\n        sort(topPaths.begin(), topPaths.end(), [](const PathInfo &a, const PathInfo &b) {\n            return a.T < b.T;\n        });\n        if ((int)topPaths.size() > NUM_TOP_PATHS) {\n            topPaths.resize(NUM_TOP_PATHS);\n        }\n\n        ++restartsDone;\n    }\n\n    // Combined-objective adjacent-swap local search on top paths\n    for (auto &pi : topPaths) {\n        auto now = Clock::now();\n        double elapsed = chrono::duration<double>(now - t0).count();\n        if (elapsed > TOTAL_LIMIT * 0.9) break; // leave some time for final steps\n\n        local_search_adjacent_swaps_obj(pi.path, ov, approxEdge, startWordCost, OVERLAP_WEIGHT);\n        string S = build_superstring(pi.path, words, ov);\n        pi.T = compute_cost_no_parent(S, dist, cellsByLetter, startIdx);\n        if (pi.T < globalBestT) {\n            globalBestT = pi.T;\n            globalBestS = S;\n        }\n    }\n\n    // Overlap-based relocation local search on best-by-overlap path\n    if (!bestPathByOv.empty()) {\n        auto now = Clock::now();\n        double elapsed = chrono::duration<double>(now - t0).count();\n        if (elapsed < TOTAL_LIMIT * 0.95) {\n            relocate_local_search_T(bestPathByOv, ov, words, dist, cellsByLetter, startIdx,\n                                    globalBestT, globalBestS);\n        }\n    }\n    // And on best-by-cost path (if different)\n    if (!bestPathByT.empty() && bestPathByT != bestPathByOv) {\n        auto now = Clock::now();\n        double elapsed = chrono::duration<double>(now - t0).count();\n        if (elapsed < TOTAL_LIMIT * 0.95) {\n            relocate_local_search_T(bestPathByT, ov, words, dist, cellsByLetter, startIdx,\n                                    globalBestT, globalBestS);\n        }\n    }\n\n    // DP-guided random local search on top few paths by cost (with approximate gating)\n    for (const auto &pi : topPaths) {\n        auto now = Clock::now();\n        double elapsed = chrono::duration<double>(now - t0).count();\n        if (elapsed > TOTAL_LIMIT * 0.98) break; // near the limit\n\n        refine_by_DP(pi.path, pi.T, words, ov, dist, cellsByLetter,\n                     startIdx, approxEdge, startWordCost,\n                     globalBestT, globalBestS, rng, LOCAL_ITERS_DP);\n    }\n\n    // Reconstruct final finger movement for the best string\n    vector<int> bestCells = compute_path_with_parent(globalBestS, dist, cellsByLetter, startIdx);\n    int L = (int)bestCells.size();\n    for (int pos = 0; pos < L; ++pos) {\n        int idxCell = bestCells[pos];\n        int x = idxCell / N;\n        int y = idxCell % N;\n        cout << x << ' ' << y << '\\n';\n    }\n\n    return 0;\n}","ahc030":"#include <bits/stdc++.h>\nusing namespace std;\n\n// Representation of each field's shape\nstruct Field {\n    int H, W;                             // bounding box size\n    vector<pair<int,int>> offsets;        // shape cells relative to (0,0)\n    vector<char> occ;                     // occupancy grid H x W: 1 if cell in shape\n};\n\n// A single candidate placement of a field\nstruct Placement {\n    int di, dj;                           // translation offset on the N x N grid\n    bool alive;                           // still possible?\n    vector<int> cells;                    // global cell indices covered by this placement\n};\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)) {\n        return 0;\n    }\n    int N2 = N * N;\n\n    // Read field shapes and compute totalOil = sum of all field areas\n    vector<Field> fields(M);\n    int totalOil = 0;\n    for (int k = 0; k < M; ++k) {\n        int d;\n        cin >> d;\n        totalOil += d;\n        vector<pair<int,int>> cells(d);\n        int max_i = 0, max_j = 0;\n        for (int t = 0; t < d; ++t) {\n            int x, y;\n            cin >> x >> y;\n            cells[t] = {x, y};\n            if (x > max_i) max_i = x;\n            if (y > max_j) max_j = y;\n        }\n        Field &f = fields[k];\n        f.H = max_i + 1;\n        f.W = max_j + 1;\n        f.offsets = move(cells);\n        f.occ.assign(f.H * f.W, 0);\n        for (auto &p : f.offsets) {\n            int x = p.first, y = p.second;\n            f.occ[x * f.W + y] = 1;\n        }\n    }\n\n    // Build all candidate placements and cover counts\n    vector<vector<Placement>> placements(M);\n    vector<vector<int>> coverCount(M, vector<int>(N2, 0)); // coverCount[k][cell]\n    vector<int> totalCandidates(M, 0);\n\n    for (int k = 0; k < M; ++k) {\n        Field &f = fields[k];\n        for (int di = 0; di <= N - f.H; ++di) {\n            for (int dj = 0; dj <= N - f.W; ++dj) {\n                Placement p;\n                p.di = di;\n                p.dj = dj;\n                p.alive = true;\n                p.cells.reserve(f.offsets.size());\n                for (auto &off : f.offsets) {\n                    int i = di + off.first;\n                    int j = dj + off.second;\n                    int cid = i * N + j;\n                    p.cells.push_back(cid);\n                    coverCount[k][cid]++;\n                }\n                placements[k].push_back(move(p));\n                totalCandidates[k]++;\n            }\n        }\n    }\n\n    // observed[c]: exact v(c) if drilled; -1 otherwise\n    vector<int> observed(N2, -1);\n    // known[c]: value of v(c) if we have turned it into a hard constraint (from drilling or inference); -1 otherwise\n    vector<int> known(N2, -1);\n\n    // Candidate-based min/max possible v for each cell and elimination potential\n    vector<int> candMin(N2), candMax(N2), elimSum(N2);\n\n    // Inferred min/max after also applying global sum constraint and observed\n    vector<int> infoMin(N2), infoMax(N2);\n\n    // Recompute candMin, candMax, elimSum from current candidate sets\n    auto recomputeCandidateMinMax = [&]() {\n        for (int c = 0; c < N2; ++c) {\n            int mn = 0, mx = 0, el = 0;\n            for (int k = 0; k < M; ++k) {\n                int tc = totalCandidates[k];\n                if (tc <= 0) continue;      // safety\n                int cc = coverCount[k][c];\n                if (cc == tc) mn += 1;      // all placements of k cover c\n                if (cc > 0)    mx += 1;      // some placement covers c\n                if (cc > 0 && cc < tc) {\n                    // Potential elimination for this field at this cell\n                    el += min(cc, tc - cc);\n                }\n            }\n            candMin[c] = mn;\n            candMax[c] = mx;\n            elimSum[c] = el;\n        }\n    };\n\n    // Compute infoMin/infoMax by combining candidate-based bounds + observed + global sum.\n    auto recomputeInfoBounds = [&]() {\n        // Start from candidate bounds\n        for (int c = 0; c < N2; ++c) {\n            infoMin[c] = candMin[c];\n            infoMax[c] = candMax[c];\n        }\n        // Apply observed (exact drilled values override everything)\n        for (int c = 0; c < N2; ++c) {\n            if (observed[c] != -1) {\n                infoMin[c] = infoMax[c] = observed[c];\n            }\n        }\n\n        // Iterative refinement using global sum: sum v(c) = totalOil\n        const int MAX_ITER = 10;\n        for (int iter = 0; iter < MAX_ITER; ++iter) {\n            long long Smin = 0, Smax = 0;\n            for (int c = 0; c < N2; ++c) {\n                Smin += infoMin[c];\n                Smax += infoMax[c];\n            }\n            if (Smin > totalOil || totalOil > Smax) {\n                // Inconsistent bounds (should not happen). Stop refinement to stay safe.\n                break;\n            }\n            bool changed = false;\n            for (int c = 0; c < N2; ++c) {\n                int L = infoMin[c];\n                int U = infoMax[c];\n                long long restMin = Smin - L; // sum of mins of all other cells\n                long long restMax = Smax - U; // sum of maxs of all other cells\n                int newL = max(L, totalOil - (int)restMax);\n                int newU = min(U, totalOil - (int)restMin);\n                if (newL < 0) newL = 0;\n                if (newU < newL) newU = newL;\n                if (newL != L || newU != U) {\n                    infoMin[c] = newL;\n                    infoMax[c] = newU;\n                    changed = true;\n                }\n            }\n            if (!changed) break;\n        }\n    };\n\n    // Apply hard constraint v(c) = val to prune candidate placements\n    auto applyConstraint = [&](int c, int val) {\n        for (int k = 0; k < M; ++k) {\n            int tc_before = totalCandidates[k];\n            if (tc_before <= 0) continue; // safety\n\n            int cc = coverCount[k][c];\n            bool minCk = (cc == tc_before); // all placements of k cover c?\n            bool maxCk = (cc > 0);          // some placement covers c?\n\n            int min_without_k = candMin[c] - (minCk ? 1 : 0);\n            int max_without_k = candMax[c] - (maxCk ? 1 : 0);\n\n            Field &f = fields[k];\n\n            for (Placement &p : placements[k]) {\n                if (!p.alive) continue;\n\n                // Does this placement cover cell c?\n                int delta = 0;\n                int di = p.di, dj = p.dj;\n                int ci = c / N;\n                int cj = c % N;\n                int li = ci - di;\n                int lj = cj - dj;\n                if (0 <= li && li < f.H && 0 <= lj && lj < f.W) {\n                    if (f.occ[li * f.W + lj]) delta = 1;\n                }\n\n                int min_possible = delta + min_without_k;\n                int max_possible = delta + max_without_k;\n\n                if (val < min_possible || val > max_possible) {\n                    // This placement cannot be part of any configuration consistent\n                    // with this constraint; remove it.\n                    p.alive = false;\n                    totalCandidates[k]--;\n                    // Update cover counts for all cells covered by this placement\n                    for (int cell2 : p.cells) {\n                        coverCount[k][cell2]--;\n                    }\n                }\n            }\n        }\n    };\n\n    // Exact enumeration of remaining placements when search space is small.\n    // Returns true if it found new determined cells (put in cellsOut/valsOut).\n    auto tryEnumeration = [&](vector<int> &cellsOut, vector<int> &valsOut) -> bool {\n        cellsOut.clear();\n        valsOut.clear();\n\n        // Gather fields with >1 candidate and count them\n        vector<pair<int,int>> multi; // {candidateCount, fieldIndex}\n        multi.reserve(M);\n        for (int k = 0; k < M; ++k) {\n            int cnt = totalCandidates[k];\n            if (cnt <= 0) {\n                // Inconsistent candidate set; give up enumeration.\n                return false;\n            }\n            if (cnt > 1) multi.emplace_back(cnt, k);\n        }\n\n        if (multi.empty()) {\n            // All fields have a unique placement.\n            // v(c) is fully determined by these placements.\n            vector<int> baseSum(N2, 0);\n            for (int k = 0; k < M; ++k) {\n                // Find the single alive placement\n                int idx = -1;\n                for (int pi = 0; pi < (int)placements[k].size(); ++pi) {\n                    if (placements[k][pi].alive) { idx = pi; break; }\n                }\n                if (idx == -1) return false; // safety\n                for (int cell2 : placements[k][idx].cells) {\n                    baseSum[cell2]++;\n                }\n            }\n            bool anyNew = false;\n            for (int c = 0; c < N2; ++c) {\n                int val = baseSum[c];\n                if (known[c] != -1) continue;\n                if (observed[c] != -1 && observed[c] != val) continue;\n                cellsOut.push_back(c);\n                valsOut.push_back(val);\n                anyNew = true;\n            }\n            return anyNew;\n        }\n\n        // Sort fields with multiple candidates by increasing candidate count\n        sort(multi.begin(), multi.end());\n\n        const long double PROD_LIMIT = 120000.0L; // max number of full assignments to consider\n        long double prod = 1.0L;\n        for (auto &pr : multi) {\n            prod *= pr.first;\n            if (prod > PROD_LIMIT) {\n                return false; // too many combinations; skip enumeration\n            }\n        }\n\n        int V = (int)multi.size();\n        vector<int> varField(V);\n        for (int i = 0; i < V; ++i) varField[i] = multi[i].second;\n\n        // Prepare candidate placement lists per variable field\n        vector<vector<int>> candList(V);\n        for (int i = 0; i < V; ++i) {\n            int k = varField[i];\n            vector<int> &lst = candList[i];\n            lst.reserve(multi[i].first);\n            for (int pi = 0; pi < (int)placements[k].size(); ++pi) {\n                if (placements[k][pi].alive) lst.push_back(pi);\n            }\n            if ((int)lst.size() != multi[i].first) {\n                return false;\n            }\n        }\n\n        // baseSum: contributions from fields with exactly one candidate\n        vector<int> baseSum(N2, 0);\n        for (int k = 0; k < M; ++k) {\n            if (totalCandidates[k] == 1) {\n                int idx = -1;\n                for (int pi = 0; pi < (int)placements[k].size(); ++pi) {\n                    if (placements[k][pi].alive) { idx = pi; break; }\n                }\n                if (idx == -1) return false; // safety\n                for (int cell2 : placements[k][idx].cells) {\n                    baseSum[cell2]++;\n                }\n            }\n        }\n\n        // partialSum: contributions from the chosen placements of variable fields\n        vector<int> partialSum(N2, 0);\n\n        // For enumeration results\n        vector<int> assignMin(N2, INT_MAX);\n        vector<int> assignMax(N2, -1);\n        long long solutions = 0;\n\n        const long long NODE_LIMIT = 800000; // limit on DFS nodes\n        long long nodesVisited = 0;\n        bool aborted = false;\n\n        function<void(int)> dfs = [&](int idx) {\n            if (aborted) return;\n            if (idx == V) {\n                // Complete assignment; verify consistency with known/observed\n                for (int c = 0; c < N2; ++c) {\n                    int val = baseSum[c] + partialSum[c];\n                    if (known[c] != -1 && val != known[c]) return;\n                    if (known[c] == -1 && observed[c] != -1 && val != observed[c]) return;\n                }\n                // Valid complete assignment; record v(c)\n                solutions++;\n                for (int c = 0; c < N2; ++c) {\n                    int val = baseSum[c] + partialSum[c];\n                    if (val < assignMin[c]) assignMin[c] = val;\n                    if (val > assignMax[c]) assignMax[c] = val;\n                }\n                return;\n            }\n\n            int k = varField[idx];\n            vector<int> &cand = candList[idx];\n\n            for (int pid : cand) {\n                Placement &pl = placements[k][pid];\n                bool ok = true;\n\n                // Apply this placement's contribution\n                for (int cell2 : pl.cells) {\n                    partialSum[cell2]++;\n                    int val = baseSum[cell2] + partialSum[cell2];\n                    if (known[cell2] != -1 && val > known[cell2]) {\n                        ok = false;\n                    } else if (known[cell2] == -1 && observed[cell2] != -1 && val > observed[cell2]) {\n                        ok = false;\n                    }\n                }\n\n                if (ok) {\n                    dfs(idx + 1);\n                }\n\n                // Revert\n                for (int cell2 : pl.cells) {\n                    partialSum[cell2]--;\n                }\n\n                nodesVisited++;\n                if (nodesVisited > NODE_LIMIT) {\n                    aborted = true;\n                    return;\n                }\n            }\n        };\n\n        dfs(0);\n\n        if (aborted || solutions == 0) {\n            return false;\n        }\n\n        bool anyNew = false;\n        for (int c = 0; c < N2; ++c) {\n            if (known[c] != -1) continue;\n            if (observed[c] != -1) continue;\n            if (assignMin[c] == INT_MAX) continue;\n            if (assignMin[c] == assignMax[c]) {\n                cellsOut.push_back(c);\n                valsOut.push_back(assignMin[c]);\n                anyNew = true;\n            }\n        }\n        return anyNew;\n    };\n\n    int drilledCount = 0;\n\n    while (true) {\n        // Update candidate-based bounds and inferred bounds\n        recomputeCandidateMinMax();\n        recomputeInfoBounds();\n\n        // Collect new known cells from exact observations or interval collapse\n        vector<int> newCells;\n        vector<int> newVals;\n        newCells.reserve(N2);\n        newVals.reserve(N2);\n\n        for (int c = 0; c < N2; ++c) {\n            if (known[c] != -1) continue;\n            if (observed[c] != -1) {\n                newCells.push_back(c);\n                newVals.push_back(observed[c]);\n            } else if (infoMin[c] == infoMax[c]) {\n                newCells.push_back(c);\n                newVals.push_back(infoMin[c]);\n            }\n        }\n\n        if (!newCells.empty()) {\n            // Turn these into hard constraints\n            for (int idx = 0; idx < (int)newCells.size(); ++idx) {\n                int c = newCells[idx];\n                int v = newVals[idx];\n                known[c] = v;\n                applyConstraint(c, v);\n            }\n            continue; // go back to recompute with new constraints\n        }\n\n        // Check if every cell's sign (zero or positive) is already determined.\n        bool allSignKnown = true;\n        for (int c = 0; c < N2; ++c) {\n            // unknown sign if it can be both zero and positive\n            if (infoMin[c] == 0 && infoMax[c] > 0) {\n                allSignKnown = false;\n                break;\n            }\n        }\n        if (allSignKnown) break;\n\n        // Try exact enumeration when search space is small to produce more equalities\n        {\n            vector<int> enumCells;\n            vector<int> enumVals;\n            bool got = tryEnumeration(enumCells, enumVals);\n            if (got) {\n                for (int idx = 0; idx < (int)enumCells.size(); ++idx) {\n                    int c = enumCells[idx];\n                    int v = enumVals[idx];\n                    if (known[c] == -1) {\n                        known[c] = v;\n                        applyConstraint(c, v);\n                    }\n                }\n                continue; // re-run main loop with stronger constraints\n            }\n        }\n\n        // If we have drilled all cells we can (N^2), stop drilling\n        if (drilledCount >= N2) break;\n\n        // Heuristic 1: target fields that already have very few candidates (2 or 3).\n        int bestSmallCell = -1;\n        long long bestSmallScore = -1;\n        for (int k = 0; k < M; ++k) {\n            int tc = totalCandidates[k];\n            if (tc < 2 || tc > 3) continue;\n            for (int c = 0; c < N2; ++c) {\n                if (known[c] != -1) continue;\n                // sign still uncertain?\n                if (!(infoMin[c] == 0 && infoMax[c] > 0)) continue;\n                int cc = coverCount[k][c];\n                if (cc <= 0 || cc >= tc) continue; // no discrimination for this field\n                int elim = min(cc, tc - cc);\n                int diff = infoMax[c] - infoMin[c];\n                long long score = (long long)elim * 2000LL + diff;\n                if (score > bestSmallScore) {\n                    bestSmallScore = score;\n                    bestSmallCell = c;\n                }\n            }\n        }\n\n        int bestCell = -1;\n        long long bestScore = -1; // composite score: elimSum * big + diff\n\n        if (bestSmallCell != -1) {\n            bestCell = bestSmallCell;\n        } else {\n            // General heuristic: choose cell with high elimination potential and/or wide interval\n            for (int c = 0; c < N2; ++c) {\n                if (known[c] != -1) continue;              // already determined\n                if (infoMin[c] == infoMax[c]) continue;    // already effectively determined\n                int diff = infoMax[c] - infoMin[c];\n                int elim = elimSum[c];\n                if (diff <= 0 && elim <= 0) continue;\n                long long score = (long long)elim * 1000LL + diff; // elim dominates\n                if (score > bestScore) {\n                    bestScore = score;\n                    bestCell = c;\n                }\n            }\n            // Fallback: if still none, pick widest interval (very rare)\n            if (bestCell == -1) {\n                int bestDiff = -1;\n                for (int c = 0; c < N2; ++c) {\n                    if (known[c] != -1) continue;\n                    int diff = infoMax[c] - infoMin[c];\n                    if (diff > bestDiff) {\n                        bestDiff = diff;\n                        bestCell = c;\n                    }\n                }\n            }\n        }\n\n        if (bestCell == -1) break; // nothing left to drill\n\n        int bi = bestCell / N;\n        int bj = bestCell % N;\n\n        // Drill this cell\n        cout << \"q 1 \" << bi << ' ' << bj << '\\n' << flush;\n        int v_resp;\n        if (!(cin >> v_resp)) return 0;\n        observed[bestCell] = v_resp;\n        drilledCount++;\n    }\n\n    // Final inference: recompute bounds one last time\n    recomputeCandidateMinMax();\n    recomputeInfoBounds();\n\n    // Build final set of cells with oil (v(c) > 0) using only sign information\n    vector<pair<int,int>> has_oil;\n    has_oil.reserve(N2);\n    for (int c = 0; c < N2; ++c) {\n        bool positive = false;\n        if (observed[c] != -1) {\n            positive = (observed[c] > 0);\n        } else if (known[c] != -1) {\n            positive = (known[c] > 0);\n        } else {\n            // Use sign from infoMin/infoMax.\n            // We know sign is determined for all cells at this point:\n            // positive if min>=1, zero if max==0.\n            if (infoMin[c] >= 1) positive = true;\n            else positive = false; // infoMax[c] must be 0 in this branch\n        }\n        if (positive) {\n            int i = c / N;\n            int j = c % N;\n            has_oil.emplace_back(i, j);\n        }\n    }\n\n    // Output the answer\n    cout << \"a \" << has_oil.size();\n    for (auto &p : has_oil) {\n        cout << ' ' << p.first << ' ' << p.second;\n    }\n    cout << '\\n' << flush;\n\n    // Read verdict (1 = correct, 0 = wrong); should be 1 if logic is correct.\n    int verdict;\n    if (!(cin >> verdict)) return 0;\n\n    return 0;\n}","ahc031":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Rect {\n    int i0, j0, i1, j1;\n};\n\n// Greedy \"water-filling\" stripes assignment.\n// dem: demands (areas) for items (any order).\n// H  : height of stripe region.\n// W  : total width limit.\n// Returns: (shortage in cells, widths per item).\npair<long long, vector<int>> stripes_assign(const vector<long long> &dem, int H, int W) {\n    int M = (int)dem.size();\n    vector<int> w(M, 1);      // each item gets at least width 1\n    int widthSum = M;\n    long long base = H;\n\n    // Max-heap: (residual shortage if width=1, index)\n    priority_queue<pair<long long,int>> pq;\n    for (int i = 0; i < M; i++) {\n        long long r = dem[i] - base;\n        if (r > 0) pq.emplace(r, i);\n    }\n\n    while (widthSum < W && !pq.empty()) {\n        auto [r, idx] = pq.top();\n        pq.pop();\n        if (r <= 0) break;\n        w[idx]++;\n        widthSum++;\n        r -= base;\n        if (r > 0) pq.emplace(r, idx);\n    }\n\n    long long def = 0;\n    for (int i = 0; i < M; i++) {\n        long long cap = 1LL * H * w[i];\n        long long diff = dem[i] - cap;\n        if (diff > 0) def += diff;\n    }\n    return {def, w};\n}\n\n// Single guillotine packing trial, with optional randomized order.\n// shuffleOrder=false: pure area-descending order.\n// shuffleOrder=true : area with small random perturbation.\npair<long long, vector<Rect>> guillotine_trial(\n    const vector<long long> &dem, int W, bool shuffleOrder, mt19937 &rng\n) {\n    int N = (int)dem.size();\n    vector<Rect> rects(N);\n\n    // Build processing order\n    vector<int> order(N);\n    iota(order.begin(), order.end(), 0);\n\n    if (!shuffleOrder) {\n        sort(order.begin(), order.end(),\n             [&](int i, int j){ return dem[i] > dem[j]; });\n    } else {\n        vector<pair<double,int>> key(N);\n        for (int i = 0; i < N; i++) {\n            // Perturb area slightly, factor in [0.9,1.1]\n            double f = 0.9 + (rng() % 2001) * 0.0001; // 0.9..1.1000\n            key[i] = {dem[i] * f, i};\n        }\n        sort(key.begin(), key.end(),\n             [&](const pair<double,int> &a, const pair<double,int> &b){\n                 return a.first > b.first;\n             });\n        for (int i = 0; i < N; i++) order[i] = key[i].second;\n    }\n\n    vector<Rect> freeR;\n    freeR.push_back({0, 0, W, W});\n    vector<bool> assigned(N, false);\n    bool fail = false;\n\n    for (int t = 0; t < N; t++) {\n        int idx = order[t];\n        long long A = dem[idx];\n\n        struct Cand {\n            int f;\n            int orient; // 0 = vertical(full height), 1 = horizontal(full width), 2 = full rect\n            int w, h;\n            long long waste;\n        };\n\n        vector<Cand> cands;\n        int bestSmallF = -1;\n        long long bestSmallArea = -1;\n\n        for (int f = 0; f < (int)freeR.size(); f++) {\n            Rect R = freeR[f];\n            int i0 = R.i0, j0 = R.j0, i1 = R.i1, j1 = R.j1;\n            int rh = i1 - i0;\n            int rw = j1 - j0;\n            if (rh <= 0 || rw <= 0) continue;\n            long long areaR = 1LL * rh * rw;\n\n            if (areaR >= A) {\n                // Vertical option: full height\n                long long reqW = (A + rh - 1) / rh;\n                if (reqW <= rw) {\n                    long long allocArea = 1LL * reqW * rh;\n                    long long waste = allocArea - A;\n                    cands.push_back({f, 0, (int)reqW, rh, waste});\n                }\n                // Horizontal option: full width\n                long long reqH = (A + rw - 1) / rw;\n                if (reqH <= rh) {\n                    long long allocArea = 1LL * reqH * rw;\n                    long long waste = allocArea - A;\n                    cands.push_back({f, 1, rw, (int)reqH, waste});\n                }\n                // Full rectangle option\n                {\n                    long long allocArea = areaR;\n                    long long waste = allocArea - A;\n                    cands.push_back({f, 2, rw, rh, waste});\n                }\n            } else {\n                if (areaR > bestSmallArea) {\n                    bestSmallArea = areaR;\n                    bestSmallF = f;\n                }\n            }\n        }\n\n        int chosenIdx = -1;\n        if (!cands.empty()) {\n            long long minWaste = LLONG_MAX;\n            for (auto &c : cands) if (c.waste < minWaste) minWaste = c.waste;\n            // Deterministic: first minimal-waste candidate\n            for (int i = 0; i < (int)cands.size(); i++) {\n                if (cands[i].waste == minWaste) {\n                    chosenIdx = i;\n                    break;\n                }\n            }\n        }\n\n        if (chosenIdx != -1) {\n            Cand c = cands[chosenIdx];\n            Rect R = freeR[c.f];\n            int i0 = R.i0, j0 = R.j0, i1 = R.i1, j1 = R.j1;\n            if (c.orient == 0) {\n                // Vertical: full height, width = c.w\n                int wAlloc = c.w;\n                Rect used = {i0, j0, i1, j0 + wAlloc};\n                rects[idx] = used;\n                assigned[idx] = true;\n                Rect right = {i0, j0 + wAlloc, i1, j1};\n                freeR[c.f] = freeR.back();\n                freeR.pop_back();\n                if (right.i1 > right.i0 && right.j1 > right.j0) freeR.push_back(right);\n            } else if (c.orient == 1) {\n                // Horizontal: full width, height = c.h\n                int hAlloc = c.h;\n                Rect used = {i0, j0, i0 + hAlloc, j1};\n                rects[idx] = used;\n                assigned[idx] = true;\n                Rect bottom = {i0 + hAlloc, j0, i1, j1};\n                freeR[c.f] = freeR.back();\n                freeR.pop_back();\n                if (bottom.i1 > bottom.i0 && bottom.j1 > bottom.j0) freeR.push_back(bottom);\n            } else {\n                // Full rectangle\n                Rect used = {i0, j0, i1, j1};\n                rects[idx] = used;\n                assigned[idx] = true;\n                freeR[c.f] = freeR.back();\n                freeR.pop_back();\n            }\n        } else {\n            if (bestSmallF == -1) {\n                fail = true;\n                break;\n            }\n            Rect R = freeR[bestSmallF];\n            rects[idx] = R;\n            assigned[idx] = true;\n            freeR[bestSmallF] = freeR.back();\n            freeR.pop_back();\n        }\n    }\n\n    if (fail) return {LLONG_MAX, {}};\n    for (int k = 0; k < N; k++) if (!assigned[k]) return {LLONG_MAX, {}};\n\n    long long def = 0;\n    for (int k = 0; k < N; k++) {\n        const Rect &r = rects[k];\n        long long area = 1LL * (r.i1 - r.i0) * (r.j1 - r.j0);\n        long long diff = dem[k] - area;\n        if (diff > 0) def += diff;\n    }\n    return {def, rects};\n}\n\n// Local search on a guillotine layout: expand rectangles into free cells\n// to reduce total deficiency, without shrinking or moving other rectangles.\nvoid local_improve_guillotine(\n    const vector<long long> &dem, int W, vector<Rect> &rects, long long &def\n) {\n    int N = (int)rects.size();\n    if (def <= 0) return;\n\n    vector<int> occ(W * W, -1);\n    vector<int> h(N), w(N);\n    vector<long long> shortage(N);\n\n    for (int k = 0; k < N; k++) {\n        Rect &r = rects[k];\n        int i0 = r.i0, j0 = r.j0, i1 = r.i1, j1 = r.j1;\n        h[k] = i1 - i0;\n        w[k] = j1 - j0;\n        long long area = 1LL * h[k] * w[k];\n        shortage[k] = max(0LL, dem[k] - area);\n        for (int i = i0; i < i1; i++) {\n            int base = i * W;\n            for (int j = j0; j < j1; j++) {\n                occ[base + j] = k;\n            }\n        }\n    }\n\n    const int LS_PASSES = 2;\n    for (int pass = 0; pass < LS_PASSES; pass++) {\n        bool improved = false;\n\n        vector<int> order(N);\n        iota(order.begin(), order.end(), 0);\n        sort(order.begin(), order.end(),\n             [&](int i, int j){ return shortage[i] > shortage[j]; });\n\n        for (int idx = 0; idx < N; idx++) {\n            int k = order[idx];\n            if (shortage[k] <= 0) continue;\n\n            Rect &r = rects[k];\n            int i0 = r.i0, j0 = r.j0, i1 = r.i1, j1 = r.j1;\n            int hk = h[k], wk = w[k];\n            long long bestImp = 0;\n            int bestDir = -1; // 0=right,1=left,2=down,3=up\n\n            long long areaOld = 1LL * hk * wk;\n\n            // expand right\n            if (j1 < W) {\n                bool ok = true;\n                for (int i = i0; i < i1; i++) {\n                    if (occ[i*W + j1] != -1) { ok = false; break; }\n                }\n                if (ok) {\n                    long long areaNew = areaOld + hk;\n                    long long newShort = max(0LL, dem[k] - areaNew);\n                    long long imp = shortage[k] - newShort;\n                    if (imp > bestImp) { bestImp = imp; bestDir = 0; }\n                }\n            }\n\n            // expand left\n            if (j0 > 0) {\n                bool ok = true;\n                int nj = j0 - 1;\n                for (int i = i0; i < i1; i++) {\n                    if (occ[i*W + nj] != -1) { ok = false; break; }\n                }\n                if (ok) {\n                    long long areaNew = areaOld + hk;\n                    long long newShort = max(0LL, dem[k] - areaNew);\n                    long long imp = shortage[k] - newShort;\n                    if (imp > bestImp) { bestImp = imp; bestDir = 1; }\n                }\n            }\n\n            // expand down\n            if (i1 < W) {\n                bool ok = true;\n                int ni = i1;\n                int base = ni * W;\n                for (int j = j0; j < j1; j++) {\n                    if (occ[base + j] != -1) { ok = false; break; }\n                }\n                if (ok) {\n                    long long areaNew = areaOld + wk;\n                    long long newShort = max(0LL, dem[k] - areaNew);\n                    long long imp = shortage[k] - newShort;\n                    if (imp > bestImp) { bestImp = imp; bestDir = 2; }\n                }\n            }\n\n            // expand up\n            if (i0 > 0) {\n                bool ok = true;\n                int ni = i0 - 1;\n                int base = ni * W;\n                for (int j = j0; j < j1; j++) {\n                    if (occ[base + j] != -1) { ok = false; break; }\n                }\n                if (ok) {\n                    long long areaNew = areaOld + wk;\n                    long long newShort = max(0LL, dem[k] - areaNew);\n                    long long imp = shortage[k] - newShort;\n                    if (imp > bestImp) { bestImp = imp; bestDir = 3; }\n                }\n            }\n\n            if (bestImp > 0 && bestDir != -1) {\n                // Apply best expansion\n                if (bestDir == 0) {\n                    int j = r.j1;\n                    for (int i = r.i0; i < r.i1; i++) occ[i*W + j] = k;\n                    r.j1++; w[k]++;\n                } else if (bestDir == 1) {\n                    int j = r.j0 - 1;\n                    for (int i = r.i0; i < r.i1; i++) occ[i*W + j] = k;\n                    r.j0--; w[k]++;\n                } else if (bestDir == 2) {\n                    int i = r.i1;\n                    int base = i * W;\n                    for (int j = r.j0; j < r.j1; j++) occ[base + j] = k;\n                    r.i1++; h[k]++;\n                } else {\n                    int i = r.i0 - 1;\n                    int base = i * W;\n                    for (int j = r.j0; j < r.j1; j++) occ[base + j] = k;\n                    r.i0--; h[k]++;\n                }\n                long long areaNew = 1LL * h[k] * w[k];\n                shortage[k] = max(0LL, dem[k] - areaNew);\n                improved = true;\n            }\n        }\n\n        if (!improved) break;\n    }\n\n    long long newDef = 0;\n    for (int k = 0; k < N; k++) {\n        long long area = 1LL * (rects[k].i1 - rects[k].i0) * (rects[k].j1 - rects[k].j0);\n        long long diff = dem[k] - area;\n        if (diff > 0) newDef += diff;\n    }\n    def = newDef;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int W, D, N;\n    if (!(cin >> W >> D >> N)) return 0;\n\n    vector<vector<long long>> a(D, vector<long long>(N));\n    for (int d = 0; d < D; d++) {\n        for (int k = 0; k < N; k++) {\n            cin >> a[d][k];\n        }\n    }\n\n    // 5 candidates per day:\n    // 0: stripes\n    // 1: hybrid (small rows + big stripes)\n    // 2..4: guillotine variants (3 best layouts with different geometries)\n    const int C = 5;\n\n    vector<vector<vector<Rect>>> rects(D, vector<vector<Rect>>(C, vector<Rect>(N)));\n    vector<vector<long long>> defCells(D, vector<long long>(C, LLONG_MAX));\n\n    int NSeg = W * (W - 1);\n    int S64 = (NSeg + 63) / 64;\n\n    vector<vector<vector<uint64_t>>> Hbits(D, vector<vector<uint64_t>>(C, vector<uint64_t>(S64)));\n    vector<vector<vector<uint64_t>>> Vbits(D, vector<vector<uint64_t>>(C, vector<uint64_t>(S64)));\n\n    static bool dp[51][1001]; // for hybrid subset-sum\n\n    std::mt19937 rng(1234567);\n\n    // ---------- Build candidates per day ----------\n    for (int d = 0; d < D; d++) {\n        const auto &dem = a[d];\n\n        // Candidate 0: stripes\n        {\n            auto [defStripe, widthsStripe] = stripes_assign(dem, W, W);\n            defCells[d][0] = defStripe;\n            int x = 0;\n            for (int k = 0; k < N; k++) {\n                int w = widthsStripe[k];\n                int j0 = x;\n                int j1 = x + w;\n                if (j1 > W) j1 = W;\n                x = j1;\n                rects[d][0][k] = {0, j0, W, j1};\n            }\n        }\n\n        // Candidate 1: hybrid\n        {\n            vector<int> smallIdx, bigIdx;\n            smallIdx.reserve(N);\n            bigIdx.reserve(N);\n            for (int k = 0; k < N; k++) {\n                if (dem[k] < W) smallIdx.push_back(k);\n                else bigIdx.push_back(k);\n            }\n\n            if (smallIdx.empty()) {\n                rects[d][1] = rects[d][0];\n                defCells[d][1] = defCells[d][0];\n            } else {\n                int S = (int)smallIdx.size();\n                vector<int> smallRow(N, -1), smallJ0(N, 0);\n                vector<int> remaining = smallIdx;\n                vector<int> rowUsedWidth;\n                rowUsedWidth.reserve(S);\n                int row = 0;\n\n                while (!remaining.empty()) {\n                    int M = (int)remaining.size();\n                    vector<int> w(M);\n                    for (int i = 0; i < M; i++) {\n                        w[i] = (int)dem[remaining[i]];\n                    }\n\n                    for (int i = 0; i <= M; i++)\n                        for (int j = 0; j <= W; j++)\n                            dp[i][j] = false;\n                    dp[0][0] = true;\n                    for (int i = 0; i < M; i++) {\n                        int wi = w[i];\n                        for (int j = 0; j <= W; j++) {\n                            if (!dp[i][j]) continue;\n                            dp[i+1][j] = true;\n                            if (j + wi <= W) dp[i+1][j + wi] = true;\n                        }\n                    }\n\n                    int best = 0;\n                    for (int j = W; j >= 1; j--) {\n                        if (dp[M][j]) { best = j; break; }\n                    }\n                    if (best == 0) best = w[0];\n\n                    vector<int> use(M, 0);\n                    int j = best;\n                    for (int i = M - 1; i >= 0; i--) {\n                        if (j >= w[i] && dp[i][j - w[i]]) {\n                            use[i] = 1;\n                            j -= w[i];\n                        } else use[i] = 0;\n                    }\n\n                    int curWidth = 0;\n                    vector<int> newRemaining;\n                    newRemaining.reserve(M);\n                    for (int i = 0; i < M; i++) {\n                        int idx = remaining[i];\n                        if (use[i]) {\n                            int j0 = curWidth;\n                            int j1 = j0 + w[i];\n                            if (j1 > W) j1 = W;\n                            smallRow[idx] = row;\n                            smallJ0[idx] = j0;\n                            curWidth = j1;\n                        } else newRemaining.push_back(idx);\n                    }\n                    remaining.swap(newRemaining);\n                    rowUsedWidth.push_back(curWidth);\n                    row++;\n                }\n\n                int H_small = row;\n                if (H_small > W) {\n                    rects[d][1] = rects[d][0];\n                    defCells[d][1] = defCells[d][0];\n                } else if (bigIdx.empty()) {\n                    for (int idx : smallIdx) {\n                        int r = smallRow[idx];\n                        int j0 = smallJ0[idx];\n                        int j1 = j0 + (int)dem[idx];\n                        if (j1 > W) j1 = W;\n                        rects[d][1][idx] = {r, j0, r + 1, j1};\n                    }\n                    defCells[d][1] = 0;\n                } else {\n                    int H_big = W - H_small;\n                    if (H_big <= 0) {\n                        rects[d][1] = rects[d][0];\n                        defCells[d][1] = defCells[d][0];\n                    } else {\n                        int Mbig = (int)bigIdx.size();\n                        vector<pair<long long,int>> bigList;\n                        bigList.reserve(Mbig);\n                        for (int idx : bigIdx) {\n                            bigList.emplace_back(dem[idx], idx);\n                        }\n                        sort(bigList.begin(), bigList.end(),\n                             [&](const pair<long long,int> &p1, const pair<long long,int> &p2){\n                                 return p1.first < p2.first;\n                             });\n\n                        vector<long long> bigDemands(Mbig);\n                        vector<int> bigOrderIndex(Mbig);\n                        for (int i = 0; i < Mbig; i++) {\n                            bigDemands[i] = bigList[i].first;\n                            bigOrderIndex[i] = bigList[i].second;\n                        }\n\n                        auto [defBig, widthsBig] = stripes_assign(bigDemands, H_big, W);\n\n                        for (int idx : smallIdx) {\n                            int r = smallRow[idx];\n                            int j0 = smallJ0[idx];\n                            int j1 = j0 + (int)dem[idx];\n                            if (j1 > W) j1 = W;\n                            rects[d][1][idx] = {r, j0, r + 1, j1};\n                        }\n\n                        int x = 0;\n                        for (int i = 0; i < Mbig; i++) {\n                            int idx = bigOrderIndex[i];\n                            int w = widthsBig[i];\n                            int j0 = x;\n                            int j1 = x + w;\n                            if (j1 > W) j1 = W;\n                            x = j1;\n                            rects[d][1][idx] = {H_small, j0, W, j1};\n                        }\n\n                        defCells[d][1] = defBig;\n                    }\n                }\n            }\n        }\n\n        // Candidates 2,3,4: guillotine variants\n        {\n            const int TRIALS1 = 20;\n            const int TRIALS2 = 60;\n            const long long DEF_THRESHOLD = 20000;\n\n            struct GCand {\n                long long def;\n                vector<Rect> rect;\n            };\n            vector<GCand> guillCands;\n\n            // Deterministic first trial\n            {\n                auto res0 = guillotine_trial(dem, W, false, rng);\n                if (res0.first != LLONG_MAX) {\n                    guillCands.push_back({res0.first, std::move(res0.second)});\n                }\n            }\n\n            int trialsDone = 1;\n\n            // Randomized trials\n            for (; trialsDone < TRIALS1; trialsDone++) {\n                auto res = guillotine_trial(dem, W, true, rng);\n                if (res.first != LLONG_MAX) {\n                    guillCands.push_back({res.first, std::move(res.second)});\n                }\n            }\n\n            // Extra trials for hard days (large deficiency)\n            long long bestSoFar = LLONG_MAX;\n            for (auto &g : guillCands) bestSoFar = min(bestSoFar, g.def);\n            if (bestSoFar > 0 && bestSoFar > DEF_THRESHOLD) {\n                for (; trialsDone < TRIALS2; trialsDone++) {\n                    auto res = guillotine_trial(dem, W, true, rng);\n                    if (res.first != LLONG_MAX) {\n                        guillCands.push_back({res.first, std::move(res.second)});\n                        bestSoFar = min(bestSoFar, res.first);\n                    }\n                    if (bestSoFar == 0) break;\n                }\n            }\n\n            if (guillCands.empty()) {\n                // fallback all guill candidates to stripes\n                for (int cid = 2; cid <= 4; cid++) {\n                    rects[d][cid] = rects[d][0];\n                    defCells[d][cid] = defCells[d][0];\n                }\n            } else {\n                // sort by deficiency and keep up to 3\n                sort(guillCands.begin(), guillCands.end(),\n                     [](const GCand &a, const GCand &b){ return a.def < b.def; });\n\n                int K = min(3, (int)guillCands.size());\n\n                // Candidate 2: best, apply local search\n                rects[d][2] = guillCands[0].rect;\n                defCells[d][2] = guillCands[0].def;\n                if (defCells[d][2] > 0) {\n                    local_improve_guillotine(dem, W, rects[d][2], defCells[d][2]);\n                }\n\n                // Candidates 3 and 4: next best raw\n                if (K >= 2) {\n                    rects[d][3] = guillCands[1].rect;\n                    defCells[d][3] = guillCands[1].def;\n                } else {\n                    rects[d][3] = rects[d][2];\n                    defCells[d][3] = defCells[d][2];\n                }\n                if (K >= 3) {\n                    rects[d][4] = guillCands[2].rect;\n                    defCells[d][4] = guillCands[2].def;\n                } else {\n                    rects[d][4] = rects[d][2];\n                    defCells[d][4] = defCells[d][2];\n                }\n            }\n        }\n\n        // Build H/V bitsets\n        for (int c = 0; c < C; c++) {\n            fill(Hbits[d][c].begin(), Hbits[d][c].end(), 0ULL);\n            fill(Vbits[d][c].begin(), Vbits[d][c].end(), 0ULL);\n\n            for (int k = 0; k < N; k++) {\n                const Rect &r = rects[d][c][k];\n                int i0 = r.i0, j0 = r.j0, i1 = r.i1, j1 = r.j1;\n\n                // Horizontal edges: (i,j)-(i,j+1), 1<=i<=W-1, 0<=j<=W-1\n                if (i0 > 0) {\n                    int i = i0;\n                    int base = (i - 1) * W;\n                    for (int j = j0; j < j1; j++) {\n                        int idx = base + j;\n                        int word = idx >> 6;\n                        int bit = idx & 63;\n                        Hbits[d][c][word] |= (1ULL << bit);\n                    }\n                }\n                if (i1 < W) {\n                    int i = i1;\n                    int base = (i - 1) * W;\n                    for (int j = j0; j < j1; j++) {\n                        int idx = base + j;\n                        int word = idx >> 6;\n                        int bit = idx & 63;\n                        Hbits[d][c][word] |= (1ULL << bit);\n                    }\n                }\n\n                // Vertical edges: (i,j)-(i+1,j), 0<=i<=W-1, 1<=j<=W-1\n                if (j0 > 0) {\n                    int j = j0;\n                    for (int i = i0; i < i1; i++) {\n                        int idx = i * (W - 1) + (j - 1);\n                        int word = idx >> 6;\n                        int bit = idx & 63;\n                        Vbits[d][c][word] |= (1ULL << bit);\n                    }\n                }\n                if (j1 < W) {\n                    int j = j1;\n                    for (int i = i0; i < i1; i++) {\n                        int idx = i * (W - 1) + (j - 1);\n                        int word = idx >> 6;\n                        int bit = idx & 63;\n                        Vbits[d][c][word] |= (1ULL << bit);\n                    }\n                }\n            }\n        }\n    }\n\n    // ---------- DP over days to select candidate per day ----------\n    vector<long long> dpPrev(C, LLONG_MAX), dpCur(C, LLONG_MAX);\n    vector<array<int,5>> parent(D);\n\n    // Day 0: L0 = 0\n    for (int c = 0; c < C; c++) {\n        long long areaCost = defCells[0][c] * 100LL;\n        dpPrev[c] = areaCost;\n        parent[0][c] = -1;\n    }\n\n    for (int d = 1; d < D; d++) {\n        for (int c = 0; c < C; c++) dpCur[c] = LLONG_MAX;\n\n        long long L[5][5];\n        for (int p = 0; p < C; p++) {\n            for (int c = 0; c < C; c++) {\n                long long l = 0;\n                // Horizontal segments\n                for (int w64 = 0; w64 < S64; w64++) {\n                    uint64_t x = Hbits[d-1][p][w64] ^ Hbits[d][c][w64];\n                    if (x) l += __builtin_popcountll(x);\n                }\n                // Vertical segments\n                for (int w64 = 0; w64 < S64; w64++) {\n                    uint64_t x = Vbits[d-1][p][w64] ^ Vbits[d][c][w64];\n                    if (x) l += __builtin_popcountll(x);\n                }\n                L[p][c] = l;\n            }\n        }\n\n        for (int c = 0; c < C; c++) {\n            long long areaCost = defCells[d][c] * 100LL;\n            long long best = LLONG_MAX;\n            int bestPrev = -1;\n            for (int p = 0; p < C; p++) {\n                if (dpPrev[p] == LLONG_MAX) continue;\n                long long cost = dpPrev[p] + areaCost + L[p][c];\n                if (cost < best) {\n                    best = cost;\n                    bestPrev = p;\n                }\n            }\n            dpCur[c] = best;\n            parent[d][c] = bestPrev;\n        }\n        dpPrev.swap(dpCur);\n    }\n\n    long long bestTotal = LLONG_MAX;\n    int lastC = 0;\n    for (int c = 0; c < C; c++) {\n        if (dpPrev[c] < bestTotal) {\n            bestTotal = dpPrev[c];\n            lastC = c;\n        }\n    }\n\n    vector<int> chosen(D);\n    chosen[D-1] = lastC;\n    for (int d = D-1; d >= 1; d--) {\n        chosen[d-1] = parent[d][chosen[d]];\n    }\n\n    // Output rectangles\n    for (int d = 0; d < D; d++) {\n        int c = chosen[d];\n        for (int k = 0; k < N; k++) {\n            Rect r = rects[d][c][k];\n            int i0 = r.i0, j0 = r.j0, i1 = r.i1, j1 = r.j1;\n            if (i0 < 0) i0 = 0;\n            if (j0 < 0) j0 = 0;\n            if (i1 > W) i1 = W;\n            if (j1 > W) j1 = W;\n            if (i0 >= i1) i1 = min(W, i0 + 1);\n            if (j0 >= j1) j1 = min(W, j0 + 1);\n            cout << i0 << ' ' << j0 << ' ' << i1 << ' ' << j1 << '\\n';\n        }\n    }\n\n    return 0;\n}","ahc032":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const long long MOD = 998244353LL;\n\n// Fast RNG (xorshift64)\nstruct XorShift64 {\n    uint64_t x;\n    XorShift64(uint64_t seed = 88172645463325252ull) {\n        x = seed ? seed : 88172645463325252ull;\n    }\n    inline uint64_t next() {\n        uint64_t y = x;\n        y ^= y << 7;\n        y ^= y >> 9;\n        return x = y;\n    }\n    inline int next_int(int n) { // 0..n-1\n        return (int)(next() % (uint64_t)n);\n    }\n    inline double next_double() { // [0,1)\n        return (next() >> 11) * (1.0 / (1ULL << 53));\n    }\n};\n\nstruct Op {\n    int m, p, q;\n};\n\nstruct CellChange {\n    int idx;\n    int oldv;\n    int newv;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    auto global_start = chrono::steady_clock::now();\n    const double TOTAL_LIMIT = 1.9; // safety margin under 2.0s\n\n    int N, M, K;\n    if (!(cin >> N >> M >> K)) return 0;\n    const int NN = N * N;\n\n    // Read initial board\n    vector<int> initial_board(NN);\n    long long initial_score = 0;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            long long v;\n            cin >> v;\n            v %= MOD;\n            initial_board[i * N + j] = (int)v;\n            initial_score += v;\n        }\n    }\n\n    // Read stamps s[m][3][3]\n    static int s[20][3][3];\n    for (int m = 0; m < M; ++m) {\n        for (int i = 0; i < 3; ++i) {\n            for (int j = 0; j < 3; ++j) {\n                long long v;\n                cin >> v;\n                v %= MOD;\n                s[m][i][j] = (int)v;\n            }\n        }\n    }\n\n    // Precompute candidate operations (m,p,q)\n    vector<Op> all_ops;\n    all_ops.reserve(M * (N - 2) * (N - 2));\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                all_ops.push_back({m, p, q});\n            }\n        }\n    }\n    const int NUM_OPS = (int)all_ops.size(); // 980 for N=9,M=20\n\n    // Precompute for each op: its 9 cell indices and increments\n    vector<array<int, 9>> op_cells(NUM_OPS);\n    vector<array<int, 9>> op_vals(NUM_OPS);\n    vector<array<int8_t, 81>> op_pos(NUM_OPS); // board index -> pos or -1\n\n    for (int op_id = 0; op_id < NUM_OPS; ++op_id) {\n        const Op &op = all_ops[op_id];\n        int m = op.m, p = op.p, q = op.q;\n        array<int, 9> cells;\n        array<int, 9> vals;\n        int t = 0;\n        for (int di = 0; di < 3; ++di) {\n            int r = p + di;\n            int base = r * N;\n            for (int dj = 0; dj < 3; ++dj) {\n                int c = q + dj;\n                int idx = base + c;\n                cells[t] = idx;\n                vals[t] = s[m][di][dj];\n                ++t;\n            }\n        }\n        op_cells[op_id] = cells;\n        op_vals[op_id] = vals;\n\n        auto &pm = op_pos[op_id];\n        pm.fill(-1);\n        for (int i = 0; i < 9; ++i) {\n            pm[cells[i]] = (int8_t)i;\n        }\n    }\n\n    // RNG\n    uint64_t seed = chrono::high_resolution_clock::now().time_since_epoch().count();\n    XorShift64 rng(seed);\n\n    // Greedy initial solution\n    vector<int> board = initial_board;\n    long long cur_score = initial_score;\n    vector<int> cur_ops;\n    cur_ops.reserve(K);\n\n    for (int step = 0; step < K; ++step) {\n        long long best_delta = 0;\n        int best_id = -1;\n        for (int op_id = 0; op_id < NUM_OPS; ++op_id) {\n            const auto &cells = op_cells[op_id];\n            const auto &vals  = op_vals[op_id];\n            long long delta = 0;\n            for (int t = 0; t < 9; ++t) {\n                int d = vals[t];\n                if (d == 0) continue;\n                int idx = cells[t];\n                int x = board[idx];\n                int tmp = x + d;\n                if (tmp >= MOD) tmp -= MOD;\n                delta += tmp - x;\n            }\n            if (delta > best_delta) {\n                best_delta = delta;\n                best_id = op_id;\n            }\n        }\n        if (best_id == -1 || best_delta <= 0) break;\n\n        const auto &cells = op_cells[best_id];\n        const auto &vals  = op_vals[best_id];\n        for (int t = 0; t < 9; ++t) {\n            int d = vals[t];\n            if (d == 0) continue;\n            int idx = cells[t];\n            int x = board[idx];\n            int tmp = x + d;\n            if (tmp >= MOD) tmp -= MOD;\n            board[idx] = tmp;\n        }\n        cur_score += best_delta;\n        cur_ops.push_back(best_id);\n    }\n\n    long long best_score = cur_score;\n    vector<int> best_ops = cur_ops;\n\n    // Simulated Annealing (single run)\n    const double SA_TIME_LIMIT = 1.6; // seconds within TOTAL_LIMIT\n    auto sa_start = chrono::steady_clock::now();\n    const double T0 = 1e9;\n    const double T_end = 1e6;\n    double T = T0;\n\n    CellChange changes[18]; // max affected cells for REPLACE\n    int iteration = 0;\n\n    while (true) {\n        if ((iteration & 1023) == 0) {\n            auto now = chrono::steady_clock::now();\n            double elapsed_sa = chrono::duration<double>(now - sa_start).count();\n            if (elapsed_sa >= SA_TIME_LIMIT) break;\n            double global_elapsed = chrono::duration<double>(now - global_start).count();\n            if (global_elapsed >= TOTAL_LIMIT - 0.1) break;\n            double progress = elapsed_sa / SA_TIME_LIMIT;\n            if (progress > 1.0) progress = 1.0;\n            T = T0 + (T_end - T0) * progress;\n        }\n        ++iteration;\n\n        int L = (int)cur_ops.size();\n        int move_type; // 0=ADD,1=REMOVE,2=REPLACE\n        if (L == 0) {\n            move_type = 0;\n        } else if (L == K) {\n            move_type = (rng.next_int(2) == 0 ? 1 : 2);\n        } else {\n            int r = rng.next_int(100);\n            if (r < 40) move_type = 0;        // 40% ADD\n            else if (r < 80) move_type = 2;   // 40% REPLACE\n            else move_type = 1;               // 20% REMOVE\n        }\n\n        long long deltaScore = 0;\n        int chN = 0;\n\n        if (move_type == 0) { // ADD\n            int op_new = rng.next_int(NUM_OPS);\n            const auto &cells = op_cells[op_new];\n            const auto &vals  = op_vals[op_new];\n\n            deltaScore = 0;\n            chN = 0;\n            for (int t = 0; t < 9; ++t) {\n                int d = vals[t];\n                if (d == 0) continue;\n                int idx = cells[t];\n                int x = board[idx];\n                int tmp = x + d;\n                if (tmp >= MOD) tmp -= MOD;\n                if (tmp != x) {\n                    deltaScore += tmp - x;\n                    changes[chN++] = {idx, x, tmp};\n                }\n            }\n\n            bool accept;\n            if (deltaScore >= 0) {\n                accept = true;\n            } else if (-deltaScore > 20.0 * T) {\n                accept = false;\n            } else {\n                double prob = exp((double)deltaScore / T);\n                accept = (rng.next_double() < prob);\n            }\n\n            if (accept) {\n                for (int i = 0; i < chN; ++i) {\n                    board[changes[i].idx] = changes[i].newv;\n                }\n                cur_score += deltaScore;\n                cur_ops.push_back(op_new);\n                if (cur_score > best_score) {\n                    best_score = cur_score;\n                    best_ops = cur_ops;\n                }\n            }\n\n        } else if (move_type == 1) { // REMOVE\n            if (L == 0) continue;\n            int idx_op = rng.next_int(L);\n            int op_old = cur_ops[idx_op];\n            const auto &cells = op_cells[op_old];\n            const auto &vals  = op_vals[op_old];\n\n            deltaScore = 0;\n            chN = 0;\n            for (int t = 0; t < 9; ++t) {\n                int d = vals[t];\n                if (d == 0) continue;\n                int idx = cells[t];\n                int x = board[idx];\n                int tmp = x - d;\n                if (tmp < 0) tmp += MOD;\n                if (tmp != x) {\n                    deltaScore += tmp - x;\n                    changes[chN++] = {idx, x, tmp};\n                }\n            }\n\n            bool accept;\n            if (deltaScore >= 0) {\n                accept = true;\n            } else if (-deltaScore > 20.0 * T) {\n                accept = false;\n            } else {\n                double prob = exp((double)deltaScore / T);\n                accept = (rng.next_double() < prob);\n            }\n\n            if (accept) {\n                for (int i = 0; i < chN; ++i) {\n                    board[changes[i].idx] = changes[i].newv;\n                }\n                cur_score += deltaScore;\n                cur_ops[idx_op] = cur_ops.back();\n                cur_ops.pop_back();\n                if (cur_score > best_score) {\n                    best_score = cur_score;\n                    best_ops = cur_ops;\n                }\n            }\n\n        } else { // REPLACE\n            if (L == 0) continue;\n            int idx_old = rng.next_int(L);\n            int op_old = cur_ops[idx_old];\n            int op_new = rng.next_int(NUM_OPS);\n            if (op_new == op_old) continue;\n\n            const auto &cellsOld = op_cells[op_old];\n            const auto &valsOld  = op_vals[op_old];\n            const auto &cellsNew = op_cells[op_new];\n            const auto &valsNew  = op_vals[op_new];\n\n            int idxList[18];\n            int uc = 0;\n            for (int t = 0; t < 9; ++t) idxList[uc++] = cellsOld[t];\n            for (int t = 0; t < 9; ++t) {\n                int idx = cellsNew[t];\n                bool found = false;\n                for (int z = 0; z < uc; ++z) {\n                    if (idxList[z] == idx) { found = true; break; }\n                }\n                if (!found) idxList[uc++] = idx;\n            }\n\n            auto &posOldMap = op_pos[op_old];\n            auto &posNewMap = op_pos[op_new];\n\n            deltaScore = 0;\n            chN = 0;\n            for (int t = 0; t < uc; ++t) {\n                int idx = idxList[t];\n                int x = board[idx];\n\n                int posOld = (int)posOldMap[idx];\n                int d_old = (posOld >= 0 ? valsOld[posOld] : 0);\n                int posNew = (int)posNewMap[idx];\n                int d_new = (posNew >= 0 ? valsNew[posNew] : 0);\n                int diff = d_new - d_old;\n                if (diff == 0) continue;\n\n                int tmp = x + diff;\n                if (tmp < 0) tmp += MOD;\n                else if (tmp >= MOD) tmp -= MOD;\n\n                if (tmp != x) {\n                    deltaScore += tmp - x;\n                    changes[chN++] = {idx, x, tmp};\n                }\n            }\n\n            bool accept;\n            if (deltaScore >= 0) {\n                accept = true;\n            } else if (-deltaScore > 20.0 * T) {\n                accept = false;\n            } else {\n                double prob = exp((double)deltaScore / T);\n                accept = (rng.next_double() < prob);\n            }\n\n            if (accept) {\n                for (int i = 0; i < chN; ++i) {\n                    board[changes[i].idx] = changes[i].newv;\n                }\n                cur_score += deltaScore;\n                cur_ops[idx_old] = op_new;\n                if (cur_score > best_score) {\n                    best_score = cur_score;\n                    best_ops = cur_ops;\n                }\n            }\n        }\n    }\n\n    // Final deterministic local improvement from best SA solution\n    vector<int> sol_ops = best_ops;\n    vector<int> boardHC = initial_board;\n    long long scoreHC = initial_score;\n\n    // Rebuild boardHC\n    for (int op_id : sol_ops) {\n        const auto &cells = op_cells[op_id];\n        const auto &vals  = op_vals[op_id];\n        for (int t = 0; t < 9; ++t) {\n            int d = vals[t];\n            if (d == 0) continue;\n            int idx = cells[t];\n            int x = boardHC[idx];\n            int tmp = x + d;\n            if (tmp >= MOD) tmp -= MOD;\n            boardHC[idx] = tmp;\n            scoreHC += tmp - x;\n        }\n    }\n\n    // Hill climbing: best ADD / best REMOVE\n    const int MAX_HC_ITERS = 2000;\n    for (int iter = 0; iter < MAX_HC_ITERS; ++iter) {\n        auto now = chrono::steady_clock::now();\n        double elapsed_total = chrono::duration<double>(now - global_start).count();\n        if (elapsed_total >= TOTAL_LIMIT) break;\n\n        int L = (int)sol_ops.size();\n\n        long long bestAddDelta = 0;\n        int bestAddOp = -1;\n        if (L < K) {\n            for (int op_id = 0; op_id < NUM_OPS; ++op_id) {\n                const auto &cells = op_cells[op_id];\n                const auto &vals  = op_vals[op_id];\n                long long delta = 0;\n                for (int t = 0; t < 9; ++t) {\n                    int d = vals[t];\n                    if (d == 0) continue;\n                    int idx = cells[t];\n                    int x = boardHC[idx];\n                    int tmp = x + d;\n                    if (tmp >= MOD) tmp -= MOD;\n                    delta += tmp - x;\n                }\n                if (delta > bestAddDelta) {\n                    bestAddDelta = delta;\n                    bestAddOp = op_id;\n                }\n            }\n        }\n\n        long long bestRemDelta = 0;\n        int bestRemIdx = -1;\n        for (int i = 0; i < L; ++i) {\n            int op_id = sol_ops[i];\n            const auto &cells = op_cells[op_id];\n            const auto &vals  = op_vals[op_id];\n            long long delta = 0;\n            for (int t = 0; t < 9; ++t) {\n                int d = vals[t];\n                if (d == 0) continue;\n                int idx = cells[t];\n                int x = boardHC[idx];\n                int tmp = x - d;\n                if (tmp < 0) tmp += MOD;\n                delta += tmp - x;\n            }\n            if (delta > bestRemDelta) {\n                bestRemDelta = delta;\n                bestRemIdx = i;\n            }\n        }\n\n        if (bestAddDelta <= 0 && bestRemDelta <= 0) break;\n\n        if (bestAddDelta >= bestRemDelta && bestAddDelta > 0 && L < K && bestAddOp != -1) {\n            // Apply best ADD\n            const auto &cells = op_cells[bestAddOp];\n            const auto &vals  = op_vals[bestAddOp];\n            for (int t = 0; t < 9; ++t) {\n                int d = vals[t];\n                if (d == 0) continue;\n                int idx = cells[t];\n                int x = boardHC[idx];\n                int tmp = x + d;\n                if (tmp >= MOD) tmp -= MOD;\n                boardHC[idx] = tmp;\n                scoreHC += tmp - x;\n            }\n            sol_ops.push_back(bestAddOp);\n        } else if (bestRemDelta > 0 && bestRemIdx != -1) {\n            // Apply best REMOVE\n            int op_id = sol_ops[bestRemIdx];\n            const auto &cells = op_cells[op_id];\n            const auto &vals  = op_vals[op_id];\n            for (int t = 0; t < 9; ++t) {\n                int d = vals[t];\n                if (d == 0) continue;\n                int idx = cells[t];\n                int x = boardHC[idx];\n                int tmp = x - d;\n                if (tmp < 0) tmp += MOD;\n                boardHC[idx] = tmp;\n                scoreHC += tmp - x;\n            }\n            sol_ops[bestRemIdx] = sol_ops.back();\n            sol_ops.pop_back();\n        } else {\n            break;\n        }\n    }\n\n    // Extra random REPLACE hill-climb (only accept positive moves)\n    const int MAX_RR_TRIES = 200000;\n    int tries = 0;\n    while (tries < MAX_RR_TRIES) {\n        auto now = chrono::steady_clock::now();\n        double elapsed_total = chrono::duration<double>(now - global_start).count();\n        if (elapsed_total >= TOTAL_LIMIT) break;\n\n        int L = (int)sol_ops.size();\n        if (L == 0) break;\n\n        int idx_old = rng.next_int(L);\n        int op_old = sol_ops[idx_old];\n        int op_new = rng.next_int(NUM_OPS);\n        if (op_new == op_old) {\n            ++tries;\n            continue;\n        }\n\n        const auto &cellsOld = op_cells[op_old];\n        const auto &valsOld  = op_vals[op_old];\n        const auto &cellsNew = op_cells[op_new];\n        const auto &valsNew  = op_vals[op_new];\n        auto &posOldMap = op_pos[op_old];\n        auto &posNewMap = op_pos[op_new];\n\n        int idxList[18];\n        int uc = 0;\n        for (int t = 0; t < 9; ++t) idxList[uc++] = cellsOld[t];\n        for (int t = 0; t < 9; ++t) {\n            int idx = cellsNew[t];\n            bool found = false;\n            for (int z = 0; z < uc; ++z) {\n                if (idxList[z] == idx) { found = true; break; }\n            }\n            if (!found) idxList[uc++] = idx;\n        }\n\n        long long delta = 0;\n        for (int t = 0; t < uc; ++t) {\n            int idx = idxList[t];\n            int x = boardHC[idx];\n\n            int posOld = (int)posOldMap[idx];\n            int d_old = (posOld >= 0 ? valsOld[posOld] : 0);\n            int posNew = (int)posNewMap[idx];\n            int d_new = (posNew >= 0 ? valsNew[posNew] : 0);\n            int diff = d_new - d_old;\n            if (diff == 0) continue;\n\n            int tmp = x + diff;\n            if (tmp < 0) tmp += MOD;\n            else if (tmp >= MOD) tmp -= MOD;\n            delta += tmp - x;\n        }\n\n        if (delta > 0) {\n            // apply replace\n            for (int t = 0; t < uc; ++t) {\n                int idx = idxList[t];\n                int x = boardHC[idx];\n\n                int posOld = (int)posOldMap[idx];\n                int d_old = (posOld >= 0 ? valsOld[posOld] : 0);\n                int posNew = (int)posNewMap[idx];\n                int d_new = (posNew >= 0 ? valsNew[posNew] : 0);\n                int diff = d_new - d_old;\n                if (diff == 0) continue;\n\n                int tmp = x + diff;\n                if (tmp < 0) tmp += MOD;\n                else if (tmp >= MOD) tmp -= MOD;\n                boardHC[idx] = tmp;\n            }\n            scoreHC += delta;\n            sol_ops[idx_old] = op_new;\n            tries = 0; // reset after improvement\n        } else {\n            ++tries;\n        }\n    }\n\n    // Output final solution\n    cout << (int)sol_ops.size() << '\\n';\n    for (int op_id : sol_ops) {\n        const Op &op = all_ops[op_id];\n        cout << op.m << ' ' << op.p << ' ' << op.q << '\\n';\n    }\n\n    return 0;\n}","ahc033":"#include <bits/stdc++.h>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    if (!(cin >> N)) return 0; // N == 5\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    const int totalContainers = N * N; // 25\n\n    // For each container id, its receiving (spawn) row.\n    vector<int> spawnRow(totalContainers);\n    for (int r = 0; r < N; ++r) {\n        for (int j = 0; j < N; ++j) {\n            int id = A[r][j];\n            spawnRow[id] = r;\n        }\n    }\n\n    // Grid: -1 = empty, otherwise container id.\n    vector<vector<int>> grid(N, vector<int>(N, -1));\n\n    // Container states.\n    const int NOT_SPAWNED = 0, ON_GRID = 1, CARRIED = 2, DISPATCHED = 3;\n    vector<int> state(totalContainers, NOT_SPAWNED);\n\n    // Positions of containers when ON_GRID; (-1,-1) otherwise.\n    vector<int> posx(totalContainers, -1), posy(totalContainers, -1);\n\n    // Receiving gate spawn indices per row.\n    int next_idx[5] = {0, 0, 0, 0, 0};\n    bool spawn_done[5] = {false, false, false, false, false};\n\n    // Big crane (index 0).\n    int bx = 0, by = 0;    // position\n    int carry = -1;        // carried container id, -1 if none\n\n    // For each dispatch row r, next id to dispatch for that row.\n    int nextRowId[5];\n    for (int r = 0; r < N; ++r) nextRowId[r] = r * N;\n\n    // Operation strings for cranes.\n    vector<string> ops(N);\n\n    int dispatched_count = 0;\n\n    auto stepTowards = [&](int gx, int gy) -> char {\n        if (bx < gx) return 'D';\n        if (bx > gx) return 'U';\n        if (by < gy) return 'R';\n        if (by > gy) return 'L';\n        return '.';\n    };\n\n    const int MAX_TURNS = 10000;\n    for (int t = 0; t < MAX_TURNS && dispatched_count < totalContainers; ++t) {\n        // Step 1: spawn containers at receiving gates.\n        for (int r = 0; r < N; ++r) {\n            if (next_idx[r] < N &&\n                grid[r][0] == -1 &&\n                !(carry != -1 && bx == r && by == 0)) {\n                int id = A[r][next_idx[r]];\n                grid[r][0] = id;\n                state[id] = ON_GRID;\n                posx[id] = r;\n                posy[id] = 0;\n                ++next_idx[r];\n                if (next_idx[r] == N) spawn_done[r] = true;\n            }\n        }\n\n        // Step 2: decide big crane command.\n        char big_cmd = '.';\n\n        if (dispatched_count >= totalContainers) {\n            big_cmd = '.';\n        } else if (carry != -1) {\n            // Carrying some container.\n            int rc = carry / N;\n            if (carry == nextRowId[rc]) {\n                // This container is the next required for its row -> dispatch it.\n                int gx = rc;\n                int gy = N - 1;\n                if (bx == gx && by == gy) {\n                    big_cmd = 'Q';\n                } else {\n                    big_cmd = stepTowards(gx, gy);\n                }\n            } else {\n                // Not yet needed for its row -> store it.\n                int dr = carry / N;\n\n                // Prefer storing in dest row dr.\n                bool storedHere = false;\n                if (bx == dr && by >= 1 && by <= N - 2 && grid[bx][by] == -1) {\n                    // Already at an empty interior cell in dest row.\n                    big_cmd = 'Q';\n                    storedHere = true;\n                }\n\n                if (!storedHere) {\n                    int bestX = -1, bestY = -1;\n                    int bestDist = INT_MAX;\n\n                    // 1) Dest row interior cells (dr,1..3).\n                    for (int y = 1; y <= N - 2; ++y) {\n                        if (grid[dr][y] == -1) {\n                            int dist = abs(bx - dr) + abs(by - y);\n                            if (dist < bestDist) {\n                                bestDist = dist;\n                                bestX = dr;\n                                bestY = y;\n                            }\n                        }\n                    }\n                    // 2) Dest row gate (dr,0) if spawn is done.\n                    if (spawn_done[dr] && grid[dr][0] == -1) {\n                        int dist = abs(bx - dr) + abs(by - 0);\n                        if (dist < bestDist) {\n                            bestDist = dist;\n                            bestX = dr;\n                            bestY = 0;\n                        }\n                    }\n\n                    if (bestX != -1) {\n                        // We found a destination-row storage spot.\n                        if (bx == bestX && by == bestY) {\n                            big_cmd = 'Q';\n                        } else {\n                            big_cmd = stepTowards(bestX, bestY);\n                        }\n                    } else {\n                        // No dest-row spot; fallback to global interior / finished gates.\n                        bool canStoreHere = (by >= 1 && by <= N - 2 && grid[bx][by] == -1);\n                        if (canStoreHere) {\n                            big_cmd = 'Q';\n                        } else {\n                            int gX = -1, gY = -1;\n                            int gDist = INT_MAX;\n\n                            // Global interior cells.\n                            for (int x = 0; x < N; ++x) {\n                                for (int y = 1; y <= N - 2; ++y) {\n                                    if (grid[x][y] == -1) {\n                                        int dist = abs(bx - x) + abs(by - y);\n                                        if (dist < gDist) {\n                                            gDist = dist;\n                                            gX = x; gY = y;\n                                        }\n                                    }\n                                }\n                            }\n                            // Gates of rows whose spawn is done.\n                            for (int x = 0; x < N; ++x) {\n                                if (spawn_done[x] && grid[x][0] == -1) {\n                                    int dist = abs(bx - x) + abs(by - 0);\n                                    if (dist < gDist) {\n                                        gDist = dist;\n                                        gX = x; gY = 0;\n                                    }\n                                }\n                            }\n\n                            if (gX != -1) {\n                                if (bx == gX && by == gY) {\n                                    big_cmd = 'Q';\n                                } else {\n                                    big_cmd = stepTowards(gX, gY);\n                                }\n                            } else {\n                                // Extremely unlikely: no place to store, just idle.\n                                big_cmd = '.';\n                            }\n                        }\n                    }\n                }\n            }\n        } else {\n            // Not carrying: choose best next target among rows.\n            int bestId = -1;\n            int bestCost = INT_MAX;\n\n            for (int r = 0; r < N; ++r) {\n                // Ensure nextRowId[r] is not behind (safety).\n                while (nextRowId[r] < (r + 1) * N &&\n                       state[nextRowId[r]] == DISPATCHED) {\n                    ++nextRowId[r];\n                }\n                int id = nextRowId[r];\n                if (id >= (r + 1) * N) continue; // row r done\n\n                if (state[id] == ON_GRID) {\n                    int cx = posx[id], cy = posy[id];\n                    if (cx == -1) continue; // safety\n                    int dist = abs(bx - cx) + abs(by - cy);\n                    int cost = dist; // ON_GRID preferred (no penalty)\n                    if (cost < bestCost) {\n                        bestCost = cost;\n                        bestId = id;\n                    }\n                } else if (state[id] == NOT_SPAWNED) {\n                    int sr = spawnRow[id];\n                    int distGate = abs(bx - sr) + abs(by - 0);\n                    // Large penalty to prefer ON_GRID containers first.\n                    int extra = 20;\n                    int cost = distGate + extra;\n                    if (cost < bestCost) {\n                        bestCost = cost;\n                        bestId = id;\n                    }\n                }\n                // CARRIED case should not happen here.\n            }\n\n            if (bestId == -1) {\n                big_cmd = '.';\n            } else if (state[bestId] == ON_GRID) {\n                int cx = posx[bestId], cy = posy[bestId];\n                if (bx == cx && by == cy) {\n                    big_cmd = 'P';\n                } else {\n                    big_cmd = stepTowards(cx, cy);\n                }\n            } else if (state[bestId] == NOT_SPAWNED) {\n                int sr = spawnRow[bestId];\n                if (grid[sr][0] != -1) {\n                    // Clear blocking container from its gate.\n                    if (bx == sr && by == 0) {\n                        big_cmd = 'P';\n                    } else {\n                        big_cmd = stepTowards(sr, 0);\n                    }\n                } else {\n                    // Gate empty but id not spawned yet: move to gate and wait.\n                    if (bx == sr && by == 0) {\n                        big_cmd = '.';\n                    } else {\n                        big_cmd = stepTowards(sr, 0);\n                    }\n                }\n            } else {\n                big_cmd = '.';\n            }\n        }\n\n        // Small cranes: bomb at t=0, then idle.\n        char small_cmd = (t == 0 ? 'B' : '.');\n        ops[0].push_back(big_cmd);\n        for (int i = 1; i < N; ++i) ops[i].push_back(small_cmd);\n\n        // Apply big crane action.\n        if (big_cmd == 'P') {\n            if (carry == -1 && grid[bx][by] != -1) {\n                carry = grid[bx][by];\n                state[carry] = CARRIED;\n                posx[carry] = -1;\n                posy[carry] = -1;\n                grid[bx][by] = -1;\n            }\n        } else if (big_cmd == 'Q') {\n            if (carry != -1 && grid[bx][by] == -1) {\n                grid[bx][by] = carry;\n                state[carry] = ON_GRID;\n                posx[carry] = bx;\n                posy[carry] = by;\n                carry = -1;\n            }\n        } else if (big_cmd == 'U') {\n            if (bx > 0) --bx;\n        } else if (big_cmd == 'D') {\n            if (bx < N - 1) ++bx;\n        } else if (big_cmd == 'L') {\n            if (by > 0) --by;\n        } else if (big_cmd == 'R') {\n            if (by < N - 1) ++by;\n        } else {\n            // '.', 'B' for big crane: no movement.\n        }\n\n        // Step 3: dispatch containers at right edge.\n        for (int i = 0; i < N; ++i) {\n            int &cell = grid[i][N - 1];\n            if (cell != -1) {\n                int id = cell;\n                cell = -1;\n                state[id] = DISPATCHED;\n                posx[id] = -1;\n                posy[id] = -1;\n                ++dispatched_count;\n                int r = id / N;\n                if (nextRowId[r] == id) {\n                    ++nextRowId[r];\n                }\n            }\n        }\n    }\n\n    // Output operation strings.\n    for (int i = 0; i < N; ++i) {\n        cout << ops[i] << '\\n';\n    }\n\n    return 0;\n}","ahc034":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int MAXN = 20;\nconst int TOT_LIMIT = 100000;\n// Leave room for fallback (~<2000 ops)\nconst int LIMIT_GREEDY = TOT_LIMIT - 2000;\n\nint N;\nlong long h[MAXN][MAXN];         // mutable heights for execution\nlong long orig_h[MAXN][MAXN];    // original heights\n\nlong long negPotential[MAXN][MAXN]; // static negative potential (from orig_h)\nlong long posPotential[MAXN][MAXN]; // static positive potential (from orig_h)\n\nvector<string> ops;\n\nint cur_r = 0, cur_c = 0;  // current truck position\nlong long load_truck = 0;  // current truck load\nlong long base_total = 0;  // sum of |h[i][j]|, used in greedy\n\nvector<pair<int,int>> snakePath;\n\n// ----------------------------------------------------------------------\n// Modes for positive selection:\n// metric = wD[mode]*dist - wStatic[mode]*staticNP - wDyn[mode]*dynNP\n// ----------------------------------------------------------------------\nconst int MODES = 8;\nint wD[MODES]       = {200, 200, 200, 200, 200, 200, 200, 200};\nint wStaticF[MODES] = {  0,   1,   0,   1,   2,   0,   1,   2};\nint wDynF[MODES]    = {  0,   0,   1,   1,   0,   2,   2,   1};\n\n// ----------------------------------------------------------------------\n// Build snake Hamiltonian path for fallback (row-wise snake)\n// ----------------------------------------------------------------------\nvoid buildSnakePath() {\n    snakePath.clear();\n    snakePath.reserve(MAXN * MAXN);\n    for (int i = 0; i < N; ++i) {\n        if (i % 2 == 0) {\n            for (int j = 0; j < N; ++j) {\n                snakePath.emplace_back(i, j);\n            }\n        } else {\n            for (int j = N - 1; j >= 0; --j) {\n                snakePath.emplace_back(i, j);\n            }\n        }\n    }\n}\n\n// ----------------------------------------------------------------------\n// Precompute static negative and positive potentials from original heights.\n// For each cell (i,j), sum of nearby negative/positive amounts within radius R.\n// ----------------------------------------------------------------------\nvoid precomputePotentials() {\n    const int R = 6; // radius for local potential\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            long long negSum = 0;\n            long long posSum = 0;\n            for (int di = -R; di <= R; ++di) {\n                int ni = i + di;\n                if (ni < 0 || ni >= N) continue;\n                int rem = R - abs(di);\n                int cj1 = max(0, j - rem);\n                int cj2 = min(N - 1, j + rem);\n                for (int nj = cj1; nj <= cj2; ++nj) {\n                    long long v = orig_h[ni][nj];\n                    if (v < 0) negSum += -v;\n                    else       posSum += v;\n                }\n            }\n            negPotential[i][j] = negSum;\n            posPotential[i][j] = posSum;\n        }\n    }\n}\n\n// ----------------------------------------------------------------------\n// Dynamic local negative potential around (i,j) based on given grid.\n// Sum of -grid[ni][nj] for negative cells within radius Rdyn (diamond).\n// Used in modes with wDyn>0.\n// ----------------------------------------------------------------------\nlong long localNegPotentialCurrent(int i, int j, long long grid[MAXN][MAXN]) {\n    const int Rdyn = 5;\n    long long sum = 0;\n    for (int di = -Rdyn; di <= Rdyn; ++di) {\n        int ni = i + di;\n        if (ni < 0 || ni >= N) continue;\n        int rem = Rdyn - abs(di);\n        int cj1 = max(0, j - rem);\n        int cj2 = min(N - 1, j + rem);\n        for (int nj = cj1; nj <= cj2; ++nj) {\n            long long v = grid[ni][nj];\n            if (v < 0) sum += -v;\n        }\n    }\n    return sum;\n}\n\n// ----------------------------------------------------------------------\n// Basic movement for execution: move step-by-step (no opportunistic load/unload)\n// Used in fallback and when truck is empty in greedy.\n// ----------------------------------------------------------------------\nvoid move_to_basic_exec(int tr, int tc) {\n    while (cur_r < tr) {\n        ++cur_r;\n        ops.emplace_back(\"D\");\n    }\n    while (cur_r > tr) {\n        --cur_r;\n        ops.emplace_back(\"U\");\n    }\n    while (cur_c < tc) {\n        ++cur_c;\n        ops.emplace_back(\"R\");\n    }\n    while (cur_c > tc) {\n        --cur_c;\n        ops.emplace_back(\"L\");\n    }\n}\n\n// ----------------------------------------------------------------------\n// Movement when loaded in greedy phase (execution):\n// choose between two Manhattan paths based on how much negative capacity\n// they pass, then traverse that path and opportunistically unload and\n// (near the target) opportunistically load from positives.\n// ----------------------------------------------------------------------\nvoid move_to_loaded_exec(int tr, int tc) {\n    const int LOAD_RADIUS = 4; // only load positives that are close to target\n\n    int r0 = cur_r, c0 = cur_c;\n    int dr = tr - r0;\n    int dc = tc - c0;\n\n    vector<char> path1, path2;\n    path1.reserve(abs(dr) + abs(dc));\n    path2.reserve(abs(dr) + abs(dc));\n\n    // Path1: vertical first, then horizontal\n    if (dr > 0) for (int k = 0; k < dr; ++k) path1.push_back('D');\n    else       for (int k = 0; k < -dr; ++k) path1.push_back('U');\n    if (dc > 0) for (int k = 0; k < dc; ++k) path1.push_back('R');\n    else        for (int k = 0; k < -dc; ++k) path1.push_back('L');\n\n    // Path2: horizontal first, then vertical\n    if (dc > 0) for (int k = 0; k < dc; ++k) path2.push_back('R');\n    else        for (int k = 0; k < -dc; ++k) path2.push_back('L');\n    if (dr > 0) for (int k = 0; k < dr; ++k) path2.push_back('D');\n    else       for (int k = 0; k < -dr; ++k) path2.push_back('U');\n\n    auto eval_path = [&](const vector<char>& path) -> long long {\n        int r = r0, c = c0;\n        long long rem = load_truck;\n        long long sum_unload = 0;\n        for (char ch : path) {\n            if (ch == 'D') ++r;\n            else if (ch == 'U') --r;\n            else if (ch == 'R') ++c;\n            else --c;\n            if (rem <= 0) continue;\n            long long v = h[r][c];\n            if (v < 0) {\n                long long need = -v;\n                long long d = min(rem, need);\n                sum_unload += d;\n                rem -= d;\n                if (rem == 0) break;\n            }\n        }\n        return sum_unload;\n    };\n\n    long long s1 = eval_path(path1);\n    long long s2 = eval_path(path2);\n    const vector<char>& best = (s2 > s1 ? path2 : path1);\n\n    for (char ch : best) {\n        if (ch == 'D') { ++cur_r; ops.emplace_back(\"D\"); }\n        else if (ch == 'U') { --cur_r; ops.emplace_back(\"U\"); }\n        else if (ch == 'R') { ++cur_c; ops.emplace_back(\"R\"); }\n        else { --cur_c; ops.emplace_back(\"L\"); }\n\n        // Opportunistic unload to negatives\n        if (load_truck > 0) {\n            long long v = h[cur_r][cur_c];\n            if (v < 0) {\n                long long need = -v;\n                long long d = min(load_truck, need);\n                if (d > 0) {\n                    ops.emplace_back(\"-\" + to_string(d));\n                    load_truck -= d;\n                    h[cur_r][cur_c] += d;\n                    base_total -= d;\n                }\n            }\n        }\n\n        // Opportunistic load from positives near the target\n        long long v2 = h[cur_r][cur_c];\n        if (v2 > 0) {\n            int d_to_t = abs(cur_r - tr) + abs(cur_c - tc);\n            if (d_to_t <= LOAD_RADIUS) {\n                long long d = v2;\n                ops.emplace_back(\"+\" + to_string(d));\n                load_truck += d;\n                h[cur_r][cur_c] = 0;\n                base_total -= d;\n            }\n        }\n    }\n}\n\n// ----------------------------------------------------------------------\n// Positive selection (execution) for a given mode.\n// metric = wD[mode]*dist - wStatic[mode]*staticNP - wDyn[mode]*dynNP\n// ----------------------------------------------------------------------\npair<int,int> findPositive_exec(int mode) {\n    int bestR = -1, bestC = -1;\n    long long bestMetric = (1LL << 60);\n    int bestd = INT_MAX;\n    long long bestVal = -1;\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            long long v = h[i][j];\n            if (v <= 0) continue;\n            int d = abs(i - cur_r) + abs(j - cur_c);\n            long long staticNP = negPotential[i][j];\n            long long dynNP = 0;\n            if (wDynF[mode] != 0) {\n                dynNP = localNegPotentialCurrent(i, j, h);\n            }\n            long long metric = 1LL * wD[mode] * d\n                             - 1LL * wStaticF[mode] * staticNP\n                             - 1LL * wDynF[mode] * dynNP;\n\n            if (metric < bestMetric ||\n                (metric == bestMetric &&\n                 (d < bestd || (d == bestd && v > bestVal)))) {\n                bestMetric = metric;\n                bestd = d;\n                bestVal = v;\n                bestR = i;\n                bestC = j;\n            }\n        }\n    }\n    return {bestR, bestC};\n}\n\n// ----------------------------------------------------------------------\n// Nearest negative selection (execution): primarily minimize distance,\n// then prefer larger |h| and larger nearby positive potential.\n// ----------------------------------------------------------------------\npair<int,int> findNearestNegative_exec() {\n    int bestR = -1, bestC = -1;\n    int bestd = INT_MAX;\n    long long bestScore = -1; // combines |h| and posPotential\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            long long v = h[i][j];\n            if (v >= 0) continue;\n            int d = abs(i - cur_r) + abs(j - cur_c);\n            long long absV = -v;\n            long long score = absV * 1000 + posPotential[i][j];\n            if (d < bestd || (d == bestd && score > bestScore)) {\n                bestd = d;\n                bestScore = score;\n                bestR = i;\n                bestC = j;\n            }\n        }\n    }\n    return {bestR, bestC};\n}\n\n// ----------------------------------------------------------------------\n// Stage 1 (execution): Greedy shipping with chosen mode.\n// ----------------------------------------------------------------------\nvoid greedy_phase_exec(int mode) {\n    base_total = 0;\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            base_total += llabs(h[i][j]);\n\n    while (base_total > 0 && (int)ops.size() < LIMIT_GREEDY) {\n        if (load_truck == 0) {\n            auto [pr, pc] = findPositive_exec(mode);\n            if (pr == -1) break; // should not happen\n            move_to_basic_exec(pr, pc);\n\n            long long v = h[pr][pc];\n            if (v > 0) {\n                long long d = v;\n                ops.emplace_back(\"+\" + to_string(d));\n                load_truck += d;\n                h[pr][pc] = 0;\n                base_total -= d;\n            }\n        } else {\n            auto [nr, nc] = findNearestNegative_exec();\n            if (nr == -1) break; // should not happen\n            move_to_loaded_exec(nr, nc);\n\n            long long v = h[nr][nc];\n            if (v < 0 && load_truck > 0) {\n                long long need = -v;\n                long long d = min(load_truck, need);\n                if (d > 0) {\n                    ops.emplace_back(\"-\" + to_string(d));\n                    load_truck -= d;\n                    h[nr][nc] += d;\n                    base_total -= d;\n                }\n            }\n        }\n    }\n}\n\n// ----------------------------------------------------------------------\n// Simulation helpers: same logic as execution, but on local state, and\n// accumulating cost and operation count, for mode selection.\n// ----------------------------------------------------------------------\nvoid move_to_basic_sim(int &r, int &c, long long &load,\n                       long long hh[MAXN][MAXN],\n                       long long &cost, int &ops_cnt,\n                       int tr, int tc) {\n    while (r < tr) {\n        cost += 100 + load;\n        ++ops_cnt;\n        ++r;\n    }\n    while (r > tr) {\n        cost += 100 + load;\n        ++ops_cnt;\n        --r;\n    }\n    while (c < tc) {\n        cost += 100 + load;\n        ++ops_cnt;\n        ++c;\n    }\n    while (c > tc) {\n        cost += 100 + load;\n        ++ops_cnt;\n        --c;\n    }\n}\n\nvoid move_to_loaded_sim(int &r, int &c, long long &load,\n                        long long hh[MAXN][MAXN],\n                        long long &base_sim,\n                        long long &cost, int &ops_cnt,\n                        int tr, int tc) {\n    const int LOAD_RADIUS = 4;\n\n    int r0 = r, c0 = c;\n    int dr = tr - r0;\n    int dc = tc - c0;\n\n    vector<char> path1, path2;\n    path1.reserve(abs(dr) + abs(dc));\n    path2.reserve(abs(dr) + abs(dc));\n\n    // Path1: vertical first, then horizontal\n    if (dr > 0) for (int k = 0; k < dr; ++k) path1.push_back('D');\n    else       for (int k = 0; k < -dr; ++k) path1.push_back('U');\n    if (dc > 0) for (int k = 0; k < dc; ++k) path1.push_back('R');\n    else        for (int k = 0; k < -dc; ++k) path1.push_back('L');\n\n    // Path2: horizontal first, then vertical\n    if (dc > 0) for (int k = 0; k < dc; ++k) path2.push_back('R');\n    else        for (int k = 0; k < -dc; ++k) path2.push_back('L');\n    if (dr > 0) for (int k = 0; k < dr; ++k) path2.push_back('D');\n    else       for (int k = 0; k < -dr; ++k) path2.push_back('U');\n\n    auto eval_path = [&](const vector<char>& path) -> long long {\n        int rr = r0, cc = c0;\n        long long rem = load;\n        long long sum_unload = 0;\n        for (char ch : path) {\n            if (ch == 'D') ++rr;\n            else if (ch == 'U') --rr;\n            else if (ch == 'R') ++cc;\n            else --cc;\n            if (rem <= 0) continue;\n            long long v = hh[rr][cc];\n            if (v < 0) {\n                long long need = -v;\n                long long d = min(rem, need);\n                sum_unload += d;\n                rem -= d;\n                if (rem == 0) break;\n            }\n        }\n        return sum_unload;\n    };\n\n    long long s1 = eval_path(path1);\n    long long s2 = eval_path(path2);\n    const vector<char>& best = (s2 > s1 ? path2 : path1);\n\n    for (char ch : best) {\n        // move cost\n        cost += 100 + load;\n        ++ops_cnt;\n        if (ch == 'D') ++r;\n        else if (ch == 'U') --r;\n        else if (ch == 'R') ++c;\n        else --c;\n\n        // opportunistic unload\n        if (load > 0) {\n            long long v = hh[r][c];\n            if (v < 0) {\n                long long need = -v;\n                long long d = min(load, need);\n                if (d > 0) {\n                    cost += d;   // unload cost\n                    ++ops_cnt;   // unload op\n                    load -= d;\n                    hh[r][c] += d;\n                    base_sim -= d;\n                }\n            }\n        }\n\n        // opportunistic load near the target\n        long long v2 = hh[r][c];\n        if (v2 > 0) {\n            int d_to_t = abs(r - tr) + abs(c - tc);\n            if (d_to_t <= LOAD_RADIUS) {\n                long long d = v2;\n                cost += d;   // load cost\n                ++ops_cnt;   // load op\n                load += d;\n                hh[r][c] = 0;\n                base_sim -= d;\n            }\n        }\n    }\n}\n\npair<int,int> findPositive_sim(int mode,\n                               long long hh[MAXN][MAXN],\n                               int r, int c) {\n    int bestR = -1, bestC = -1;\n    long long bestMetric = (1LL << 60);\n    int bestd = INT_MAX;\n    long long bestVal = -1;\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            long long v = hh[i][j];\n            if (v <= 0) continue;\n            int d = abs(i - r) + abs(j - c);\n            long long staticNP = negPotential[i][j];\n            long long dynNP = 0;\n            if (wDynF[mode] != 0) {\n                dynNP = localNegPotentialCurrent(i, j, hh);\n            }\n            long long metric = 1LL * wD[mode] * d\n                             - 1LL * wStaticF[mode] * staticNP\n                             - 1LL * wDynF[mode] * dynNP;\n\n            if (metric < bestMetric ||\n                (metric == bestMetric &&\n                 (d < bestd || (d == bestd && v > bestVal)))) {\n                bestMetric = metric;\n                bestd = d;\n                bestVal = v;\n                bestR = i;\n                bestC = j;\n            }\n        }\n    }\n    return {bestR, bestC};\n}\n\npair<int,int> findNearestNegative_sim(long long hh[MAXN][MAXN],\n                                      int r, int c) {\n    int bestR = -1, bestC = -1;\n    int bestd = INT_MAX;\n    long long bestScore = -1;\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            long long v = hh[i][j];\n            if (v >= 0) continue;\n            int d = abs(i - r) + abs(j - c);\n            long long absV = -v;\n            long long score = absV * 1000 + posPotential[i][j];\n            if (d < bestd || (d == bestd && score > bestScore)) {\n                bestd = d;\n                bestScore = score;\n                bestR = i;\n                bestC = j;\n            }\n        }\n    }\n    return {bestR, bestC};\n}\n\n// ----------------------------------------------------------------------\n// Simulate greedy stage for given mode, return approximate cost.\n// If it cannot finish within LIMIT_GREEDY ops, returns a huge penalty.\n// ----------------------------------------------------------------------\nlong long simulate_mode(int mode) {\n    static long long hh[MAXN][MAXN];\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            hh[i][j] = orig_h[i][j];\n\n    long long base_sim = 0;\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            base_sim += llabs(hh[i][j]);\n\n    int r = 0, c = 0;\n    long long load = 0;\n    long long cost = 0;\n    int ops_cnt = 0;\n\n    while (base_sim > 0 && ops_cnt < LIMIT_GREEDY) {\n        if (load == 0) {\n            auto [pr, pc] = findPositive_sim(mode, hh, r, c);\n            if (pr == -1) break; // should not happen\n            move_to_basic_sim(r, c, load, hh, cost, ops_cnt, pr, pc);\n\n            long long v = hh[pr][pc];\n            if (v > 0) {\n                long long d = v;\n                cost += d;   // load cost\n                ++ops_cnt;   // one operation\n                load += d;\n                hh[pr][pc] = 0;\n                base_sim -= d;\n            }\n        } else {\n            auto [nr, nc] = findNearestNegative_sim(hh, r, c);\n            if (nr == -1) break; // no negative but load>0 => inconsistent\n            move_to_loaded_sim(r, c, load, hh, base_sim, cost, ops_cnt, nr, nc);\n\n            long long v = hh[nr][nc];\n            if (v < 0 && load > 0) {\n                long long need = -v;\n                long long d = min(load, need);\n                if (d > 0) {\n                    cost += d;   // unload cost\n                    ++ops_cnt;   // one operation\n                    load -= d;\n                    hh[nr][nc] += d;\n                    base_sim -= d;\n                }\n            }\n        }\n    }\n\n    if (base_sim > 0 || ops_cnt >= LIMIT_GREEDY) {\n        return (long long)4e18; // penalty\n    }\n    return cost;\n}\n\n// ----------------------------------------------------------------------\n// Stage 2: fallback using two-pass snake sweep to guarantee completion\n// ----------------------------------------------------------------------\nvoid fallback_snake() {\n    // Unload any remaining load at current cell\n    if (load_truck > 0) {\n        ops.emplace_back(\"-\" + to_string(load_truck));\n        h[cur_r][cur_c] += load_truck;\n        load_truck = 0;\n    }\n\n    // Move to (0,0), the start of snakePath\n    move_to_basic_exec(0, 0);\n\n    int M = (int)snakePath.size();\n\n    // Forward pass\n    for (int idx = 0; idx < M; ++idx) {\n        int r = snakePath[idx].first;\n        int c = snakePath[idx].second;\n        move_to_basic_exec(r, c);\n\n        long long v = h[r][c];\n        if (v > 0) {\n            long long d = v;\n            ops.emplace_back(\"+\" + to_string(d));\n            load_truck += d;\n            h[r][c] = 0;\n        } else if (v < 0 && load_truck > 0) {\n            long long need = -v;\n            long long d = min(load_truck, need);\n            ops.emplace_back(\"-\" + to_string(d));\n            load_truck -= d;\n            h[r][c] += d;\n        }\n    }\n\n    // Backward pass\n    for (int idx = M - 1; idx >= 0; --idx) {\n        int r = snakePath[idx].first;\n        int c = snakePath[idx].second;\n        move_to_basic_exec(r, c);\n\n        long long v = h[r][c];\n        if (v < 0 && load_truck > 0) {\n            long long need = -v;\n            long long d = min(load_truck, need);\n            ops.emplace_back(\"-\" + to_string(d));\n            load_truck -= d;\n            h[r][c] += d;\n        }\n    }\n    // After this, by conservation, all heights should be zero and load_truck == 0.\n}\n\n// ----------------------------------------------------------------------\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    if (!(cin >> N)) return 0;\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j) {\n            cin >> orig_h[i][j];\n            h[i][j] = orig_h[i][j];\n        }\n\n    precomputePotentials();\n    buildSnakePath();\n\n    // Decide best mode by simulation among candidates\n    long long bestCost = (long long)4e18;\n    int bestMode = 0;\n    for (int mode = 0; mode < MODES; ++mode) {\n        long long c = simulate_mode(mode);\n        if (c < bestCost) {\n            bestCost = c;\n            bestMode = mode;\n        }\n    }\n\n    // Reset runtime state and run greedy with chosen mode\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            h[i][j] = orig_h[i][j];\n\n    cur_r = 0;\n    cur_c = 0;\n    load_truck = 0;\n    ops.clear();\n\n    greedy_phase_exec(bestMode);\n\n    // Check if everything is leveled\n    bool all_zero = true;\n    for (int i = 0; i < N && all_zero; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (h[i][j] != 0) {\n                all_zero = false;\n                break;\n            }\n        }\n    }\n\n    // If greedy didn't finish, use fallback snake\n    if (!all_zero && (int)ops.size() < TOT_LIMIT) {\n        fallback_snake();\n    }\n\n    // Absolute safety: never output more than 100000 operations\n    if ((int)ops.size() > TOT_LIMIT) {\n        ops.resize(TOT_LIMIT);\n    }\n\n    for (const string &s : ops) {\n        cout << s << '\\n';\n    }\n    return 0;\n}","ahc035":"#include <bits/stdc++.h>\nusing namespace std;\n\n/*\n Heuristic strategy with dimension-weighted synergy and selection\n + exponential cooling simulated annealing.\n\n This is essentially the best-performing variant from the previous\n iterations (score ~4.16e7), with a minor tweak:\n   - Increase SA iterations from 300,000 to 400,000 to allow\n     slightly deeper search while remaining well within time limits.\n\n Overview per turn:\n   1) Compute current per-dim maxima Y_l over this generation.\n      Dimension weights:\n         w_l = 1 + ALPHA * (1 - Y_l / X_l)\n      (if X_l == 0, w_l = 1). Under-saturated dimensions get higher weight.\n   2) Using w_l, define for each seed k a weighted normalized value:\n         normV[k] = sum_l w_l * x[k,l] / X_l\n   3) Compute pairwise \"synergy\" for all seeds:\n         S(a,b) = sum_l w_l * max(x_a_l, x_b_l) / X_l.\n   4) Select 36 seeds:\n        - Dimension champions (best for each dimension by x[k,l], tie-broken by normV).\n        - Then greedily add seeds using:\n             score(k) = normV[k] + \u03bb * avg_synergy_to_selected(k).\n   5) Among the 36 selected seeds, compute \"centrality\":\n        cent(s) = avg synergy to other selected seeds.\n      Order seeds by:\n        normV[s] + \u03b3 * cent(s) + champion_bonus (if champion).\n   6) Greedy initial placement:\n        - Positions sorted by degree (center > edge > corner).\n        - Place seeds in that order into positions to maximize incremental synergy.\n   7) Simulated annealing on the placement:\n        - Objective = sum_edge synergy(arr[u], arr[v]) (synergy-only).\n        - Random swaps with Metropolis acceptance.\n        - 400,000 iterations per turn, exponential cooling:\n             T = T0 * (T1/T0)^(iter / ITER).\n        - Track best arrangement encountered.\n   8) Output arrangement, then read next generation seeds.\n*/\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, T;\n    if (!(cin >> N >> M >> T)) return 0;\n\n    const int SEED_COUNT = 2 * N * (N - 1); // 60 for N=6\n    const int SZ = N * N;                   // 36 for N=6\n    const int MAXS = 60;                    // max seed count\n\n    // Current seeds: x[k][l]\n    vector<vector<int>> x(SEED_COUNT, vector<int>(M));\n    for (int i = 0; i < SEED_COUNT; i++) {\n        for (int l = 0; l < M; l++) cin >> x[i][l];\n    }\n\n    // Global per-dimension maxima from initial seeds\n    vector<int> X_global(M, 0);\n    for (int l = 0; l < M; l++) {\n        int mx = 0;\n        for (int i = 0; i < SEED_COUNT; i++) {\n            mx = max(mx, x[i][l]);\n        }\n        X_global[l] = mx;\n    }\n\n    // Active dimensions (avoid division by zero)\n    vector<int> active_dims;\n    active_dims.reserve(M);\n    for (int l = 0; l < M; l++) {\n        if (X_global[l] > 0) active_dims.push_back(l);\n    }\n\n    // Grid adjacency and edges\n    vector<vector<int>> neighbors(SZ);\n    vector<pair<int,int>> edges;\n    edges.reserve(2 * N * (N - 1));\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            int pos = i * N + j;\n            if (j + 1 < N) {\n                int q = pos + 1;\n                edges.emplace_back(pos, q);\n                neighbors[pos].push_back(q);\n                neighbors[q].push_back(pos);\n            }\n            if (i + 1 < N) {\n                int q = pos + N;\n                edges.emplace_back(pos, q);\n                neighbors[pos].push_back(q);\n                neighbors[q].push_back(pos);\n            }\n        }\n    }\n\n    // Positions sorted by degree (center > edge > corner)\n    vector<int> pos_by_deg(SZ);\n    iota(pos_by_deg.begin(), pos_by_deg.end(), 0);\n    sort(pos_by_deg.begin(), pos_by_deg.end(), [&](int a, int b) {\n        if (neighbors[a].size() != neighbors[b].size())\n            return neighbors[a].size() > neighbors[b].size();\n        return a < b;\n    });\n\n    // RNG (xorshift, deterministic)\n    uint64_t rng_state = 88172645463325252ull;\n    auto rng = [&]() -> uint64_t {\n        rng_state ^= (rng_state << 7);\n        rng_state ^= (rng_state >> 9);\n        return rng_state;\n    };\n    auto rand01 = [&]() -> double {\n        // 53-bit precision uniform in [0,1)\n        return (rng() >> 11) * (1.0 / (1ULL << 53));\n    };\n\n    // Per-turn data\n    vector<double> normV(SEED_COUNT);   // weighted normalized value\n    static double synergy[MAXS][MAXS];  // pairwise synergy\n    vector<double> dim_weight(M, 1.0);  // per-dimension weights\n\n    const double ALPHA  = 0.7;   // dimension-under-saturation weight\n    const double LAMBDA = 0.35;  // weight for synergy in selection\n    const double GAMMA  = 0.45;  // weight for centrality in ordering\n    const double CH_BONUS = 0.25;// bonus in ordering for dimension champions\n\n    const int ITER = 400000;     // SA iterations per turn (increased from 300k)\n    const double T0 = 0.8;\n    const double T1 = 0.01;\n    const double alpha_T = pow(T1 / T0, 1.0 / ITER);\n\n    for (int turn = 0; turn < T; turn++) {\n        // 1) Current per-dim maxima Y_l\n        vector<int> Y(M, 0);\n        for (int l = 0; l < M; l++) {\n            int mx = 0;\n            for (int k = 0; k < SEED_COUNT; k++) {\n                mx = max(mx, x[k][l]);\n            }\n            Y[l] = mx;\n        }\n\n        // 2) Dimension weights and weighted normalized values\n        for (int l = 0; l < M; l++) {\n            if (X_global[l] <= 0) {\n                dim_weight[l] = 1.0;\n            } else {\n                double ratio = (double)Y[l] / (double)X_global[l]; // 0..1\n                dim_weight[l] = 1.0 + ALPHA * (1.0 - ratio);\n            }\n        }\n\n        for (int k = 0; k < SEED_COUNT; k++) {\n            double s = 0.0;\n            for (int idx = 0; idx < (int)active_dims.size(); idx++) {\n                int l = active_dims[idx];\n                s += dim_weight[l] * (double)x[k][l] / (double)X_global[l];\n            }\n            normV[k] = s;\n        }\n\n        // 3) Synergy matrix using dim_weight\n        for (int i = 0; i < SEED_COUNT; i++) {\n            synergy[i][i] = 0.0;\n            for (int j = i + 1; j < SEED_COUNT; j++) {\n                double s = 0.0;\n                for (int idx = 0; idx < (int)active_dims.size(); idx++) {\n                    int l = active_dims[idx];\n                    double w = dim_weight[l];\n                    s += w * (double)max(x[i][l], x[j][l]) / (double)X_global[l];\n                }\n                synergy[i][j] = synergy[j][i] = s;\n            }\n        }\n\n        // 4) Select 36 seeds: dimension champions + synergy-guided greedy fill\n        vector<int> selected;\n        selected.reserve(SZ);\n        vector<char> used(SEED_COUNT, 0);\n        vector<char> isChampion(SEED_COUNT, 0);\n\n        // 4-1) Dimension champions\n        for (int idx = 0; idx < (int)active_dims.size(); idx++) {\n            int l = active_dims[idx];\n            int best = -1;\n            int bestVal = -1;\n            double bestNorm = -1.0;\n            for (int k = 0; k < SEED_COUNT; k++) {\n                int v = x[k][l];\n                if (v > bestVal || (v == bestVal && normV[k] > bestNorm)) {\n                    bestVal = v;\n                    bestNorm = normV[k];\n                    best = k;\n                }\n            }\n            if (best != -1 && !used[best]) {\n                used[best] = 1;\n                isChampion[best] = 1;\n                selected.push_back(best);\n                if ((int)selected.size() == SZ) break;\n            }\n        }\n\n        // 4-2) Greedy fill with synergy-based score\n        while ((int)selected.size() < SZ) {\n            int bestK = -1;\n            double bestScore = -1e100;\n\n            for (int k = 0; k < SEED_COUNT; k++) {\n                if (used[k]) continue;\n                double avgSyn = 0.0;\n                if (!selected.empty()) {\n                    double sumSyn = 0.0;\n                    for (int s : selected) sumSyn += synergy[k][s];\n                    avgSyn = sumSyn / (double)selected.size();\n                }\n                double score = normV[k] + LAMBDA * avgSyn;\n                if (score > bestScore) {\n                    bestScore = score;\n                    bestK = k;\n                }\n            }\n            if (bestK == -1) {\n                // Fallback: pick any unused seed\n                for (int k = 0; k < SEED_COUNT; k++) {\n                    if (!used[k]) {\n                        bestK = k;\n                        break;\n                    }\n                }\n                if (bestK == -1) break;\n            }\n            used[bestK] = 1;\n            selected.push_back(bestK);\n        }\n\n        // 5) Centrality for selected seeds\n        vector<double> cent(SZ);\n        for (int i = 0; i < SZ; i++) {\n            double s = 0.0;\n            for (int j = 0; j < SZ; j++) {\n                if (i == j) continue;\n                s += synergy[selected[i]][selected[j]];\n            }\n            cent[i] = s / max(1, SZ - 1);\n        }\n\n        // 6) Ordering of selected seeds for placement\n        vector<int> seed_order(SZ);\n        iota(seed_order.begin(), seed_order.end(), 0);\n        sort(seed_order.begin(), seed_order.end(), [&](int a, int b) {\n            double sa = normV[selected[a]] + GAMMA * cent[a]\n                        + (isChampion[selected[a]] ? CH_BONUS : 0.0);\n            double sb = normV[selected[b]] + GAMMA * cent[b]\n                        + (isChampion[selected[b]] ? CH_BONUS : 0.0);\n            if (sa != sb) return sa > sb;\n            return selected[a] < selected[b];\n        });\n\n        // 7) Greedy initial placement by synergy\n        vector<int> pos_to_seed(SZ, -1);\n        for (int idx = 0; idx < SZ; idx++) {\n            int seed_id = selected[seed_order[idx]];\n            int bestPos = -1;\n            double bestInc = -1e100;\n\n            for (int pos : pos_by_deg) {\n                if (pos_to_seed[pos] != -1) continue;\n                double inc = 0.0;\n                for (int nb : neighbors[pos]) {\n                    if (pos_to_seed[nb] != -1) {\n                        int nbSeed = pos_to_seed[nb];\n                        inc += synergy[seed_id][nbSeed];\n                    }\n                }\n                if (inc > bestInc + 1e-9 ||\n                    (fabs(inc - bestInc) <= 1e-9 &&\n                     neighbors[pos].size() >\n                        (bestPos == -1 ? -1 : (int)neighbors[bestPos].size()))) {\n                    bestInc = inc;\n                    bestPos = pos;\n                }\n            }\n            if (bestPos == -1) bestPos = pos_by_deg[0];\n            pos_to_seed[bestPos] = seed_id;\n        }\n\n        // Current arrangement\n        vector<int> arr = pos_to_seed;\n\n        // Initial synergy score\n        double cur_score = 0.0;\n        for (auto &e : edges) {\n            cur_score += synergy[arr[e.first]][arr[e.second]];\n        }\n\n        // SA: keep best\n        vector<int> best_arr = arr;\n        double best_score = cur_score;\n\n        double Tcur = T0;\n        for (int it = 0; it < ITER; it++) {\n            int p1 = (int)(rng() % SZ);\n            int p2 = (int)(rng() % SZ);\n            if (p1 == p2) {\n                Tcur *= alpha_T;\n                continue;\n            }\n\n            int s1 = arr[p1];\n            int s2 = arr[p2];\n            if (s1 == s2) {\n                Tcur *= alpha_T;\n                continue;\n            }\n\n            double delta = 0.0;\n\n            // Edges incident to p1 (excluding p2)\n            for (int nb : neighbors[p1]) {\n                if (nb == p2) continue;\n                int s_nb = arr[nb];\n                delta -= synergy[s1][s_nb];\n                delta += synergy[s2][s_nb];\n            }\n            // Edges incident to p2 (excluding p1)\n            for (int nb : neighbors[p2]) {\n                if (nb == p1) continue;\n                int s_nb = arr[nb];\n                delta -= synergy[s2][s_nb];\n                delta += synergy[s1][s_nb];\n            }\n\n            bool accept = false;\n            if (delta >= 0.0) {\n                accept = true;\n            } else {\n                double prob = exp(delta / Tcur);\n                if (rand01() < prob) accept = true;\n            }\n\n            if (accept) {\n                cur_score += delta;\n                swap(arr[p1], arr[p2]);\n                if (cur_score > best_score) {\n                    best_score = cur_score;\n                    best_arr = arr;\n                }\n            }\n\n            Tcur *= alpha_T;\n        }\n\n        // Use best arrangement found\n        arr = best_arr;\n\n        // 8) Output arrangement\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                if (j) cout << ' ';\n                cout << arr[i * N + j];\n            }\n            cout << '\\n';\n        }\n        cout.flush();\n\n        // 9) Read next generation seeds\n        if (turn + 1 < T) {\n            for (int i = 0; i < SEED_COUNT; i++) {\n                for (int l = 0; l < M; l++) {\n                    cin >> x[i][l];\n                }\n            }\n        } else {\n            // Final seeds may be provided; read and ignore\n            for (int i = 0; i < SEED_COUNT; i++) {\n                for (int l = 0; l < M; l++) {\n                    int tmp;\n                    if (!(cin >> tmp)) break;\n                }\n            }\n        }\n    }\n\n    return 0;\n}","ahc038":"#include <bits/stdc++.h>\nusing namespace std;\n\n// Directions: 0=Right, 1=Down, 2=Left, 3=Up\nconst int DX[4] = {0, 1, 0, -1};\nconst int DY[4] = {1, 0, -1, 0};\n\n// Hungarian algorithm for square cost matrix (minimization).\n// Returns assignment: match[i] = j (0-based), minimizing sum cost[i][match[i]].\nvector<int> hungarian(const vector<vector<int>>& a) {\n    int n = (int)a.size();\n    const int INF = 1e9;\n    vector<int> u(n + 1), v(n + 1), p(n + 1), way(n + 1);\n\n    for (int i = 1; i <= n; i++) {\n        p[0] = i;\n        int j0 = 0;\n        vector<int> minv(n + 1, INF);\n        vector<char> used(n + 1, false);\n        do {\n            used[j0] = true;\n            int i0 = p[j0];\n            int delta = INF, j1 = 0;\n            for (int j = 1; j <= n; j++) if (!used[j]) {\n                int cur = a[i0 - 1][j - 1] - u[i0] - v[j];\n                if (cur < minv[j]) {\n                    minv[j] = cur;\n                    way[j]  = j0;\n                }\n                if (minv[j] < delta) {\n                    delta = minv[j];\n                    j1    = j;\n                }\n            }\n            for (int j = 0; j <= n; j++) {\n                if (used[j]) {\n                    u[p[j]] += delta;\n                    v[j]     -= delta;\n                } else {\n                    minv[j]  -= delta;\n                }\n            }\n            j0 = j1;\n        } while (p[j0] != 0);\n        do {\n            int j1 = way[j0];\n            p[j0]  = p[j1];\n            j0     = j1;\n        } while (j0);\n    }\n\n    vector<int> match(n);\n    for (int j = 1; j <= n; j++) {\n        if (p[j] > 0) match[p[j] - 1] = j - 1;\n    }\n    return match;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, V;\n    if (!(cin >> N >> M >> V)) return 0;\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    // Current takoyaki occupancy\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            if (s[i][j] == '1') occ[i][j] = 1;\n        }\n    }\n\n    // Collect mismatched cells\n    vector<pair<int,int>> sources; // s=1, t=0\n    vector<pair<int,int>> targets; // s=0, t=1\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (s[i][j] == '1' && t[i][j] == '0') {\n                sources.emplace_back(i, j);\n            } else if (s[i][j] == '0' && t[i][j] == '1') {\n                targets.emplace_back(i, j);\n            }\n        }\n    }\n    int K = (int)sources.size(); // number of takoyaki to move\n\n    // Arm: 2 vertices: 0=root, 1=fingertip, length 1\n    const int Vp = 2;\n    const int fingerVertex = 1; // fingertip id\n\n    struct PairInfo {\n        int sx, sy;\n        int tx, ty;\n    };\n    vector<PairInfo> pairs;\n\n    // Build pairing (matching between sources and targets)\n    if (K > 0) {\n        vector<int> matchT(K, -1);\n        const int HUNG_LIMIT = 320; // use Hungarian only for K <= 320\n\n        if (K <= HUNG_LIMIT) {\n            // Optimal Hungarian assignment\n            vector<vector<int>> costST(K, vector<int>(K));\n            for (int i = 0; i < K; i++) {\n                for (int j = 0; j < K; j++) {\n                    costST[i][j] = abs(sources[i].first - targets[j].first)\n                                 + abs(sources[i].second - targets[j].second);\n                }\n            }\n            matchT = hungarian(costST);\n        } else {\n            // Greedy global matching + local improvement for larger K\n            vector<vector<int>> dist(K, vector<int>(K));\n            struct Edge { int d, i, j; };\n            vector<Edge> edges;\n            edges.reserve(K * K);\n\n            for (int i = 0; i < K; i++) {\n                for (int j = 0; j < K; j++) {\n                    int d = abs(sources[i].first - targets[j].first)\n                          + abs(sources[i].second - targets[j].second);\n                    dist[i][j] = d;\n                    edges.push_back({d, i, j});\n                }\n            }\n\n            sort(edges.begin(), edges.end(), [](const Edge &a, const Edge &b) {\n                return a.d < b.d;\n            });\n\n            vector<char> usedS(K, 0), usedT(K, 0);\n            int matched = 0;\n            for (const auto &e : edges) {\n                int i = e.i, j = e.j;\n                if (!usedS[i] && !usedT[j]) {\n                    usedS[i] = usedT[j] = 1;\n                    matchT[i] = j;\n                    if (++matched == K) break;\n                }\n            }\n\n            if (K >= 2) {\n                int maxPass = 5; // local-improvement passes for large K\n                for (int pass = 0; pass < maxPass; pass++) {\n                    bool improved = false;\n                    for (int i = 0; i < K; i++) {\n                        int a = matchT[i];\n                        for (int j = i + 1; j < K; j++) {\n                            int b = matchT[j];\n                            int delta = dist[i][b] + dist[j][a]\n                                      - dist[i][a] - dist[j][b];\n                            if (delta < 0) {\n                                swap(matchT[i], matchT[j]);\n                                a = matchT[i];\n                                improved = true;\n                            }\n                        }\n                    }\n                    if (!improved) break;\n                }\n            }\n        }\n\n        // Build pairs from final matching\n        pairs.resize(K);\n        for (int i = 0; i < K; i++) {\n            int j = matchT[i];\n            pairs[i].sx = sources[i].first;\n            pairs[i].sy = sources[i].second;\n            pairs[i].tx = targets[j].first;\n            pairs[i].ty = targets[j].second;\n        }\n    }\n\n    // Build visiting order of pairs: multi-start NN, then cycle 2-opt, then Or-opt on path\n    vector<int> order;\n    vector<vector<int>> transCost; // pair-to-pair target->source distance\n    if (K > 0) {\n        // \"Inside cost\" source->target (independent of order)\n        vector<int> insideCost(K);\n        for (int i = 0; i < K; i++) {\n            insideCost[i] = abs(pairs[i].sx - pairs[i].tx)\n                          + abs(pairs[i].sy - pairs[i].ty);\n        }\n\n        // Candidate starting indices for multi-start NN\n        vector<int> cand;\n        vector<char> inCand(K, 0);\n\n        auto add_cand = [&](int idx) {\n            if (idx >= 0 && idx < K && !inCand[idx]) {\n                inCand[idx] = 1;\n                cand.push_back(idx);\n            }\n        };\n\n        add_cand(0);\n        add_cand(K - 1);\n\n        int idxMinSum = 0, idxMaxSum = 0, idxMinX = 0, idxMaxX = 0;\n        int idxCenter = 0;\n        int gridCX = (N - 1) / 2;\n        int gridCY = (N - 1) / 2;\n        int bestCenterDist = INT_MAX;\n\n        for (int i = 0; i < K; i++) {\n            int sx = pairs[i].sx, sy = pairs[i].sy;\n            int tx = pairs[i].tx, ty = pairs[i].ty;\n            int sum = sx + sy;\n            if (sum < pairs[idxMinSum].sx + pairs[idxMinSum].sy) idxMinSum = i;\n            if (sum > pairs[idxMaxSum].sx + pairs[idxMaxSum].sy) idxMaxSum = i;\n            if (sx < pairs[idxMinX].sx) idxMinX = i;\n            if (sx > pairs[idxMaxX].sx) idxMaxX = i;\n            int cx = (sx + tx) / 2;\n            int cy = (sy + ty) / 2;\n            int cd = abs(cx - gridCX) + abs(cy - gridCY);\n            if (cd < bestCenterDist) {\n                bestCenterDist = cd;\n                idxCenter = i;\n            }\n        }\n\n        add_cand(idxMinSum);\n        add_cand(idxMaxSum);\n        add_cand(idxMinX);\n        add_cand(idxMaxX);\n        add_cand(idxCenter);\n        if (K > 4) add_cand(K / 2);\n\n        // Additional candidates: pairs with largest insideCost\n        vector<int> ids(K);\n        iota(ids.begin(), ids.end(), 0);\n        sort(ids.begin(), ids.end(), [&](int a, int b) {\n            return insideCost[a] > insideCost[b];\n        });\n        int extraTop = min(K, 5);\n        for (int i = 0; i < extraTop; i++) add_cand(ids[i]);\n\n        // Multi-start nearest neighbor paths\n        long long bestCost = (1LL << 60);\n        vector<int> bestOrder;\n\n        for (int st : cand) {\n            vector<char> used(K, 0);\n            vector<int> ord;\n            ord.reserve(K);\n\n            ord.push_back(st);\n            used[st] = 1;\n            int cur = st;\n\n            while ((int)ord.size() < K) {\n                int bestId = -1;\n                int bestD = INT_MAX;\n                for (int i = 0; i < K; i++) if (!used[i]) {\n                    int d = abs(pairs[cur].tx - pairs[i].sx)\n                          + abs(pairs[cur].ty - pairs[i].sy);\n                    if (d < bestD) {\n                        bestD = d;\n                        bestId = i;\n                    }\n                }\n                used[bestId] = 1;\n                ord.push_back(bestId);\n                cur = bestId;\n            }\n\n            long long cost = 0;\n            for (int idx : ord) cost += insideCost[idx];\n            for (int i = 1; i < K; i++) {\n                int a = ord[i - 1], b = ord[i];\n                cost += abs(pairs[a].tx - pairs[b].sx)\n                      + abs(pairs[a].ty - pairs[b].sy);\n            }\n\n            if (cost < bestCost) {\n                bestCost = cost;\n                bestOrder = ord;\n            }\n        }\n\n        order = bestOrder;\n\n        // Precompute pair-to-pair transition costs\n        transCost.assign(K, vector<int>(K));\n        for (int i = 0; i < K; i++) {\n            for (int j = 0; j < K; j++) {\n                transCost[i][j] = abs(pairs[i].tx - pairs[j].sx)\n                                + abs(pairs[i].ty - pairs[j].sy);\n            }\n        }\n\n        // === Cycle 2-opt on order (treat as cycle) ===\n        if (K >= 4) {\n            int maxPass2;\n            if (K <= 120) maxPass2 = 12;\n            else if (K <= 250) maxPass2 = 8;\n            else maxPass2 = 4;\n\n            for (int pass = 0; pass < maxPass2; pass++) {\n                bool improved = false;\n                for (int a = 0; a < K && !improved; a++) {\n                    int A = order[a];\n                    int B = order[(a + 1) % K];\n                    for (int b = a + 2; b < K; b++) {\n                        if (a == 0 && b == K - 1) continue; // avoid full reversal\n                        int C = order[b];\n                        int D = order[(b + 1) % K];\n                        int oldCost = transCost[A][B] + transCost[C][D];\n                        int newCost = transCost[A][C] + transCost[B][D];\n                        if (newCost < oldCost) {\n                            reverse(order.begin() + a + 1, order.begin() + b + 1);\n                            improved = true;\n                            break;\n                        }\n                    }\n                }\n                if (!improved) break;\n            }\n        }\n\n        // Cut the cycle into the best path by removing the largest transition edge\n        if (K > 1) {\n            int bestCut = 0;\n            int bestCutVal = -1;\n            for (int i = 0; i < K; i++) {\n                int a = order[i];\n                int b = order[(i + 1) % K];\n                int val = transCost[a][b];\n                if (val > bestCutVal) {\n                    bestCutVal = val;\n                    bestCut = i;\n                }\n            }\n            vector<int> newOrder;\n            newOrder.reserve(K);\n            for (int i = 0; i < K; i++) {\n                newOrder.push_back(order[(bestCut + 1 + i) % K]);\n            }\n            order.swap(newOrder);\n        }\n\n        // Or-opt refinement (moving a single pair) on the PATH order\n        if (K >= 3) {\n            int maxPassOr;\n            if (K <= 120) maxPassOr = 8;\n            else if (K <= 250) maxPassOr = 5;\n            else maxPassOr = 3;\n\n            for (int pass = 0; pass < maxPassOr; pass++) {\n                bool improved = false;\n                // don't move endpoints (0 and K-1)\n                for (int i = 1; i < K - 1 && !improved; i++) {\n                    int city = order[i];\n                    int prev = order[i - 1];\n                    int next = order[i + 1];\n\n                    for (int j = 1; j < K && !improved; j++) {\n                        if (j == i || j == i + 1) continue;\n                        int before = order[j - 1];\n                        int after  = order[j];\n\n                        int oldCost = transCost[prev][city] + transCost[city][next]\n                                    + transCost[before][after];\n                        int newCost = transCost[prev][next]\n                                    + transCost[before][city] + transCost[city][after];\n                        if (newCost < oldCost) {\n                            order.erase(order.begin() + i);\n                            if (j > i) j--;\n                            order.insert(order.begin() + j, city);\n                            improved = true;\n                        }\n                    }\n                }\n                if (!improved) break;\n            }\n        }\n    }\n\n    // Choose final initial root based on the first pair in the visiting order\n    int initRootX = 0, initRootY = 0;\n    if (K == 0) {\n        initRootX = 0;\n        initRootY = 0;\n    } else {\n        int firstIdx = order[0];\n        auto &P0 = pairs[firstIdx];\n        initRootX = P0.sx;\n        if (P0.sy > 0) initRootY = P0.sy - 1;\n        else initRootY = 0;\n    }\n\n    // Command sequence\n    vector<string> cmds;\n    cmds.reserve(100000);\n\n    int rootXsim = initRootX, rootYsim = initRootY; // simulation root position\n    int dir = 0;              // 0=Right initially\n    bool holding = false;\n\n    auto add_step = [&](char mv, char rot, bool doP) {\n        string S(2 * Vp, '.'); // length 4\n        S[0] = mv;\n        S[1] = rot;\n        if (doP) {\n            S[Vp + fingerVertex] = 'P'; // fingertip action (index 3)\n        }\n        cmds.push_back(S);\n\n        // Update root position\n        if (mv == 'U') rootXsim--;\n        else if (mv == 'D') rootXsim++;\n        else if (mv == 'L') rootYsim--;\n        else if (mv == 'R') rootYsim++;\n\n        // Update direction of edge (0,1)\n        if (rot == 'L') dir = (dir + 3) & 3;\n        else if (rot == 'R') dir = (dir + 1) & 3;\n    };\n\n    auto finger_x = [&]() { return rootXsim + DX[dir]; };\n    auto finger_y = [&]() { return rootYsim + DY[dir]; };\n\n    // Move root to (nx, ny) and orientation to ndir, overlapping movement & rotation\n    auto move_root_dir = [&](int nx, int ny, int ndir) {\n        int dx = nx - rootXsim;\n        int dy = ny - rootYsim;\n        vector<char> path;\n        if (dx > 0) path.insert(path.end(), dx, 'D');\n        else if (dx < 0) path.insert(path.end(), -dx, 'U');\n        if (dy > 0) path.insert(path.end(), dy, 'R');\n        else if (dy < 0) path.insert(path.end(), -dy, 'L');\n\n        int diff = (ndir - dir + 4) & 3;\n        int rotSteps = 0;\n        char rotChar = '.';\n        if (diff == 0) {\n            rotSteps = 0;\n        } else if (diff == 1) {\n            rotSteps = 1;\n            rotChar = 'R';\n        } else if (diff == 2) {\n            rotSteps = 2;\n            rotChar = 'R'; // two clockwise rotations\n        } else { // diff == 3\n            rotSteps = 1;\n            rotChar = 'L';\n        }\n\n        int moveSteps = (int)path.size();\n        int overlap = min(rotSteps, moveSteps);\n        for (int i = 0; i < moveSteps; i++) {\n            char mv = path[i];\n            char rot = (i < overlap ? rotChar : '.');\n            add_step(mv, rot, false);\n        }\n        for (int i = overlap; i < rotSteps; i++) {\n            // rotate in place\n            add_step('.', rotChar, false);\n        }\n    };\n\n    // Move fingertip exactly to (tx, ty)\n    auto move_finger_to = [&](int tx, int ty) {\n        int bestNX = rootXsim, bestNY = rootYsim, bestDir = dir;\n        int bestCost = INT_MAX;\n\n        for (int ndir = 0; ndir < 4; ndir++) {\n            int nrX = tx - DX[ndir];\n            int nrY = ty - DY[ndir];\n            if (nrX < 0 || nrX >= N || nrY < 0 || nrY >= N) continue;\n            int distRoot = abs(nrX - rootXsim) + abs(nrY - rootYsim);\n            int diff = (ndir - dir + 4) & 3;\n            int rotCost = min(diff, 4 - diff); // number of 90-degree rotations\n            int cost = max(distRoot, rotCost); // rotations overlapped with movement\n            if (cost < bestCost) {\n                bestCost = cost;\n                bestNX = nrX;\n                bestNY = nrY;\n                bestDir = ndir;\n            }\n        }\n\n        move_root_dir(bestNX, bestNY, bestDir);\n        // fingertip now at (tx, ty)\n    };\n\n    if (K > 0) {\n        for (int idx : order) {\n            const auto &P = pairs[idx];\n\n            // ===== PICK PHASE =====\n            size_t prevSize = cmds.size();\n            move_finger_to(P.sx, P.sy);\n            int fx = finger_x(), fy = finger_y();\n\n            bool doPick = false;\n            if (!holding && fx >= 0 && fx < N && fy >= 0 && fy < N && occ[fx][fy] == 1) {\n                doPick = true;\n                holding = true;\n                occ[fx][fy] = 0;\n            }\n\n            if (doPick) {\n                size_t curSize = cmds.size();\n                if (curSize > prevSize) {\n                    // Merge pick into the last movement/rotation step\n                    cmds[curSize - 1][Vp + fingerVertex] = 'P';\n                } else {\n                    // No movement/rotation was needed; add a standalone P step\n                    add_step('.', '.', true);\n                }\n            }\n\n            // ===== DROP PHASE =====\n            prevSize = cmds.size();\n            move_finger_to(P.tx, P.ty);\n            fx = finger_x();\n            fy = finger_y();\n\n            bool doDrop = false;\n            if (holding && fx >= 0 && fx < N && fy >= 0 && fy < N && occ[fx][fy] == 0) {\n                doDrop = true;\n                holding = false;\n                occ[fx][fy] = 1;\n            }\n\n            if (doDrop) {\n                size_t curSize = cmds.size();\n                if (curSize > prevSize) {\n                    // Merge drop into the last movement/rotation step\n                    cmds[curSize - 1][Vp + fingerVertex] = 'P';\n                } else {\n                    // No movement/rotation needed; add a standalone P step\n                    add_step('.', '.', true);\n                }\n            }\n        }\n    }\n\n    // Output\n    // 1) Tree description: 2 vertices: 0 (root), 1 (fingertip), length 1\n    cout << Vp << '\\n';\n    cout << 0 << ' ' << 1 << '\\n';\n\n    // 2) Initial root position\n    cout << initRootX << ' ' << initRootY << '\\n';\n\n    // 3) Operation sequence\n    for (const string &S : cmds) {\n        cout << S << '\\n';\n    }\n\n    return 0;\n}","ahc039":"#include <bits/stdc++.h>\nusing namespace std;\n\n// =================== Geometry utilities ===================\n\nbool pointInPolygon(int px, int py, const vector<pair<int,int>>& poly) {\n    int n = (int)poly.size();\n    bool inside = false;\n    for (int i = 0, j = n - 1; i < n; j = i++) {\n        long long xi = poly[i].first, yi = poly[i].second;\n        long long xj = poly[j].first, yj = poly[j].second;\n\n        long long minx = min(xi, xj), maxx = max(xi, xj);\n        long long miny = min(yi, yj), maxy = max(yi, yj);\n        long long cross = (xj - xi) * 1LL * (py - yi) - (yj - yi) * 1LL * (px - xi);\n        if (cross == 0 && px >= minx && px <= maxx && py >= miny && py <= maxy) {\n            return true; // on edge\n        }\n\n        bool cond = ((yi > py) != (yj > py)); // ignore horizontal edges\n        if (cond) {\n            double interX = xi + (double)(xj - xi) * (double)(py - yi) / (double)(yj - yi);\n            if (interX > px) inside = !inside;\n        }\n    }\n    return inside;\n}\n\nint evaluatePolygonDiff(const vector<pair<int,int>>& poly,\n                        const vector<int>& xs, const vector<int>& ys, int N) {\n    if (poly.empty()) return INT_MIN / 2;\n    int total = 2 * N;\n    int minx = INT_MAX, maxx = INT_MIN, miny = INT_MAX, maxy = INT_MIN;\n    for (auto &p : poly) {\n        minx = min(minx, p.first);\n        maxx = max(maxx, p.first);\n        miny = min(miny, p.second);\n        maxy = max(maxy, p.second);\n    }\n\n    int diff = 0;\n    for (int i = 0; i < total; ++i) {\n        int x = xs[i], y = ys[i];\n        if (x < minx || x > maxx || y < miny || y > maxy) continue;\n        if (pointInPolygon(x, y, poly)) {\n            diff += (i < N ? 1 : -1);\n        }\n    }\n    return diff;\n}\n\n// Build outer boundary polygon from a 4-connected component mask of grid cells.\nvector<pair<int,int>> buildPolygonFromMask(\n    int H, int W,\n    const vector<char>& inside,\n    const vector<int>& xCoord,\n    const vector<int>& yCoord\n) {\n    int V = (H + 1) * (W + 1);\n    vector<vector<int>> adj(V);\n\n    auto cellInside = [&](int i, int j) -> bool {\n        if (i < 0 || i >= H || j < 0 || j >= W) return false;\n        return inside[i * W + j] != 0;\n    };\n    auto vertIndex = [&](int r, int c) -> int {\n        return r * (W + 1) + c;\n    };\n    auto addEdge = [&](int u, int v) {\n        adj[u].push_back(v);\n        adj[v].push_back(u);\n    };\n\n    // Build boundary edges for all inside cells\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            if (!cellInside(i, j)) continue;\n\n            // Left side\n            if (j == 0 || !cellInside(i, j - 1)) {\n                int u = vertIndex(i, j);\n                int v = vertIndex(i + 1, j);\n                addEdge(u, v);\n            }\n            // Right side\n            if (j == W - 1 || !cellInside(i, j + 1)) {\n                int u = vertIndex(i, j + 1);\n                int v = vertIndex(i + 1, j + 1);\n                addEdge(u, v);\n            }\n            // Bottom side\n            if (i == 0 || !cellInside(i - 1, j)) {\n                int u = vertIndex(i, j);\n                int v = vertIndex(i, j + 1);\n                addEdge(u, v);\n            }\n            // Top side\n            if (i == H - 1 || !cellInside(i + 1, j)) {\n                int u = vertIndex(i + 1, j);\n                int v = vertIndex(i + 1, j + 1);\n                addEdge(u, v);\n            }\n        }\n    }\n\n    vector<char> used(V, 0);\n    vector<pair<int,int>> bestPoly;\n    long long bestAreaAbs = -1;\n\n    for (int start = 0; start < V; ++start) {\n        if (used[start] || adj[start].empty()) continue;\n\n        vector<int> cyc;\n        int cur = start;\n        int prev = -1;\n        int safety = 0;\n\n        while (true) {\n            cyc.push_back(cur);\n            used[cur] = 1;\n\n            if (adj[cur].empty()) {\n                cyc.clear();\n                break;\n            }\n\n            int nxt;\n            if ((int)adj[cur].size() == 1) {\n                nxt = adj[cur][0];\n            } else {\n                if (adj[cur][0] != prev) nxt = adj[cur][0];\n                else nxt = adj[cur][1];\n            }\n\n            prev = cur;\n            cur = nxt;\n            if (cur == start) break;\n\n            if (++safety > V * 4) {\n                cyc.clear();\n                break;\n            }\n        }\n\n        if (cyc.empty() || (int)cyc.size() < 4) continue;\n\n        // Convert to coordinates\n        vector<pair<int,int>> ptsRaw;\n        ptsRaw.reserve(cyc.size());\n        for (int vid : cyc) {\n            int r = vid / (W + 1);\n            int c = vid % (W + 1);\n            int x = xCoord[c];\n            int y = yCoord[r];\n            ptsRaw.emplace_back(x, y);\n        }\n\n        // Remove collinear vertices\n        int m = (int)ptsRaw.size();\n        vector<pair<int,int>> pts;\n        pts.reserve(m);\n        for (int i = 0; i < m; ++i) {\n            auto &prevP = ptsRaw[(i + m - 1) % m];\n            auto &curP  = ptsRaw[i];\n            auto &nextP = ptsRaw[(i + 1) % m];\n            bool collinear =\n                (prevP.first == curP.first && curP.first == nextP.first) ||\n                (prevP.second == curP.second && curP.second == nextP.second);\n            if (!collinear) {\n                pts.push_back(curP);\n            }\n        }\n\n        if ((int)pts.size() < 4) continue;\n        if ((int)pts.size() > 1000) continue;\n\n        // Perimeter check\n        long long per = 0;\n        int m2 = (int)pts.size();\n        for (int i = 0; i < m2; ++i) {\n            auto &a = pts[i];\n            auto &b = pts[(i + 1) % m2];\n            per += llabs((long long)a.first - b.first) + llabs((long long)a.second - b.second);\n        }\n        if (per > 400000LL) continue;\n\n        // Area (for picking the outermost largest cycle)\n        long long area2 = 0;\n        for (int i = 0; i < m2; ++i) {\n            long long x1 = pts[i].first, y1 = pts[i].second;\n            long long x2 = pts[(i + 1) % m2].first, y2 = pts[(i + 1) % m2].second;\n            area2 += x1 * y2 - x2 * y1;\n        }\n        long long areaAbs = llabs(area2);\n        if (areaAbs > bestAreaAbs) {\n            bestAreaAbs = areaAbs;\n            bestPoly = std::move(pts);\n        }\n    }\n\n    return bestPoly;\n}\n\nint evaluateRectDiff(int xL, int yB, int xR, int yT,\n                     const vector<int>& xs, const vector<int>& ys, int N) {\n    if (xL > xR || yB > yT) return INT_MIN / 2;\n    int total = 2 * N;\n    int diff = 0;\n    for (int i = 0; i < total; ++i) {\n        int x = xs[i], y = ys[i];\n        if (x >= xL && x <= xR && y >= yB && y <= yT) {\n            diff += (i < N ? 1 : -1);\n        }\n    }\n    return diff;\n}\n\n// =================== Main ===================\n\nstruct Rect {\n    int xL, yB, xR, yT;\n    int diff;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    if (!(cin >> N)) return 0;\n    int total = 2 * N;\n\n    const int MAXC = 100000;\n    const int FULL = MAXC + 1;\n\n    vector<int> xs(total), ys(total);\n    for (int i = 0; i < total; ++i) {\n        cin >> xs[i] >> ys[i];\n    }\n\n    // Global best polygon and best rectangle\n    vector<pair<int,int>> bestPoly = {\n        {0, 0},\n        {MAXC, 0},\n        {MAXC, MAXC},\n        {0, MAXC}\n    };\n    int bestDiff = 0;\n    Rect bestRect = {0, 0, MAXC, MAXC, 0};\n\n    auto updateBestRectWithDiff = [&](int xL, int yB, int xR, int yT, int diff) {\n        if (diff > bestRect.diff) {\n            bestRect = {xL, yB, xR, yT, diff};\n        }\n        if (diff > bestDiff) {\n            bestDiff = diff;\n            bestPoly.clear();\n            bestPoly.push_back({xL, yB});\n            bestPoly.push_back({xR, yB});\n            bestPoly.push_back({xR, yT});\n            bestPoly.push_back({xL, yT});\n        }\n    };\n\n    auto updateBestWithRect = [&](int xL, int yB, int xR, int yT) {\n        if (xL > xR || yB > yT) return;\n        int diff = evaluateRectDiff(xL, yB, xR, yT, xs, ys, N);\n        updateBestRectWithDiff(xL, yB, xR, yT, diff);\n    };\n\n    auto updateBestWithPoly = [&](const vector<pair<int,int>>& poly) {\n        if (poly.empty()) return;\n        int diff = evaluatePolygonDiff(poly, xs, ys, N);\n        if (diff > bestDiff) {\n            bestDiff = diff;\n            bestPoly = poly;\n        }\n    };\n\n    // Grid sizes and weight modes\n    vector<int> gridSizes = {40, 60, 90, 130, 160};\n    // (weight for mackerel, weight for sardine)\n    vector<pair<int,int>> weightModes = {\n        {1, -1},\n        {1, -2},\n        {2, -1},\n        {1, -3},\n        {2, -3}\n    };\n\n    vector<int> cell;\n    vector<long long> colSum;\n\n    for (int S : gridSizes) {\n        int H = S, W = S;\n        vector<int> xCoord(W + 1), yCoord(H + 1);\n        for (int j = 0; j <= W; ++j) {\n            int val = (int)(1LL * j * FULL / W);\n            if (val > MAXC) val = MAXC;\n            xCoord[j] = val;\n        }\n        for (int i = 0; i <= H; ++i) {\n            int val = (int)(1LL * i * FULL / H);\n            if (val > MAXC) val = MAXC;\n            yCoord[i] = val;\n        }\n\n        // Per-cell counts\n        vector<int> mCell(H * W, 0), sCell(H * W, 0), rawCell(H * W, 0);\n        for (int idx = 0; idx < total; ++idx) {\n            int x = xs[idx], y = ys[idx];\n            int cx = (int)(1LL * x * W / FULL);\n            int cy = (int)(1LL * y * H / FULL);\n            if (cx < 0) cx = 0;\n            if (cx >= W) cx = W - 1;\n            if (cy < 0) cy = 0;\n            if (cy >= H) cy = H - 1;\n            int cidx = cy * W + cx;\n            if (idx < N) mCell[cidx]++; else sCell[cidx]++;\n        }\n        for (int i = 0; i < H * W; ++i) {\n            rawCell[i] = mCell[i] - sCell[i];\n        }\n\n        for (auto [wM, wS] : weightModes) {\n            // Weighted cell values\n            cell.assign(H * W, 0);\n            for (int i = 0; i < H * W; ++i) {\n                cell[i] = wM * mCell[i] + wS * sCell[i];\n            }\n\n            // ---- 2D Kadane to find best sub-rectangle on this grid ----\n            const long long NEG_INF = -(1LL << 60);\n            long long bestSum = NEG_INF;\n            int bestL = 0, bestR = 0, bestT = 0, bestB = 0;\n\n            colSum.assign(W, 0);\n            for (int top = 0; top < H; ++top) {\n                fill(colSum.begin(), colSum.end(), 0);\n                for (int bottom = top; bottom < H; ++bottom) {\n                    int rowOffset = bottom * W;\n                    for (int c = 0; c < W; ++c) {\n                        colSum[c] += cell[rowOffset + c];\n                    }\n                    long long sum = 0;\n                    int curL = 0;\n                    for (int c = 0; c < W; ++c) {\n                        if (sum <= 0) {\n                            sum = colSum[c];\n                            curL = c;\n                        } else {\n                            sum += colSum[c];\n                        }\n                        if (sum > bestSum) {\n                            bestSum = sum;\n                            bestL = curL;\n                            bestR = c;\n                            bestT = top;\n                            bestB = bottom;\n                        }\n                    }\n                }\n            }\n\n            if (bestSum > 0) {\n                int xL = xCoord[bestL];\n                int xR = xCoord[bestR + 1];\n                int yB = yCoord[bestT];\n                int yT = yCoord[bestB + 1];\n                if (xL < 0) xL = 0;\n                if (xR > MAXC) xR = MAXC;\n                if (yB < 0) yB = 0;\n                if (yT > MAXC) yT = MAXC;\n                updateBestWithRect(xL, yB, xR, yT);\n            }\n\n            // ---- Connected positive components (cell > 0) -> polygons ----\n            vector<char> visited(H * W, 0);\n            struct Comp {\n                long long weightedSum;\n                long long rawDiff;\n                vector<pair<int,int>> cells;\n            };\n            vector<Comp> bestComps;\n            const int KCOMP = 2;\n\n            static const int dr[4] = {-1, 1, 0, 0};\n            static const int dc[4] = {0, 0, -1, 1};\n\n            for (int i = 0; i < H; ++i) {\n                for (int j = 0; j < W; ++j) {\n                    int idx = i * W + j;\n                    if (visited[idx] || cell[idx] <= 0) continue;\n\n                    long long curWeighted = 0;\n                    long long curRaw = 0;\n                    vector<pair<int,int>> compCells;\n                    compCells.reserve(64);\n\n                    queue<int> q;\n                    visited[idx] = 1;\n                    q.push(idx);\n\n                    while (!q.empty()) {\n                        int u = q.front(); q.pop();\n                        int r = u / W, c = u % W;\n                        compCells.emplace_back(r, c);\n                        curWeighted += cell[u];\n                        curRaw += rawCell[u];\n\n                        for (int d = 0; d < 4; ++d) {\n                            int nr = r + dr[d];\n                            int nc = c + dc[d];\n                            if (nr < 0 || nr >= H || nc < 0 || nc >= W) continue;\n                            int v = nr * W + nc;\n                            if (!visited[v] && cell[v] > 0) {\n                                visited[v] = 1;\n                                q.push(v);\n                            }\n                        }\n                    }\n\n                    if (curWeighted <= 0) continue;\n\n                    if ((int)bestComps.size() < KCOMP) {\n                        bestComps.push_back({curWeighted, curRaw, std::move(compCells)});\n                    } else {\n                        int pos = (bestComps[0].rawDiff < bestComps[1].rawDiff ? 0 : 1);\n                        if (curRaw > bestComps[pos].rawDiff) {\n                            bestComps[pos] = {curWeighted, curRaw, std::move(compCells)};\n                        }\n                    }\n                }\n            }\n\n            for (auto &comp : bestComps) {\n                vector<char> mask(H * W, 0);\n                for (auto &rc : comp.cells) {\n                    mask[rc.first * W + rc.second] = 1;\n                }\n                auto poly = buildPolygonFromMask(H, W, mask, xCoord, yCoord);\n                if (!poly.empty()) {\n                    updateBestWithPoly(poly);\n                }\n            }\n\n            // ---- Additional: rawDiff threshold components for wM=1, wS=-1 ----\n            if (wM == 1 && wS == -1 && S >= 60) {\n                int thresholds[2] = {2, 3};\n                for (int t = 0; t < 2; ++t) {\n                    int thr = thresholds[t];\n                    vector<char> visitedThr(H * W, 0);\n                    vector<Comp> bestCompsThr;\n\n                    for (int i = 0; i < H; ++i) {\n                        for (int j = 0; j < W; ++j) {\n                            int idx = i * W + j;\n                            if (visitedThr[idx] || rawCell[idx] < thr) continue;\n\n                            long long curRaw = 0;\n                            vector<pair<int,int>> compCells;\n                            compCells.reserve(64);\n\n                            queue<int> q;\n                            visitedThr[idx] = 1;\n                            q.push(idx);\n\n                            while (!q.empty()) {\n                                int u = q.front(); q.pop();\n                                int r = u / W, c = u % W;\n                                compCells.emplace_back(r, c);\n                                curRaw += rawCell[u];\n\n                                for (int d = 0; d < 4; ++d) {\n                                    int nr = r + dr[d];\n                                    int nc = c + dc[d];\n                                    if (nr < 0 || nr >= H || nc < 0 || nc >= W) continue;\n                                    int v = nr * W + nc;\n                                    if (!visitedThr[v] && rawCell[v] >= thr) {\n                                        visitedThr[v] = 1;\n                                        q.push(v);\n                                    }\n                                }\n                            }\n\n                            if (curRaw <= 0) continue;\n\n                            if ((int)bestCompsThr.size() < KCOMP) {\n                                bestCompsThr.push_back({curRaw, curRaw, std::move(compCells)});\n                            } else {\n                                int pos = (bestCompsThr[0].rawDiff < bestCompsThr[1].rawDiff ? 0 : 1);\n                                if (curRaw > bestCompsThr[pos].rawDiff) {\n                                    bestCompsThr[pos] = {curRaw, curRaw, std::move(compCells)};\n                                }\n                            }\n                        }\n                    }\n\n                    for (auto &comp : bestCompsThr) {\n                        vector<char> mask(H * W, 0);\n                        for (auto &rc : comp.cells) {\n                            mask[rc.first * W + rc.second] = 1;\n                        }\n                        auto poly = buildPolygonFromMask(H, W, mask, xCoord, yCoord);\n                        if (!poly.empty()) {\n                            updateBestWithPoly(poly);\n                        }\n                    }\n                }\n            }\n        }\n    }\n\n    // Fallback small rectangles around mackerels if nothing positive\n    if (bestDiff <= 0) {\n        const int delta = 1000;\n        for (int i = 0; i < N; ++i) {\n            int xL = max(0, xs[i] - delta);\n            int xR = min(100000, xs[i] + delta);\n            int yB = max(0, ys[i] - delta);\n            int yT = min(100000, ys[i] + delta);\n            updateBestWithRect(xL, yB, xR, yT);\n        }\n    }\n\n    // ---------- Local grid refinement around bestRect ----------\n\n    auto localGridRefine = [&]() {\n        if (bestRect.diff <= 0) return;\n        const int margin = 8000;\n        int xL0 = max(0, bestRect.xL - margin);\n        int xR0 = min(MAXC, bestRect.xR + margin);\n        int yB0 = max(0, bestRect.yB - margin);\n        int yT0 = min(MAXC, bestRect.yT + margin);\n        if (xL0 >= xR0 || yB0 >= yT0) return;\n\n        int localW = xR0 - xL0 + 1;\n        int localH = yT0 - yB0 + 1;\n        if (localW <= 5 || localH <= 5) return;\n\n        const int S = 80;\n        int H = S, W = S;\n\n        vector<int> xCoord(W + 1), yCoord(H + 1);\n        for (int j = 0; j <= W; ++j) {\n            int val = xL0 + (int)((long long)j * localW / W);\n            if (val > xR0) val = xR0;\n            xCoord[j] = val;\n        }\n        for (int i = 0; i <= H; ++i) {\n            int val = yB0 + (int)((long long)i * localH / H);\n            if (val > yT0) val = yT0;\n            yCoord[i] = val;\n        }\n\n        vector<int> mCell(H * W, 0), sCell(H * W, 0), rawCell(H * W, 0);\n        for (int idx = 0; idx < total; ++idx) {\n            int x = xs[idx], y = ys[idx];\n            if (x < xL0 || x > xR0 || y < yB0 || y > yT0) continue;\n            int cx = (int)((long long)(x - xL0) * W / localW);\n            int cy = (int)((long long)(y - yB0) * H / localH);\n            if (cx < 0) cx = 0;\n            if (cx >= W) cx = W - 1;\n            if (cy < 0) cy = 0;\n            if (cy >= H) cy = H - 1;\n            int cidx = cy * W + cx;\n            if (idx < N) mCell[cidx]++; else sCell[cidx]++;\n        }\n        for (int i = 0; i < H * W; ++i) {\n            rawCell[i] = mCell[i] - sCell[i];\n        }\n\n        vector<pair<int,int>> localWeightModes = {\n            {1, -1},\n            {1, -2},\n            {2, -1}\n        };\n\n        vector<int> cellLocal(H * W);\n        vector<long long> colSumLocal(W);\n\n        for (auto [wM, wS] : localWeightModes) {\n            for (int i = 0; i < H * W; ++i) {\n                cellLocal[i] = wM * mCell[i] + wS * sCell[i];\n            }\n\n            // 2D Kadane on local grid\n            const long long NEG_INF = -(1LL << 60);\n            long long bestSum = NEG_INF;\n            int bestL = 0, bestR = 0, bestT = 0, bestB = 0;\n\n            fill(colSumLocal.begin(), colSumLocal.end(), 0);\n            for (int top = 0; top < H; ++top) {\n                fill(colSumLocal.begin(), colSumLocal.end(), 0);\n                for (int bottom = top; bottom < H; ++bottom) {\n                    int rowOffset = bottom * W;\n                    for (int c = 0; c < W; ++c) {\n                        colSumLocal[c] += cellLocal[rowOffset + c];\n                    }\n                    long long sum = 0;\n                    int curL = 0;\n                    for (int c = 0; c < W; ++c) {\n                        if (sum <= 0) {\n                            sum = colSumLocal[c];\n                            curL = c;\n                        } else {\n                            sum += colSumLocal[c];\n                        }\n                        if (sum > bestSum) {\n                            bestSum = sum;\n                            bestL = curL;\n                            bestR = c;\n                            bestT = top;\n                            bestB = bottom;\n                        }\n                    }\n                }\n            }\n\n            if (bestSum > 0) {\n                int xL = xCoord[bestL];\n                int xR = xCoord[bestR + 1];\n                int yB = yCoord[bestT];\n                int yT = yCoord[bestB + 1];\n                if (xL < 0) xL = 0;\n                if (xR > MAXC) xR = MAXC;\n                if (yB < 0) yB = 0;\n                if (yT > MAXC) yT = MAXC;\n                updateBestWithRect(xL, yB, xR, yT);\n            }\n\n            // Connected components with cellLocal > 0\n            vector<char> visited(H * W, 0);\n            struct Comp {\n                long long rawDiff;\n                vector<pair<int,int>> cells;\n            };\n            vector<Comp> bestComps;\n            const int KCOMP = 2;\n            static const int dr[4] = {-1, 1, 0, 0};\n            static const int dc[4] = {0, 0, -1, 1};\n\n            for (int i = 0; i < H; ++i) {\n                for (int j = 0; j < W; ++j) {\n                    int idx = i * W + j;\n                    if (visited[idx] || cellLocal[idx] <= 0) continue;\n\n                    long long curRaw = 0;\n                    vector<pair<int,int>> compCells;\n                    compCells.reserve(32);\n\n                    queue<int> q;\n                    visited[idx] = 1;\n                    q.push(idx);\n\n                    while (!q.empty()) {\n                        int u = q.front(); q.pop();\n                        int r = u / W, c = u % W;\n                        compCells.emplace_back(r, c);\n                        curRaw += rawCell[u];\n\n                        for (int d = 0; d < 4; ++d) {\n                            int nr = r + dr[d];\n                            int nc = c + dc[d];\n                            if (nr < 0 || nr >= H || nc < 0 || nc >= W) continue;\n                            int v = nr * W + nc;\n                            if (!visited[v] && cellLocal[v] > 0) {\n                                visited[v] = 1;\n                                q.push(v);\n                            }\n                        }\n                    }\n\n                    if (curRaw <= 0) continue;\n                    if ((int)bestComps.size() < KCOMP) {\n                        bestComps.push_back({curRaw, std::move(compCells)});\n                    } else {\n                        int pos = (bestComps[0].rawDiff < bestComps[1].rawDiff ? 0 : 1);\n                        if (curRaw > bestComps[pos].rawDiff) {\n                            bestComps[pos] = {curRaw, std::move(compCells)};\n                        }\n                    }\n                }\n            }\n\n            for (auto &comp : bestComps) {\n                vector<char> mask(H * W, 0);\n                for (auto &rc : comp.cells) {\n                    mask[rc.first * W + rc.second] = 1;\n                }\n                auto poly = buildPolygonFromMask(H, W, mask, xCoord, yCoord);\n                if (!poly.empty()) {\n                    updateBestWithPoly(poly);\n                }\n            }\n        }\n    };\n\n    localGridRefine();\n\n    // ---------- Local search on rectangles (multi-start) ----------\n\n    vector<int> uniqX = xs, uniqY = ys;\n    sort(uniqX.begin(), uniqX.end());\n    uniqX.erase(unique(uniqX.begin(), uniqX.end()), uniqX.end());\n    sort(uniqY.begin(), uniqY.end());\n    uniqY.erase(unique(uniqY.begin(), uniqY.end()), uniqY.end());\n\n    mt19937 rng(1234567);\n\n    auto randRange = [&](int lo, int hi) -> int {\n        if (lo > hi) return lo;\n        uint32_t r = rng();\n        return lo + (int)(r % (uint32_t)(hi - lo + 1));\n    };\n\n    // Deterministic side refinement for a rectangle\n    auto refineRect = [&](Rect &cur) {\n        if (uniqX.empty() || uniqY.empty()) return;\n        static const int OFFS[6] = {-50, -25, -10, 10, 25, 50};\n        int Mx = (int)uniqX.size();\n        int My = (int)uniqY.size();\n\n        for (int pass = 0; pass < 2; ++pass) {\n            // Left\n            {\n                int idx = (int)(lower_bound(uniqX.begin(), uniqX.end(), cur.xL) - uniqX.begin());\n                if (idx >= Mx) idx = Mx - 1;\n                int base = idx;\n                int bestLocalDiff = cur.diff;\n                int bestLocalX = cur.xL;\n                for (int k = 0; k < 6; ++k) {\n                    int nidx = base + OFFS[k];\n                    if (nidx < 0) nidx = 0;\n                    if (nidx >= Mx) nidx = Mx - 1;\n                    int nx = uniqX[nidx];\n                    if (nx >= cur.xR) continue;\n                    if (nx == cur.xL) continue;\n                    int diff = evaluateRectDiff(nx, cur.yB, cur.xR, cur.yT, xs, ys, N);\n                    if (diff > bestLocalDiff) {\n                        bestLocalDiff = diff;\n                        bestLocalX = nx;\n                    }\n                }\n                if (bestLocalDiff > cur.diff) {\n                    cur.xL = bestLocalX;\n                    cur.diff = bestLocalDiff;\n                    updateBestRectWithDiff(cur.xL, cur.yB, cur.xR, cur.yT, cur.diff);\n                }\n            }\n            // Right\n            {\n                int idx = (int)(upper_bound(uniqX.begin(), uniqX.end(), cur.xR) - uniqX.begin()) - 1;\n                if (idx < 0) idx = 0;\n                int base = idx;\n                int bestLocalDiff = cur.diff;\n                int bestLocalX = cur.xR;\n                for (int k = 0; k < 6; ++k) {\n                    int nidx = base + OFFS[k];\n                    if (nidx < 0) nidx = 0;\n                    if (nidx >= Mx) nidx = Mx - 1;\n                    int nx = uniqX[nidx];\n                    if (nx <= cur.xL) continue;\n                    if (nx == cur.xR) continue;\n                    int diff = evaluateRectDiff(cur.xL, cur.yB, nx, cur.yT, xs, ys, N);\n                    if (diff > bestLocalDiff) {\n                        bestLocalDiff = diff;\n                        bestLocalX = nx;\n                    }\n                }\n                if (bestLocalDiff > cur.diff) {\n                    cur.xR = bestLocalX;\n                    cur.diff = bestLocalDiff;\n                    updateBestRectWithDiff(cur.xL, cur.yB, cur.xR, cur.yT, cur.diff);\n                }\n            }\n            // Bottom\n            {\n                int idx = (int)(lower_bound(uniqY.begin(), uniqY.end(), cur.yB) - uniqY.begin());\n                if (idx >= My) idx = My - 1;\n                int base = idx;\n                int bestLocalDiff = cur.diff;\n                int bestLocalY = cur.yB;\n                for (int k = 0; k < 6; ++k) {\n                    int nidx = base + OFFS[k];\n                    if (nidx < 0) nidx = 0;\n                    if (nidx >= My) nidx = My - 1;\n                    int ny = uniqY[nidx];\n                    if (ny >= cur.yT) continue;\n                    if (ny == cur.yB) continue;\n                    int diff = evaluateRectDiff(cur.xL, ny, cur.xR, cur.yT, xs, ys, N);\n                    if (diff > bestLocalDiff) {\n                        bestLocalDiff = diff;\n                        bestLocalY = ny;\n                    }\n                }\n                if (bestLocalDiff > cur.diff) {\n                    cur.yB = bestLocalY;\n                    cur.diff = bestLocalDiff;\n                    updateBestRectWithDiff(cur.xL, cur.yB, cur.xR, cur.yT, cur.diff);\n                }\n            }\n            // Top\n            {\n                int idx = (int)(upper_bound(uniqY.begin(), uniqY.end(), cur.yT) - uniqY.begin()) - 1;\n                if (idx < 0) idx = 0;\n                int base = idx;\n                int bestLocalDiff = cur.diff;\n                int bestLocalY = cur.yT;\n                for (int k = 0; k < 6; ++k) {\n                    int nidx = base + OFFS[k];\n                    if (nidx < 0) nidx = 0;\n                    if (nidx >= My) nidx = My - 1;\n                    int ny = uniqY[nidx];\n                    if (ny <= cur.yB) continue;\n                    if (ny == cur.yT) continue;\n                    int diff = evaluateRectDiff(cur.xL, cur.yB, cur.xR, ny, xs, ys, N);\n                    if (diff > bestLocalDiff) {\n                        bestLocalDiff = diff;\n                        bestLocalY = ny;\n                    }\n                }\n                if (bestLocalDiff > cur.diff) {\n                    cur.yT = bestLocalY;\n                    cur.diff = bestLocalDiff;\n                    updateBestRectWithDiff(cur.xL, cur.yB, cur.xR, cur.yT, cur.diff);\n                }\n            }\n        }\n    };\n\n    auto localSearchFromSeed = [&](Rect seed) {\n        if (uniqX.empty() || uniqY.empty()) return;\n\n        Rect cur = seed;\n        cur.diff = evaluateRectDiff(cur.xL, cur.yB, cur.xR, cur.yT, xs, ys, N);\n        updateBestRectWithDiff(cur.xL, cur.yB, cur.xR, cur.yT, cur.diff);\n\n        refineRect(cur);\n\n        int curDiff = cur.diff;\n        int Mx = (int)uniqX.size();\n        int My = (int)uniqY.size();\n        const int ITER = 400;\n        const int RANGE = 50;\n\n        auto randRangeLocal = [&](int lo, int hi) -> int {\n            if (lo > hi) return lo;\n            uint32_t r = rng();\n            return lo + (int)(r % (uint32_t)(hi - lo + 1));\n        };\n\n        for (int it = 0; it < ITER; ++it) {\n            Rect cand = cur;\n            bool ok = false;\n            int side = randRangeLocal(0, 3); // 0:left,1:right,2:bottom,3:top\n\n            for (int attempt = 0; attempt < 5; ++attempt) {\n                if (side == 0) { // move left\n                    int idx = (int)(lower_bound(uniqX.begin(), uniqX.end(), cur.xL) - uniqX.begin());\n                    if (idx >= Mx) idx = Mx - 1;\n                    int lo = max(0, idx - RANGE);\n                    int hi = idx;\n                    if (lo > hi) break;\n                    int newIdx = randRangeLocal(lo, hi);\n                    int nx = uniqX[newIdx];\n                    if (nx >= cand.xR) continue;\n                    cand.xL = nx;\n                    ok = true;\n                    break;\n                } else if (side == 1) { // move right\n                    int idx = (int)(upper_bound(uniqX.begin(), uniqX.end(), cur.xR) - uniqX.begin()) - 1;\n                    if (idx < 0) idx = 0;\n                    int lo = idx;\n                    int hi = min(Mx - 1, idx + RANGE);\n                    if (lo > hi) break;\n                    int newIdx = randRangeLocal(lo, hi);\n                    int nx = uniqX[newIdx];\n                    if (nx <= cand.xL) continue;\n                    cand.xR = nx;\n                    ok = true;\n                    break;\n                } else if (side == 2) { // move bottom\n                    int idx = (int)(lower_bound(uniqY.begin(), uniqY.end(), cur.yB) - uniqY.begin());\n                    if (idx >= My) idx = My - 1;\n                    int lo = max(0, idx - RANGE);\n                    int hi = idx;\n                    if (lo > hi) break;\n                    int newIdx = randRangeLocal(lo, hi);\n                    int ny = uniqY[newIdx];\n                    if (ny >= cand.yT) continue;\n                    cand.yB = ny;\n                    ok = true;\n                    break;\n                } else { // move top\n                    int idx = (int)(upper_bound(uniqY.begin(), uniqY.end(), cur.yT) - uniqY.begin()) - 1;\n                    if (idx < 0) idx = 0;\n                    int lo = idx;\n                    int hi = min(My - 1, idx + RANGE);\n                    if (lo > hi) break;\n                    int newIdx = randRangeLocal(lo, hi);\n                    int ny = uniqY[newIdx];\n                    if (ny <= cand.yB) continue;\n                    cand.yT = ny;\n                    ok = true;\n                    break;\n                }\n            }\n\n            if (!ok) continue;\n            if (cand.xL == cur.xL && cand.xR == cur.xR &&\n                cand.yB == cur.yB && cand.yT == cur.yT) continue;\n\n            int diff = evaluateRectDiff(cand.xL, cand.yB, cand.xR, cand.yT, xs, ys, N);\n            if (diff > curDiff) {\n                cur = cand;\n                curDiff = diff;\n                cur.diff = diff;\n                updateBestRectWithDiff(cur.xL, cur.yB, cur.xR, cur.yT, cur.diff);\n            }\n        }\n    };\n\n    // Save base rectangle before local search\n    Rect baseBestRect = bestRect;\n\n    // Seed 1: base best rectangle\n    localSearchFromSeed(baseBestRect);\n\n    // Seed 2: bounding rectangle of best polygon\n    {\n        int minx = INT_MAX, maxx = INT_MIN, miny = INT_MAX, maxy = INT_MIN;\n        for (auto &p : bestPoly) {\n            minx = min(minx, p.first);\n            maxx = max(maxx, p.first);\n            miny = min(miny, p.second);\n            maxy = max(maxy, p.second);\n        }\n        if (minx < 0) minx = 0;\n        if (maxx > MAXC) maxx = MAXC;\n        if (miny < 0) miny = 0;\n        if (maxy > MAXC) maxy = MAXC;\n        if (minx < maxx && miny < maxy) {\n            Rect seed2 = {minx, miny, maxx, maxy, 0};\n            localSearchFromSeed(seed2);\n        }\n    }\n\n    // Seed 3: slightly expanded base rectangle\n    {\n        int delta = 2000;\n        Rect seed3;\n        seed3.xL = max(0, baseBestRect.xL - delta);\n        seed3.xR = min(MAXC, baseBestRect.xR + delta);\n        seed3.yB = max(0, baseBestRect.yB - delta);\n        seed3.yT = min(MAXC, baseBestRect.yT + delta);\n        if (seed3.xL < seed3.xR && seed3.yB < seed3.yT) {\n            localSearchFromSeed(seed3);\n        }\n    }\n\n    // Final polygon validity check\n    auto checkPolygon = [&](const vector<pair<int,int>>& poly) -> bool {\n        int m = (int)poly.size();\n        if (m < 4 || m > 1000) return false;\n        long long per = 0;\n        for (int i = 0; i < m; ++i) {\n            auto &a = poly[i];\n            auto &b = poly[(i + 1) % m];\n            per += llabs((long long)a.first - b.first) +\n                   llabs((long long)a.second - b.second);\n        }\n        if (per > 400000LL) return false;\n        set<pair<int,int>> st(poly.begin(), poly.end());\n        if ((int)st.size() != m) return false;\n        return true;\n    };\n\n    if (!checkPolygon(bestPoly)) {\n        bestPoly = {\n            {0, 0},\n            {MAXC, 0},\n            {MAXC, MAXC},\n            {0, MAXC}\n        };\n    }\n\n    cout << bestPoly.size() << '\\n';\n    for (auto &p : bestPoly) {\n        cout << p.first << ' ' << p.second << '\\n';\n    }\n    return 0;\n}","ahc040":"#include <bits/stdc++.h>\nusing namespace std;\nusing ll = long long;\n\nstruct EvalResult {\n    ll W = (1LL << 60);\n    ll H = (1LL << 60);\n    ll S = (1LL << 60);\n    vector<int> cuts; // 0 = cuts[0] < ... < cuts[R] = N\n};\n\n////////////////////\n// Horizontal DP  //\n////////////////////\n\nEvalResult evaluate_orientation_horizontal(const vector<ll>& w0,\n                                           const vector<ll>& h0,\n                                           const vector<int>& rot) {\n    int N = (int)w0.size();\n    const ll INF = (1LL << 62);\n\n    // Oriented sizes\n    vector<ll> width(N), height(N);\n    ll sumW = 0, maxW = 0;\n    long double area = 0.0L;\n    for (int i = 0; i < N; i++) {\n        if (rot[i] == 0) {\n            width[i]  = w0[i];\n            height[i] = h0[i];\n        } else {\n            width[i]  = h0[i];\n            height[i] = w0[i];\n        }\n        sumW += width[i];\n        maxW = max(maxW, width[i]);\n        area += (long double)width[i] * (long double)height[i];\n    }\n\n    EvalResult best;\n    if (sumW == 0) {\n        best.W = best.H = best.S = 0;\n        best.cuts = {0, N};\n        return best;\n    }\n\n    // Candidate width limits\n    vector<ll> Ws;\n    Ws.reserve(16);\n    Ws.push_back(sumW);\n    Ws.push_back(maxW);\n\n    long double base = sqrtl(max((long double)1.0L, area));\n    long double low  = max((long double)maxW, base * 0.5L);\n    long double high = min((long double)sumW, base * 2.0L);\n    if (high < low) high = low;\n\n    const int EXTRA = 10;\n    if (high == low) {\n        ll Wc = (ll)(low + 0.5L);\n        Ws.push_back(Wc);\n    } else {\n        for (int k = 0; k < EXTRA; k++) {\n            long double t = (k + 0.5L) / (long double)EXTRA;\n            long double w = low + (high - low) * t;\n            ll Wc = (ll)(w + 0.5L);\n            if (Wc < maxW) Wc = maxW;\n            if (Wc > sumW) Wc = sumW;\n            Ws.push_back(Wc);\n        }\n    }\n    sort(Ws.begin(), Ws.end());\n    Ws.erase(unique(Ws.begin(), Ws.end()), Ws.end());\n\n    vector<ll> dp(N + 1);\n    vector<int> prev(N + 1);\n\n    for (ll W_limit : Ws) {\n        dp[0] = 0;\n        prev[0] = -1;\n        for (int i = 1; i <= N; i++) {\n            ll bestH = INF;\n            int bestJ = -1;\n            ll rowW = 0;\n            ll rowH = 0;\n            for (int j = i - 1; j >= 0; j--) {\n                rowW += width[j];\n                if (rowW > W_limit) break;\n                if (height[j] > rowH) rowH = height[j];\n                ll cand = dp[j] + rowH;\n                if (cand < bestH) {\n                    bestH = cand;\n                    bestJ = j;\n                }\n            }\n            dp[i] = bestH;\n            prev[i] = bestJ;\n        }\n        if (prev[N] == -1 || dp[N] >= INF) continue;\n\n        vector<int> cuts;\n        int cur = N;\n        cuts.push_back(N);\n        while (cur > 0) {\n            int pj = prev[cur];\n            if (pj < 0) { cuts.clear(); break; }\n            cuts.push_back(pj);\n            cur = pj;\n        }\n        if (cuts.empty()) continue;\n        if (cuts.back() != 0) continue;\n        reverse(cuts.begin(), cuts.end());\n\n        ll Htotal = 0;\n        ll Wactual = 0;\n        int R = (int)cuts.size() - 1;\n        for (int r = 0; r < R; r++) {\n            int L = cuts[r];\n            int Ridx = cuts[r + 1];\n            ll rowW = 0;\n            ll rowH = 0;\n            for (int i = L; i < Ridx; i++) {\n                rowW += width[i];\n                if (height[i] > rowH) rowH = height[i];\n            }\n            Htotal += rowH;\n            if (rowW > Wactual) Wactual = rowW;\n        }\n        ll S = Htotal + Wactual;\n        if (S < best.S) {\n            best.S = S;\n            best.W = Wactual;\n            best.H = Htotal;\n            best.cuts = std::move(cuts);\n        }\n    }\n\n    if (best.S >= (1LL<<60)) {\n        best.cuts = {0, N};\n        ll rowW = 0, rowH = 0;\n        for (int i = 0; i < N; i++) {\n            rowW += width[i];\n            if (height[i] > rowH) rowH = height[i];\n        }\n        best.W = rowW;\n        best.H = rowH;\n        best.S = rowW + rowH;\n    }\n\n    return best;\n}\n\n///////////////////\n// Vertical DP   //\n///////////////////\n\nEvalResult evaluate_orientation_vertical(const vector<ll>& w0,\n                                         const vector<ll>& h0,\n                                         const vector<int>& rot) {\n    int N = (int)w0.size();\n    const ll INF = (1LL << 62);\n\n    // Oriented sizes\n    vector<ll> width(N), height(N);\n    for (int i = 0; i < N; i++) {\n        if (rot[i] == 0) {\n            width[i]  = w0[i];\n            height[i] = h0[i];\n        } else {\n            width[i]  = h0[i];\n            height[i] = w0[i];\n        }\n    }\n\n    // Swapped for DP\n    vector<ll> wS(N), hS(N);\n    ll sumW = 0, maxW = 0;\n    long double area = 0.0L;\n    for (int i = 0; i < N; i++) {\n        wS[i] = height[i];\n        hS[i] = width[i];\n        sumW += wS[i];\n        maxW = max(maxW, wS[i]);\n        area += (long double)wS[i] * (long double)hS[i];\n    }\n\n    EvalResult best;\n    if (sumW == 0) {\n        best.W = best.H = best.S = 0;\n        best.cuts = {0, N};\n        return best;\n    }\n\n    vector<ll> Ws;\n    Ws.reserve(16);\n    Ws.push_back(sumW);\n    Ws.push_back(maxW);\n\n    long double base = sqrtl(max((long double)1.0L, area));\n    long double low  = max((long double)maxW, base * 0.5L);\n    long double high = min((long double)sumW, base * 2.0L);\n    if (high < low) high = low;\n\n    const int EXTRA = 10;\n    if (high == low) {\n        ll Wc = (ll)(low + 0.5L);\n        Ws.push_back(Wc);\n    } else {\n        for (int k = 0; k < EXTRA; k++) {\n            long double t = (k + 0.5L) / (long double)EXTRA;\n            long double w = low + (high - low) * t;\n            ll Wc = (ll)(w + 0.5L);\n            if (Wc < maxW) Wc = maxW;\n            if (Wc > sumW) Wc = sumW;\n            Ws.push_back(Wc);\n        }\n    }\n    sort(Ws.begin(), Ws.end());\n    Ws.erase(unique(Ws.begin(), Ws.end()), Ws.end());\n\n    vector<ll> dp(N + 1);\n    vector<int> prev(N + 1);\n\n    for (ll W_limit : Ws) {\n        dp[0] = 0;\n        prev[0] = -1;\n        for (int i = 1; i <= N; i++) {\n            ll bestH = INF;\n            int bestJ = -1;\n            ll rowW = 0;\n            ll rowH = 0;\n            for (int j = i - 1; j >= 0; j--) {\n                rowW += wS[j];\n                if (rowW > W_limit) break;\n                if (hS[j] > rowH) rowH = hS[j];\n                ll cand = dp[j] + rowH;\n                if (cand < bestH) {\n                    bestH = cand;\n                    bestJ = j;\n                }\n            }\n            dp[i] = bestH;\n            prev[i] = bestJ;\n        }\n        if (prev[N] == -1 || dp[N] >= INF) continue;\n\n        vector<int> cuts;\n        int cur = N;\n        cuts.push_back(N);\n        while (cur > 0) {\n            int pj = prev[cur];\n            if (pj < 0) { cuts.clear(); break; }\n            cuts.push_back(pj);\n            cur = pj;\n        }\n        if (cuts.empty()) continue;\n        if (cuts.back() != 0) continue;\n        reverse(cuts.begin(), cuts.end());\n\n        ll Wcol = 0;\n        ll Hcol = 0;\n        int C = (int)cuts.size() - 1;\n        for (int c = 0; c < C; c++) {\n            int L = cuts[c];\n            int Ridx = cuts[c + 1];\n            ll colW = 0;\n            ll colH = 0;\n            for (int i = L; i < Ridx; i++) {\n                if (width[i] > colW) colW = width[i];\n                colH += height[i];\n            }\n            Wcol += colW;\n            if (colH > Hcol) Hcol = colH;\n        }\n        ll Scol = Wcol + Hcol;\n        if (Scol < best.S) {\n            best.S = Scol;\n            best.W = Wcol;\n            best.H = Hcol;\n            best.cuts = std::move(cuts);\n        }\n    }\n\n    if (best.S >= (1LL<<60)) {\n        best.cuts = {0, N};\n        ll colW = 0, colH = 0;\n        for (int i = 0; i < N; i++) {\n            if (width[i] > colW) colW = width[i];\n            colH += height[i];\n        }\n        best.W = colW;\n        best.H = colH;\n        best.S = best.W + best.H;\n    }\n\n    return best;\n}\n\nstruct Layout {\n    vector<int> rot;\n    EvalResult eval;\n    bool vertical; // false=L (rows), true=U (columns)\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, T;\n    ll sigma;\n    if (!(cin >> N >> T >> sigma)) {\n        return 0;\n    }\n    vector<ll> w0(N), h0(N);\n    for (int i = 0; i < N; i++) {\n        cin >> w0[i] >> h0[i];\n        if (w0[i] < 1) w0[i] = 1;\n        if (h0[i] < 1) h0[i] = 1;\n    }\n\n    // Baseline horizontal orientation search (original behavior)\n    vector<int> rot(N);\n    for (int i = 0; i < N; i++) {\n        // rotate if h0 > w0 so height = min dimension\n        rot[i] = (h0[i] > w0[i]) ? 1 : 0;\n    }\n    EvalResult bestH = evaluate_orientation_horizontal(w0, h0, rot);\n\n    const int BASE_PASSES = 2;\n    for (int pass = 0; pass < BASE_PASSES; pass++) {\n        for (int i = 0; i < N; i++) {\n            rot[i] ^= 1;\n            EvalResult cand = evaluate_orientation_horizontal(w0, h0, rot);\n            if (cand.S < bestH.S) {\n                bestH = cand;\n            } else {\n                rot[i] ^= 1; // revert\n            }\n        }\n    }\n    vector<int> baselineRot = rot;\n    EvalResult baselineEval = bestH;\n\n    mt19937_64 rng(123456789);\n\n    // Precompute layouts for each turn\n    vector<Layout> layouts(T);\n\n    // Turn 0: baseline horizontal layout\n    layouts[0].rot = baselineRot;\n    layouts[0].eval = baselineEval;\n    layouts[0].vertical = false;\n\n    // Turn 1: same orientation, choose best of horizontal/vertical\n    if (T > 1) {\n        Layout lay;\n        lay.rot = baselineRot;\n        EvalResult candH = baselineEval;\n        EvalResult candV = evaluate_orientation_vertical(w0, h0, lay.rot);\n        if (candV.S < candH.S) {\n            lay.vertical = true;\n            lay.eval = candV;\n        } else {\n            lay.vertical = false;\n            lay.eval = candH;\n        }\n        layouts[1] = std::move(lay);\n    }\n\n    // Remaining turns: random multi-bit neighbors of baselineRot,\n    // each evaluated with both horizontal and vertical, keep better.\n    for (int t = 2; t < T; t++) {\n        Layout lay;\n        lay.rot = baselineRot;\n\n        int maxK = min(N, 6); // flip between 2 and 6 bits\n        int k = 2;\n        if (maxK > 2) {\n            k = 2 + (int)(rng() % (maxK - 1)); // 2..maxK\n        }\n        if (k > N) k = N;\n\n        vector<int> idxs;\n        idxs.reserve(k);\n        while ((int)idxs.size() < k) {\n            int x = (int)(rng() % N);\n            bool ok = true;\n            for (int v : idxs) if (v == x) { ok = false; break; }\n            if (ok) idxs.push_back(x);\n        }\n        for (int id : idxs) lay.rot[id] ^= 1;\n\n        EvalResult candH = evaluate_orientation_horizontal(w0, h0, lay.rot);\n        EvalResult candV = evaluate_orientation_vertical(w0, h0, lay.rot);\n        if (candV.S < candH.S) {\n            lay.vertical = true;\n            lay.eval = candV;\n        } else {\n            lay.vertical = false;\n            lay.eval = candH;\n        }\n\n        layouts[t] = std::move(lay);\n    }\n\n    // Output layouts turn by turn\n    for (int t = 0; t < T; t++) {\n        const Layout &L = layouts[t];\n        const vector<int> &rotT = L.rot;\n        const EvalResult &ev = L.eval;\n        bool vertical = L.vertical;\n\n        // Oriented sizes for this layout\n        vector<ll> width(N), height(N);\n        for (int i = 0; i < N; i++) {\n            if (rotT[i] == 0) {\n                width[i]  = w0[i];\n                height[i] = h0[i];\n            } else {\n                width[i]  = h0[i];\n                height[i] = w0[i];\n            }\n        }\n\n        // Group assignment (rows or columns)\n        vector<int> group(N);\n        int G = (int)ev.cuts.size() - 1;\n        for (int g = 0; g < G; g++) {\n            for (int i = ev.cuts[g]; i < ev.cuts[g + 1]; i++) {\n                group[i] = g;\n            }\n        }\n\n        cout << N << '\\n';\n        if (!vertical) {\n            // Horizontal shelves: rows, direction 'L'\n            vector<int> baseRow(G, -1);\n            for (int g = 0; g < G; g++) {\n                int Lidx = ev.cuts[g];\n                int Ridx = ev.cuts[g + 1];\n                ll bestHrow = -1;\n                int bestIdx = Lidx;\n                for (int i = Lidx; i < Ridx; i++) {\n                    if (height[i] > bestHrow) {\n                        bestHrow = height[i];\n                        bestIdx = i;\n                    }\n                }\n                baseRow[g] = bestIdx;\n            }\n            for (int i = 0; i < N; i++) {\n                int r = group[i];\n                int b = (r == 0 ? -1 : baseRow[r - 1]);\n                char d = 'L';\n                cout << i << ' ' << rotT[i] << ' ' << d << ' ' << b << '\\n';\n            }\n        } else {\n            // Vertical shelves: columns, direction 'U'\n            vector<int> baseCol(G, -1);\n            for (int g = 0; g < G; g++) {\n                int Lidx = ev.cuts[g];\n                int Ridx = ev.cuts[g + 1];\n                ll bestWcol = -1;\n                int bestIdx = Lidx;\n                for (int i = Lidx; i < Ridx; i++) {\n                    if (width[i] > bestWcol) {\n                        bestWcol = width[i];\n                        bestIdx = i;\n                    }\n                }\n                baseCol[g] = bestIdx;\n            }\n            for (int i = 0; i < N; i++) {\n                int c = group[i];\n                int b = (c == 0 ? -1 : baseCol[c - 1]);\n                char d = 'U';\n                cout << i << ' ' << rotT[i] << ' ' << d << ' ' << b << '\\n';\n            }\n        }\n        cout.flush();\n\n        ll Wm, Hm;\n        if (!(cin >> Wm >> Hm)) return 0; // ignore measurements\n    }\n\n    return 0;\n}","ahc041":"#include <bits/stdc++.h>\nusing namespace std;\n\n// Simple fast RNG\nstruct FastRand {\n    uint64_t x;\n    FastRand() {\n        x = 88172645463393265ull;\n    }\n    uint64_t next() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return x;\n    }\n    int nextInt(int n) { // 0..n-1\n        return (int)(next() % (uint64_t)n);\n    }\n    double nextDouble() {\n        return (next() >> 11) * (1.0 / 9007199254740992.0); // [0,1)\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, H;\n    if (!(cin >> N >> M >> H)) {\n        return 0;\n    }\n\n    vector<int> A(N);\n    for (int i = 0; i < N; ++i) cin >> A[i];\n\n    vector<vector<int>> adj(N);\n    for (int i = 0; i < M; ++i) {\n        int u, v;\n        cin >> u >> v;\n        adj[u].push_back(v);\n        adj[v].push_back(u);\n    }\n\n    // Coordinates (unused in this solution, but must be read)\n    vector<int> x(N), y(N);\n    for (int i = 0; i < N; ++i) cin >> x[i] >> y[i];\n\n    // ---------- Initial forest construction: greedy by ascending beauty ----------\n    vector<int> parent(N, -1);\n    vector<int> depth(N, 0);\n    vector<char> processed(N, 0);\n\n    vector<int> orderAsc(N);\n    iota(orderAsc.begin(), orderAsc.end(), 0);\n    sort(orderAsc.begin(), orderAsc.end(), [&](int i, int j) {\n        if (A[i] != A[j]) return A[i] < A[j];\n        return i < j;\n    });\n\n    for (int idx = 0; idx < N; ++idx) {\n        int v = orderAsc[idx];\n        processed[v] = 1;\n        int bestParent = -1;\n        int bestDepth = -1;\n        for (int u : adj[v]) {\n            if (!processed[u]) continue;          // only already placed vertices\n            if (depth[u] > H - 1) continue;       // parent depth must allow child depth <= H\n            if (depth[u] > bestDepth) {\n                bestDepth = depth[u];\n                bestParent = u;\n            }\n        }\n        if (bestParent == -1) {\n            parent[v] = -1;\n            depth[v] = 0;\n        } else {\n            parent[v] = bestParent;\n            depth[v] = depth[bestParent] + 1;\n            if (depth[v] > H) depth[v] = H; // safety\n        }\n    }\n\n    // ---------- Build children lists ----------\n    vector<vector<int>> children(N);\n    for (int v = 0; v < N; ++v) {\n        int p = parent[v];\n        if (p != -1) children[p].push_back(v);\n    }\n\n    // ---------- Compute subtreeSum and subHeight bottom-up ----------\n    vector<vector<int>> nodesAtDepth(H + 1);\n    for (int v = 0; v < N; ++v) {\n        int d = depth[v];\n        if (d < 0) d = 0;\n        if (d > H) d = H;\n        nodesAtDepth[d].push_back(v);\n    }\n\n    vector<long long> subtreeSum(N, 0);\n    vector<int> subHeight(N, 0);\n\n    for (int d = H; d >= 0; --d) {\n        for (int v : nodesAtDepth[d]) {\n            long long sum = A[v];\n            int h = 0;\n            for (int c : children[v]) {\n                sum += subtreeSum[c];\n                h = max(h, 1 + subHeight[c]);\n            }\n            subtreeSum[v] = sum;\n            subHeight[v] = h;\n        }\n    }\n\n    // ---------- Compute initial score ----------\n    long long score = 0;\n    for (int v = 0; v < N; ++v) {\n        int d = depth[v];\n        if (d < 0) d = 0;\n        if (d > H) d = H;\n        score += (long long)(d + 1) * (long long)A[v];\n    }\n\n    // From now on, we get depths on demand from parent pointers.\n    auto getDepth = [&](int v) -> int {\n        int d = 0;\n        while (parent[v] != -1) {\n            v = parent[v];\n            ++d;\n        }\n        return d; // \u2264 H\n    };\n\n    // Best solution tracking (we will run extra local search / SA)\n    long long bestScore = score;\n    vector<int> bestParent = parent;\n\n    // ---------- Helpers for local modifications ----------\n    auto recomputeHeightFrom = [&](int start) {\n        int x = start;\n        while (x != -1) {\n            int old_h = subHeight[x];\n            int new_h = 0;\n            for (int c : children[x]) {\n                new_h = max(new_h, 1 + subHeight[c]);\n            }\n            if (new_h == old_h) break;\n            subHeight[x] = new_h;\n            x = parent[x];\n        }\n    };\n\n    auto reparentFn = [&](int v, int newParent, int oldDepth, int newDepth) {\n        int oldParent = parent[v];\n        if (oldParent == newParent) return;\n\n        long long deltaDepth = (long long)(newDepth - oldDepth);\n        long long deltaScore = deltaDepth * subtreeSum[v];\n        score += deltaScore;\n\n        // Update subtreeSum along old parent path: remove subtreeSum[v]\n        if (oldParent != -1) {\n            for (int x = oldParent; x != -1; x = parent[x]) {\n                subtreeSum[x] -= subtreeSum[v];\n            }\n        }\n\n        // Update subtreeSum along new parent path: add subtreeSum[v]\n        if (newParent != -1) {\n            for (int x = newParent; x != -1; x = parent[x]) {\n                subtreeSum[x] += subtreeSum[v];\n            }\n        }\n\n        // Update children lists\n        if (oldParent != -1) {\n            auto &vec = children[oldParent];\n            for (int i = 0; i < (int)vec.size(); ++i) {\n                if (vec[i] == v) {\n                    vec[i] = vec.back();\n                    vec.pop_back();\n                    break;\n                }\n            }\n        }\n        if (newParent != -1) {\n            children[newParent].push_back(v);\n        }\n\n        parent[v] = newParent;\n\n        // Update heights along old and new parent paths\n        if (oldParent != -1) recomputeHeightFrom(oldParent);\n        if (newParent != -1) recomputeHeightFrom(newParent);\n\n        // Record best solution\n        if (score > bestScore) {\n            bestScore = score;\n            bestParent = parent;\n        }\n    };\n\n    // ---------- Greedy hill climbing (depth-increasing only) ----------\n    vector<int> orderDesc(N);\n    iota(orderDesc.begin(), orderDesc.end(), 0);\n    sort(orderDesc.begin(), orderDesc.end(), [&](int i, int j) {\n        if (A[i] != A[j]) return A[i] > A[j];\n        return i < j;\n    });\n\n    bool improved;\n    do {\n        improved = false;\n        for (int v : orderDesc) {\n            int oldParent = parent[v];\n            int oldDepth = getDepth(v);\n            long long bestDelta = 0;\n            int bestP = oldParent;\n            int bestNewDepth = oldDepth;\n\n            for (int u : adj[v]) {\n                if (u == oldParent) continue;\n\n                // Check if u is in subtree of v (to avoid cycles)\n                int x = u;\n                bool cyc = false;\n                while (x != -1) {\n                    if (x == v) {\n                        cyc = true;\n                        break;\n                    }\n                    x = parent[x];\n                }\n                if (cyc) continue;\n\n                int du = getDepth(u);\n                int newDepth = du + 1;\n                if (newDepth > H) continue;\n                if (newDepth + subHeight[v] > H) continue;\n\n                long long deltaScore = (long long)(newDepth - oldDepth) * subtreeSum[v];\n                if (deltaScore > bestDelta) {\n                    bestDelta = deltaScore;\n                    bestP = u;\n                    bestNewDepth = newDepth;\n                }\n            }\n\n            if (bestP != oldParent && bestDelta > 0) {\n                reparentFn(v, bestP, oldDepth, bestNewDepth);\n                improved = true;\n            }\n        }\n    } while (improved);\n\n    // ---------- Simulated annealing to escape local maxima ----------\n    FastRand rng;\n    // Time budget for SA only; initial phases are extra but cheap.\n    const double TIME_LIMIT = 1.7; // seconds\n    const double T0 = 200000.0;\n    const double T1 = 10.0;\n\n    auto startTime = chrono::steady_clock::now();\n    double T = T0;\n\n    int iter = 0;\n    while (true) {\n        ++iter;\n        if ((iter & 1023) == 0) {\n            double elapsed = chrono::duration<double>(chrono::steady_clock::now() - startTime).count();\n            if (elapsed > TIME_LIMIT) break;\n            double t = elapsed / TIME_LIMIT;\n            if (t > 1.0) t = 1.0;\n            T = T0 + (T1 - T0) * t; // linear cooling\n            if (T < T1) T = T1;\n        }\n\n        int v = rng.nextInt(N);\n        int deg = (int)adj[v].size();\n        if (deg == 0 && parent[v] == -1) continue; // just in case\n\n        // Choose a new parent: one of neighbors or -1 (make root)\n        int choice = rng.nextInt(deg + 1); // 0..deg\n        int newParent = (choice == deg ? -1 : adj[v][choice]);\n\n        if (newParent == parent[v]) continue;\n\n        // Cycle check (only needed if newParent != -1)\n        if (newParent != -1) {\n            int x = newParent;\n            bool cyc = false;\n            while (x != -1) {\n                if (x == v) {\n                    cyc = true;\n                    break;\n                }\n                x = parent[x];\n            }\n            if (cyc) continue;\n        }\n\n        int oldDepth = getDepth(v);\n        int newDepth;\n        if (newParent == -1) {\n            newDepth = 0;\n        } else {\n            int du = getDepth(newParent);\n            newDepth = du + 1;\n        }\n\n        if (newDepth > H) continue;\n        if (newDepth + subHeight[v] > H) continue;\n\n        long long deltaScore = (long long)(newDepth - oldDepth) * subtreeSum[v];\n\n        if (deltaScore >= 0) {\n            reparentFn(v, newParent, oldDepth, newDepth);\n        } else {\n            double prob = exp((double)deltaScore / T);  // deltaScore < 0\n            double r = rng.nextDouble();\n            if (r < prob) {\n                reparentFn(v, newParent, oldDepth, newDepth);\n            }\n        }\n    }\n\n    // ---------- Final greedy hill climb after SA ----------\n    do {\n        improved = false;\n        for (int v : orderDesc) {\n            int oldParent = parent[v];\n            int oldDepth = getDepth(v);\n            long long bestDelta = 0;\n            int bestP = oldParent;\n            int bestNewDepth = oldDepth;\n\n            for (int u : adj[v]) {\n                if (u == oldParent) continue;\n\n                // Check if u is in subtree of v (to avoid cycles)\n                int x = u;\n                bool cyc = false;\n                while (x != -1) {\n                    if (x == v) {\n                        cyc = true;\n                        break;\n                    }\n                    x = parent[x];\n                }\n                if (cyc) continue;\n\n                int du = getDepth(u);\n                int newDepth = du + 1;\n                if (newDepth > H) continue;\n                if (newDepth + subHeight[v] > H) continue;\n\n                long long deltaScore = (long long)(newDepth - oldDepth) * subtreeSum[v];\n                if (deltaScore > bestDelta) {\n                    bestDelta = deltaScore;\n                    bestP = u;\n                    bestNewDepth = newDepth;\n                }\n            }\n\n            if (bestP != oldParent && bestDelta > 0) {\n                reparentFn(v, bestP, oldDepth, bestNewDepth);\n                improved = true;\n            }\n        }\n    } while (improved);\n\n    // ---------- Output best found solution ----------\n    for (int i = 0; i < N; ++i) {\n        if (i) cout << ' ';\n        cout << bestParent[i];\n    }\n    cout << '\\n';\n\n    return 0;\n}","ahc042":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Operation {\n    char dir;      // 'U', 'D', 'L', 'R' : direction of the first half\n    int  p;        // row or column index\n    int  len;      // number of shifts in each direction\n    int  cost;     // 2 * len\n    uint64_t mask; // which Oni are removed by this operation (global Oni indices)\n};\n\nstruct LocOp {\n    int cost;\n    uint64_t mask; // mask over local Oni indices\n    int gidx;      // corresponding global operation index\n};\n\nconst int INF = 1e9;\nconst int DP_THRESH = 16; // max Oni in a component to solve exactly with DP\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    if (!(cin >> N)) return 0;\n    vector<string> C(N);\n    for (int i = 0; i < N; ++i) cin >> C[i];\n\n    // Collect Oni and Fuku positions\n    vector<pair<int,int>> oni;  // (row,col) for each Oni\n    vector<vector<int>> oni_id(N, vector<int>(N, -1));\n    vector<vector<bool>> fuku(N, vector<bool>(N, false));\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            char ch = C[i][j];\n            if (ch == 'x') {\n                int id = (int)oni.size();\n                oni.emplace_back(i, j);\n                oni_id[i][j] = id;\n            } else if (ch == 'o') {\n                fuku[i][j] = true;\n            }\n        }\n    }\n\n    int M = (int)oni.size(); // number of Oni, should be 2N\n    if (M == 0) {\n        // No Oni: nothing to do\n        return 0;\n    }\n\n    // Prefix sums of Fuku for rows and columns\n    vector<vector<int>> row_pref(N, vector<int>(N, 0));\n    vector<vector<int>> col_pref(N, vector<int>(N, 0));\n\n    for (int i = 0; i < N; ++i) {\n        int acc = 0;\n        for (int j = 0; j < N; ++j) {\n            if (fuku[i][j]) acc++;\n            row_pref[i][j] = acc;\n        }\n    }\n    for (int j = 0; j < N; ++j) {\n        int acc = 0;\n        for (int i = 0; i < N; ++i) {\n            if (fuku[i][j]) acc++;\n            col_pref[j][i] = acc;\n        }\n    }\n\n    vector<Operation> ops;\n    ops.reserve(4 * N * N);\n\n    // Build all safe column operations\n    for (int j = 0; j < N; ++j) {\n        int total_fuku_col = col_pref[j][N-1];\n\n        // Up-prefix [0..h]\n        for (int h = 0; h < N; ++h) {\n            if (col_pref[j][h] == 0) { // no Fuku in [0..h]\n                uint64_t mask = 0;\n                for (int id = 0; id < M; ++id) {\n                    auto [r, c] = oni[id];\n                    if (c == j && r <= h) {\n                        mask |= (1ULL << id);\n                    }\n                }\n                if (mask) {\n                    int len = h + 1;\n                    Operation op;\n                    op.dir = 'U';\n                    op.p = j;\n                    op.len = len;\n                    op.cost = 2 * len;\n                    op.mask = mask;\n                    ops.push_back(op);\n                }\n            }\n        }\n\n        // Down-suffix [h..N-1]\n        for (int h = 0; h < N; ++h) {\n            int fuku_cnt = total_fuku_col - (h > 0 ? col_pref[j][h-1] : 0);\n            if (fuku_cnt == 0) { // no Fuku in [h..N-1]\n                uint64_t mask = 0;\n                for (int id = 0; id < M; ++id) {\n                    auto [r, c] = oni[id];\n                    if (c == j && r >= h) {\n                        mask |= (1ULL << id);\n                    }\n                }\n                if (mask) {\n                    int len = N - h;\n                    Operation op;\n                    op.dir = 'D';\n                    op.p = j;\n                    op.len = len;\n                    op.cost = 2 * len;\n                    op.mask = mask;\n                    ops.push_back(op);\n                }\n            }\n        }\n    }\n\n    // Build all safe row operations\n    for (int i = 0; i < N; ++i) {\n        int total_fuku_row = row_pref[i][N-1];\n\n        // Left-prefix [0..h]\n        for (int h = 0; h < N; ++h) {\n            if (row_pref[i][h] == 0) { // no Fuku in [0..h]\n                uint64_t mask = 0;\n                for (int id = 0; id < M; ++id) {\n                    auto [r, c] = oni[id];\n                    if (r == i && c <= h) {\n                        mask |= (1ULL << id);\n                    }\n                }\n                if (mask) {\n                    int len = h + 1;\n                    Operation op;\n                    op.dir = 'L';\n                    op.p = i;\n                    op.len = len;\n                    op.cost = 2 * len;\n                    op.mask = mask;\n                    ops.push_back(op);\n                }\n            }\n        }\n\n        // Right-suffix [h..N-1]\n        for (int h = 0; h < N; ++h) {\n            int fuku_cnt = total_fuku_row - (h > 0 ? row_pref[i][h-1] : 0);\n            if (fuku_cnt == 0) { // no Fuku in [h..N-1]\n                uint64_t mask = 0;\n                for (int id = 0; id < M; ++id) {\n                    auto [r, c] = oni[id];\n                    if (r == i && c >= h) {\n                        mask |= (1ULL << id);\n                    }\n                }\n                if (mask) {\n                    int len = N - h;\n                    Operation op;\n                    op.dir = 'R';\n                    op.p = i;\n                    op.len = len;\n                    op.cost = 2 * len;\n                    op.mask = mask;\n                    ops.push_back(op);\n                }\n            }\n        }\n    }\n\n    if (ops.empty()) {\n        // Should not happen due to guarantees\n        return 0;\n    }\n\n    // Deduplicate operations by identical mask, keeping the cheapest one\n    sort(ops.begin(), ops.end(), [](const Operation &a, const Operation &b) {\n        if (a.mask != b.mask) return a.mask < b.mask;\n        if (a.cost != b.cost) return a.cost < b.cost;\n        if (a.dir != b.dir)   return a.dir < b.dir;\n        if (a.p != b.p)       return a.p < b.p;\n        return a.len < b.len;\n    });\n\n    {\n        vector<Operation> filtered;\n        filtered.reserve(ops.size());\n        for (int i = 0; i < (int)ops.size(); ) {\n            int j = i + 1;\n            Operation best = ops[i];\n            while (j < (int)ops.size() && ops[j].mask == ops[i].mask) {\n                if (ops[j].cost < best.cost) best = ops[j];\n                ++j;\n            }\n            filtered.push_back(best);\n            i = j;\n        }\n        ops.swap(filtered);\n    }\n\n    // Dominated-set elimination: remove op_j if its mask is subset of op_i and cost_j >= cost_i\n    sort(ops.begin(), ops.end(), [](const Operation &a, const Operation &b) {\n        if (a.cost != b.cost) return a.cost < b.cost;\n        return a.mask < b.mask;\n    });\n\n    {\n        int K = (int)ops.size();\n        vector<bool> alive(K, true);\n        for (int i = 0; i < K; ++i) {\n            if (!alive[i]) continue;\n            uint64_t mi = ops[i].mask;\n            for (int j = i + 1; j < K; ++j) {\n                if (!alive[j]) continue;\n                uint64_t mj = ops[j].mask;\n                if ((mj & ~mi) == 0ULL) {\n                    // mj is subset of mi with cost_j >= cost_i => dominated\n                    alive[j] = false;\n                }\n            }\n        }\n        vector<Operation> filtered;\n        filtered.reserve(K);\n        for (int i = 0; i < K; ++i) if (alive[i]) filtered.push_back(ops[i]);\n        ops.swap(filtered);\n    }\n\n    int K_ops = (int)ops.size();\n    if (K_ops == 0) return 0;\n\n    // Build cover lists: for each Oni, which operations cover it\n    vector<vector<int>> cover_ops(M);\n    for (int idx = 0; idx < K_ops; ++idx) {\n        uint64_t m = ops[idx].mask;\n        while (m) {\n            int b = __builtin_ctzll(m);\n            m &= m - 1;\n            cover_ops[b].push_back(idx);\n        }\n    }\n\n    // Each Oni must be coverable\n    for (int i = 0; i < M; ++i) {\n        if (cover_ops[i].empty()) {\n            // Should not happen\n            return 0;\n        }\n    }\n\n    uint64_t all_mask = (M == 64) ? ~0ULL : ((1ULL << M) - 1);\n\n    // Build connected components on bipartite graph (Oni and Ops)\n    vector<int> oni_comp(M, -1);\n    vector<int> op_comp(K_ops, -1);\n    int comp_cnt = 0;\n    for (int i = 0; i < M; ++i) {\n        if (oni_comp[i] != -1) continue;\n        // BFS\n        queue<int> q;\n        oni_comp[i] = comp_cnt;\n        q.push(i); // Oni node: 0..M-1; Ops: M..M+K_ops-1\n        while (!q.empty()) {\n            int v = q.front();\n            q.pop();\n            if (v < M) {\n                // Oni node\n                int o = v;\n                for (int op_idx : cover_ops[o]) {\n                    if (op_comp[op_idx] == -1) {\n                        op_comp[op_idx] = comp_cnt;\n                        q.push(M + op_idx);\n                    }\n                }\n            } else {\n                // Operation node\n                int op_idx = v - M;\n                uint64_t m = ops[op_idx].mask;\n                while (m) {\n                    int b = __builtin_ctzll(m);\n                    m &= m - 1;\n                    if (oni_comp[b] == -1) {\n                        oni_comp[b] = comp_cnt;\n                        q.push(b);\n                    }\n                }\n            }\n        }\n        ++comp_cnt;\n    }\n\n    vector<vector<int>> comp_oni(comp_cnt), comp_ops(comp_cnt);\n    for (int i = 0; i < M; ++i) {\n        comp_oni[oni_comp[i]].push_back(i);\n    }\n    for (int k = 0; k < K_ops; ++k) {\n        comp_ops[op_comp[k]].push_back(k);\n    }\n\n    // Global solution: selected global operation indices\n    vector<bool> global_selected(K_ops, false);\n\n    // RNG\n    uint64_t seed = chrono::steady_clock::now().time_since_epoch().count();\n    mt19937_64 rng(seed);\n\n    // Helper: exact DP solver for one component (nO <= DP_THRESH)\n    auto solve_component_dp = [&](int nO, const vector<int> &oniList, const vector<int> &opsList) -> vector<int> {\n        // Map global Oni index -> local index\n        vector<int> g2l(M, -1);\n        for (int i = 0; i < nO; ++i) {\n            g2l[oniList[i]] = i;\n        }\n\n        vector<LocOp> locOps;\n        locOps.reserve(opsList.size());\n        for (int gidx : opsList) {\n            uint64_t gm = ops[gidx].mask;\n            uint64_t lm = 0;\n            uint64_t tmp = gm;\n            while (tmp) {\n                int b = __builtin_ctzll(tmp);\n                tmp &= tmp - 1;\n                int li = g2l[b];\n                if (li >= 0) lm |= (1ULL << li);\n            }\n            if (lm) {\n                LocOp lo{ops[gidx].cost, lm, gidx};\n                locOps.push_back(lo);\n            }\n        }\n\n        int Kc = (int)locOps.size();\n        if (Kc == 0) {\n            // Should not happen, but return empty\n            return {};\n        }\n\n        int FULL = (1 << nO) - 1;\n        int SZ = 1 << nO;\n        vector<int> dp(SZ, INF), prev_state(SZ, -1), prev_op(SZ, -1);\n        dp[0] = 0;\n\n        for (int s = 0; s < SZ; ++s) {\n            if (dp[s] == INF) continue;\n            int base = dp[s];\n            for (int j = 0; j < Kc; ++j) {\n                uint64_t nm = s | locOps[j].mask;\n                int ns = (int)nm;\n                int nc = base + locOps[j].cost;\n                if (nc < dp[ns]) {\n                    dp[ns] = nc;\n                    prev_state[ns] = s;\n                    prev_op[ns] = j;\n                }\n            }\n        }\n\n        if (dp[FULL] == INF) {\n            // Fallback (should not happen)\n            return {};\n        }\n\n        vector<int> chosen_loc;\n        int cur = FULL;\n        while (cur != 0) {\n            int po = prev_op[cur];\n            if (po < 0) break;\n            chosen_loc.push_back(po);\n            cur = prev_state[cur];\n        }\n\n        // Remove duplicates (just in case), and map to global indices\n        vector<bool> used_loc(Kc, false);\n        vector<int> chosen_glob;\n        chosen_glob.reserve(chosen_loc.size());\n        for (int idx : chosen_loc) {\n            if (!used_loc[idx]) {\n                used_loc[idx] = true;\n                chosen_glob.push_back(locOps[idx].gidx);\n            }\n        }\n        return chosen_glob;\n    };\n\n    // For heuristic solver per component (nO > DP_THRESH)\n    auto solve_component_heuristic = [&](int nO, const vector<int> &oniList, const vector<int> &opsList) -> vector<int> {\n        vector<int> g2l(M, -1);\n        for (int i = 0; i < nO; ++i) {\n            g2l[oniList[i]] = i;\n        }\n\n        vector<LocOp> locOps;\n        locOps.reserve(opsList.size());\n        for (int gidx : opsList) {\n            uint64_t gm = ops[gidx].mask;\n            uint64_t lm = 0;\n            uint64_t tmp = gm;\n            while (tmp) {\n                int b = __builtin_ctzll(tmp);\n                tmp &= tmp - 1;\n                int li = g2l[b];\n                if (li >= 0) lm |= (1ULL << li);\n            }\n            if (lm) {\n                LocOp lo{ops[gidx].cost, lm, gidx};\n                locOps.push_back(lo);\n            }\n        }\n\n        int Kc = (int)locOps.size();\n        if (Kc == 0) {\n            // Fallback: nothing\n            return {};\n        }\n\n        // Build cover list for local Oni\n        vector<vector<int>> cover_ops_loc(nO);\n        for (int idx = 0; idx < Kc; ++idx) {\n            uint64_t m = locOps[idx].mask;\n            while (m) {\n                int b = __builtin_ctzll(m);\n                m &= m - 1;\n                cover_ops_loc[b].push_back(idx);\n            }\n        }\n        // If any Oni isn't covered, something's wrong, but skip check.\n\n        // Weights: rarer Oni have higher weight\n        vector<double> oni_weight(nO);\n        for (int i = 0; i < nO; ++i) {\n            int deg = (int)cover_ops_loc[i].size();\n            oni_weight[i] = (deg > 0 ? 1.0 / deg : 1.0);\n        }\n\n        uint64_t FULL = (nO == 64 ? ~0ULL : ((1ULL << nO) - 1));\n\n        // Helper: prune redundant selected operations\n        auto prune_selected = [&](vector<bool> &selected, int &total_cost, vector<int> &cover_count) {\n            bool changed = true;\n            while (changed) {\n                changed = false;\n                uint64_t singular_mask = 0;\n                for (int i = 0; i < nO; ++i) {\n                    if (cover_count[i] == 1) singular_mask |= (1ULL << i);\n                }\n                for (int op_idx = 0; op_idx < Kc; ++op_idx) {\n                    if (!selected[op_idx]) continue;\n                    if ((locOps[op_idx].mask & singular_mask) == 0) {\n                        // Removing this op won't uncover any Oni\n                        selected[op_idx] = false;\n                        total_cost -= locOps[op_idx].cost;\n                        uint64_t m = locOps[op_idx].mask;\n                        while (m) {\n                            int b = __builtin_ctzll(m);\n                            m &= m - 1;\n                            cover_count[b]--;\n                        }\n                        changed = true;\n                    }\n                }\n            }\n        };\n\n        // Local search on a solution (list of local op indices)\n        auto local_search = [&](vector<int> &sel, int &cost) {\n            vector<bool> selected(Kc, false);\n            vector<int> cover_count(nO, 0);\n            int total_cost = 0;\n\n            for (int idx : sel) {\n                if (!selected[idx]) {\n                    selected[idx] = true;\n                    total_cost += locOps[idx].cost;\n                    uint64_t m = locOps[idx].mask;\n                    while (m) {\n                        int b = __builtin_ctzll(m);\n                        m &= m - 1;\n                        cover_count[b]++;\n                    }\n                }\n            }\n\n            prune_selected(selected, total_cost, cover_count);\n\n            for (int i = 0; i < nO; ++i) {\n                if (cover_count[i] == 0) {\n                    return;\n                }\n            }\n\n            vector<int> mark(Kc, 0);\n            int currentMark = 1;\n            vector<int> cand;\n            cand.reserve(64);\n\n            bool improved = true;\n            while (improved) {\n                improved = false;\n\n                uint64_t singular_mask = 0;\n                for (int i = 0; i < nO; ++i) {\n                    if (cover_count[i] == 1) singular_mask |= (1ULL << i);\n                }\n\n                // 1-for-1 replacements\n                for (int a = 0; a < Kc && !improved; ++a) {\n                    if (!selected[a]) continue;\n                    uint64_t U_mask = locOps[a].mask & singular_mask;\n                    if (!U_mask) continue;\n\n                    cand.clear();\n                    if (++currentMark == INT_MAX) {\n                        fill(mark.begin(), mark.end(), 0);\n                        currentMark = 1;\n                    }\n                    uint64_t tmp = U_mask;\n                    while (tmp) {\n                        int b = __builtin_ctzll(tmp);\n                        tmp &= tmp - 1;\n                        for (int op_idx : cover_ops_loc[b]) {\n                            if (mark[op_idx] != currentMark) {\n                                mark[op_idx] = currentMark;\n                                cand.push_back(op_idx);\n                            }\n                        }\n                    }\n\n                    for (int b_idx : cand) {\n                        if (selected[b_idx]) continue;\n                        if (locOps[b_idx].cost >= locOps[a].cost) continue;\n                        if ((locOps[b_idx].mask & U_mask) == U_mask) {\n                            // 1-for-1: a -> b_idx\n                            selected[a] = false;\n                            selected[b_idx] = true;\n                            total_cost += locOps[b_idx].cost - locOps[a].cost;\n\n                            uint64_t ma = locOps[a].mask;\n                            while (ma) {\n                                int bit = __builtin_ctzll(ma);\n                                ma &= ma - 1;\n                                cover_count[bit]--;\n                            }\n                            uint64_t mb = locOps[b_idx].mask;\n                            while (mb) {\n                                int bit = __builtin_ctzll(mb);\n                                mb &= mb - 1;\n                                cover_count[bit]++;\n                            }\n\n                            prune_selected(selected, total_cost, cover_count);\n                            improved = true;\n                            break;\n                        }\n                    }\n                }\n\n                if (improved) continue;\n\n                // 1-for-2 replacements\n                singular_mask = 0;\n                for (int i = 0; i < nO; ++i) {\n                    if (cover_count[i] == 1) singular_mask |= (1ULL << i);\n                }\n\n                for (int a = 0; a < Kc && !improved; ++a) {\n                    if (!selected[a]) continue;\n                    uint64_t U_mask = locOps[a].mask & singular_mask;\n                    if (!U_mask) continue;\n\n                    cand.clear();\n                    if (++currentMark == INT_MAX) {\n                        fill(mark.begin(), mark.end(), 0);\n                        currentMark = 1;\n                    }\n                    uint64_t tmp = U_mask;\n                    while (tmp) {\n                        int b = __builtin_ctzll(tmp);\n                        tmp &= tmp - 1;\n                        for (int op_idx : cover_ops_loc[b]) {\n                            if (mark[op_idx] != currentMark) {\n                                mark[op_idx] = currentMark;\n                                cand.push_back(op_idx);\n                            }\n                        }\n                    }\n\n                    int csz = (int)cand.size();\n                    for (int i1 = 0; i1 < csz && !improved; ++i1) {\n                        int b_idx = cand[i1];\n                        if (selected[b_idx]) continue;\n                        for (int i2 = i1 + 1; i2 < csz; ++i2) {\n                            int c_idx = cand[i2];\n                            if (selected[c_idx]) continue;\n                            int newCost = locOps[b_idx].cost + locOps[c_idx].cost;\n                            if (newCost >= locOps[a].cost) continue;\n                            uint64_t union_mask = locOps[b_idx].mask | locOps[c_idx].mask;\n                            if ((union_mask & U_mask) == U_mask) {\n                                // 1-for-2: a -> b_idx, c_idx\n                                selected[a] = false;\n                                selected[b_idx] = true;\n                                selected[c_idx] = true;\n                                total_cost += newCost - locOps[a].cost;\n\n                                uint64_t ma = locOps[a].mask;\n                                while (ma) {\n                                    int bit = __builtin_ctzll(ma);\n                                    ma &= ma - 1;\n                                    cover_count[bit]--;\n                                }\n                                uint64_t mb = locOps[b_idx].mask;\n                                while (mb) {\n                                    int bit = __builtin_ctzll(mb);\n                                    mb &= mb - 1;\n                                    cover_count[bit]++;\n                                }\n                                uint64_t mc = locOps[c_idx].mask;\n                                while (mc) {\n                                    int bit = __builtin_ctzll(mc);\n                                    mc &= mc - 1;\n                                    cover_count[bit]++;\n                                }\n\n                                prune_selected(selected, total_cost, cover_count);\n                                improved = true;\n                                break;\n                            }\n                        }\n                    }\n                }\n            }\n\n            for (int i = 0; i < nO; ++i) {\n                if (cover_count[i] == 0) return;\n            }\n\n            vector<int> new_sel;\n            new_sel.reserve(nO);\n            for (int i = 0; i < Kc; ++i) if (selected[i]) new_sel.push_back(i);\n            sel.swap(new_sel);\n            cost = total_cost;\n        };\n\n        auto run_greedy = [&](int score_type, int RCL_SIZE) -> pair<int, vector<int>> {\n            uint64_t uncovered = FULL;\n            vector<int> chosen;\n            chosen.reserve(nO);\n            int greedy_cost = 0;\n\n            while (uncovered) {\n                vector<double> bestRatios(RCL_SIZE, -1.0);\n                vector<int> bestIdx(RCL_SIZE, -1);\n\n                for (int i = 0; i < Kc; ++i) {\n                    uint64_t gainMask = locOps[i].mask & uncovered;\n                    if (!gainMask) continue;\n\n                    int nGain = __builtin_popcountll(gainMask);\n                    double wGain = 0.0;\n                    uint64_t tmp = gainMask;\n                    while (tmp) {\n                        int b = __builtin_ctzll(tmp);\n                        tmp &= tmp - 1;\n                        wGain += oni_weight[b];\n                    }\n\n                    double ratio;\n                    switch (score_type) {\n                        case 0: // weighted gain / cost\n                            ratio = wGain / (double)locOps[i].cost;\n                            break;\n                        case 1: // raw gain / cost\n                            ratio = (double)nGain / (double)locOps[i].cost;\n                            break;\n                        case 2: // gain / sqrt(cost)\n                            ratio = (double)nGain / sqrt((double)locOps[i].cost);\n                            break;\n                        case 3: // (weighted gain)^2 / cost\n                        default:\n                            ratio = (wGain * wGain) / (double)locOps[i].cost;\n                            break;\n                    }\n\n                    for (int k = 0; k < RCL_SIZE; ++k) {\n                        if (ratio > bestRatios[k]) {\n                            for (int sh = RCL_SIZE - 1; sh > k; --sh) {\n                                bestRatios[sh] = bestRatios[sh - 1];\n                                bestIdx[sh] = bestIdx[sh - 1];\n                            }\n                            bestRatios[k] = ratio;\n                            bestIdx[k] = i;\n                            break;\n                        }\n                    }\n                }\n\n                if (bestIdx[0] == -1) {\n                    break; // should not\n                }\n\n                int rcl_end = 0;\n                while (rcl_end + 1 < RCL_SIZE && bestIdx[rcl_end + 1] != -1) ++rcl_end;\n                uniform_int_distribution<int> dist(0, rcl_end);\n                int chosen_pos = dist(rng);\n                int op_idx = bestIdx[chosen_pos];\n\n                chosen.push_back(op_idx);\n                uint64_t gainMask = locOps[op_idx].mask & uncovered;\n                uncovered &= ~gainMask;\n                greedy_cost += locOps[op_idx].cost;\n            }\n\n            if (uncovered) {\n                return make_pair(INF, vector<int>());\n            }\n\n            vector<bool> selected(Kc, false);\n            vector<int> cover_count(nO, 0);\n            int total_cost = 0;\n            for (int idx : chosen) {\n                if (!selected[idx]) {\n                    selected[idx] = true;\n                    total_cost += locOps[idx].cost;\n                    uint64_t m = locOps[idx].mask;\n                    while (m) {\n                        int b = __builtin_ctzll(m);\n                        m &= m - 1;\n                        cover_count[b]++;\n                    }\n                }\n            }\n\n            prune_selected(selected, total_cost, cover_count);\n\n            for (int i = 0; i < nO; ++i) {\n                if (cover_count[i] == 0) return make_pair(INF, vector<int>());\n            }\n\n            vector<int> result;\n            result.reserve(nO);\n            for (int i = 0; i < Kc; ++i) if (selected[i]) result.push_back(i);\n            return make_pair(total_cost, move(result));\n        };\n\n        int best_cost = INF;\n        vector<int> best_sel_loc;\n        const int MAX_RUNS = 80;\n        uniform_int_distribution<int> scoreDist(0, 3);\n        uniform_int_distribution<int> rclDist(2, 5);\n\n        for (int iter = 0; iter < MAX_RUNS; ++iter) {\n            int score_type = scoreDist(rng);\n            int RCL_SIZE = rclDist(rng);\n            auto [cost, sel] = run_greedy(score_type, RCL_SIZE);\n            if (cost >= INF) continue;\n\n            int ls_cost = cost;\n            vector<int> ls_sel = sel;\n            local_search(ls_sel, ls_cost);\n\n            uint64_t covered = 0;\n            for (int idx : ls_sel) covered |= locOps[idx].mask;\n            if (covered != FULL) continue;\n\n            if (ls_cost < best_cost) {\n                best_cost = ls_cost;\n                best_sel_loc = move(ls_sel);\n            }\n        }\n\n        // Fallback: simple greedy if no solution found\n        if (best_sel_loc.empty()) {\n            auto [cost, sel] = run_greedy(1, 1);\n            if (cost < INF) {\n                best_cost = cost;\n                best_sel_loc = move(sel);\n            }\n        }\n\n        // Map to global indices\n        vector<int> res;\n        for (int idx : best_sel_loc) {\n            res.push_back(locOps[idx].gidx);\n        }\n        return res;\n    };\n\n    // Solve each component independently\n    for (int c = 0; c < comp_cnt; ++c) {\n        const auto &oniList = comp_oni[c];\n        const auto &opsList = comp_ops[c];\n        int nO = (int)oniList.size();\n        if (nO == 0 || opsList.empty()) continue;\n\n        vector<int> chosen_global;\n        if (nO <= DP_THRESH) {\n            chosen_global = solve_component_dp(nO, oniList, opsList);\n        } else {\n            chosen_global = solve_component_heuristic(nO, oniList, opsList);\n        }\n\n        for (int gidx : chosen_global) {\n            global_selected[gidx] = true;\n        }\n    }\n\n    // Build move sequence from selected global operations\n    vector<pair<char,int>> moves;\n    moves.reserve(1600);\n\n    for (int idx = 0; idx < K_ops; ++idx) {\n        if (!global_selected[idx]) continue;\n        const Operation &op = ops[idx];\n        char d1 = op.dir;\n        char d2;\n        if      (d1 == 'U') d2 = 'D';\n        else if (d1 == 'D') d2 = 'U';\n        else if (d1 == 'L') d2 = 'R';\n        else               d2 = 'L';\n\n        for (int k = 0; k < op.len; ++k) moves.emplace_back(d1, op.p);\n        for (int k = 0; k < op.len; ++k) moves.emplace_back(d2, op.p);\n    }\n\n    int T = (int)moves.size();\n    if (T > 4 * N * N) {\n        // Should not happen, but be safe.\n        return 0;\n    }\n\n    for (auto &mv : moves) {\n        cout << mv.first << ' ' << mv.second << '\\n';\n    }\n\n    return 0;\n}","ahc044":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const int MAXN = 100;\n\nstruct Candidate {\n    int a[MAXN];\n    int b[MAXN];\n    int t[MAXN];\n    int used[MAXN][2]; // edge usage counts: 0 -> a[i], 1 -> b[i]\n    long long E;\n};\n\n// Rotor-router simulation for L weeks, also records edge usage\nvoid evalCandidate(Candidate &cand, int N, int L, const vector<long long> &T) {\n    static int rotor[MAXN];\n    for (int i = 0; i < N; ++i) {\n        cand.t[i] = 0;\n        rotor[i] = 0;\n        cand.used[i][0] = cand.used[i][1] = 0;\n    }\n\n    int cur = 0;  // week 1 cleaner is 0\n\n    // weeks 1..L-1: decide next cleaner\n    for (int week = 0; week < L - 1; ++week) {\n        int x = cur;\n        cand.t[x]++;\n\n        int e = rotor[x];\n        rotor[x] ^= 1;\n        int nxt = (e == 0 ? cand.a[x] : cand.b[x]);\n        cand.used[x][e]++;\n\n        cur = nxt;\n    }\n    // last week: count the final cleaner\n    cand.t[cur]++;\n\n    long long E = 0;\n    for (int i = 0; i < N; ++i) {\n        E += llabs((long long)cand.t[i] - T[i]);\n    }\n    cand.E = E;\n}\n\n// Majority-based initial candidate from an \"ideal\" sequence\nCandidate buildMajorityCandidate(int N, int L, const vector<long long> &T, mt19937_64 &rng) {\n    Candidate cand;\n\n    // Work copy of T, ensure employee 0 appears at least once\n    vector<int> Twork(N);\n    for (int i = 0; i < N; ++i) Twork[i] = (int)T[i];\n\n    if (Twork[0] == 0) {\n        int j = 1;\n        for (int i = 2; i < N; ++i) {\n            if (Twork[i] > Twork[j]) j = i;\n        }\n        if (Twork[j] > 0) {\n            Twork[0] = 1;\n            Twork[j]--;\n        } else {\n            for (int i = 1; i < N; ++i) {\n                if (Twork[i] > 0) {\n                    Twork[i]--;\n                    break;\n                }\n            }\n            Twork[0] = 1;\n        }\n    }\n\n    // Build sequence of length L with counts Twork\n    vector<int> seq(L);\n    int pos = 0;\n    for (int i = 0; i < N; ++i) {\n        for (int k = 0; k < Twork[i]; ++k) {\n            if (pos < L) seq[pos++] = i;\n        }\n    }\n    if (pos < L) {\n        for (; pos < L; ++pos) seq[pos] = 0;\n    } else if (pos > L) {\n        seq.resize(L);\n    }\n\n    shuffle(seq.begin(), seq.end(), rng);\n\n    // Ensure seq[0] == 0 (week1 cleaner is 0)\n    if (seq[0] != 0) {\n        for (int i = 1; i < L; ++i) {\n            if (seq[i] == 0) {\n                swap(seq[0], seq[i]);\n                break;\n            }\n        }\n        seq[0] = 0; // safety\n    }\n\n    vector<vector<int>> freqOdd(N, vector<int>(N, 0));\n    vector<vector<int>> freqEven(N, vector<int>(N, 0));\n    vector<int> cntVisit(N, 0);\n\n    for (int i = 0; i < L - 1; ++i) {\n        int x = seq[i];\n        int y = seq[i + 1];\n        int k = ++cntVisit[x];\n        if (k & 1) freqOdd[x][y]++;\n        else       freqEven[x][y]++;\n    }\n\n    // Fallback destination: employee with largest T[i]\n    int fallback = 0;\n    for (int i = 1; i < N; ++i) {\n        if (T[i] > T[fallback]) fallback = i;\n    }\n\n    for (int x = 0; x < N; ++x) {\n        int best_j = fallback;\n        int best_c = 0;\n        // a_x from odd visits\n        for (int y = 0; y < N; ++y) {\n            if (freqOdd[x][y] > best_c) {\n                best_c = freqOdd[x][y];\n                best_j = y;\n            }\n        }\n        cand.a[x] = best_j;\n\n        best_j = fallback;\n        best_c = 0;\n        // b_x from even visits\n        for (int y = 0; y < N; ++y) {\n            if (freqEven[x][y] > best_c) {\n                best_c = freqEven[x][y];\n                best_j = y;\n            }\n        }\n        cand.b[x] = best_j;\n    }\n\n    evalCandidate(cand, N, L, T);\n    return cand;\n}\n\n// Build destination template from arbitrary nonnegative weights w[i]\nvector<int> buildDestTemplateFromWeights(const vector<double> &w) {\n    int N = (int)w.size();\n    int totalEdges = 2 * N;\n\n    double sumW = 0.0;\n    for (int i = 0; i < N; ++i) sumW += w[i];\n    if (sumW <= 0.0) {\n        // Fallback: all weights zero -> make uniform\n        vector<int> edgesDest;\n        edgesDest.reserve(totalEdges);\n        for (int i = 0; i < totalEdges; ++i) edgesDest.push_back(i % N);\n        return edgesDest;\n    }\n\n    vector<double> frac(N);\n    vector<int> destCount(N, 0);\n    long long S = 0;\n\n    for (int i = 0; i < N; ++i) {\n        double val = totalEdges * w[i] / sumW;\n        int base = (int)floor(val);\n        destCount[i] = base;\n        frac[i] = val - base;\n        S += base;\n    }\n    int R = totalEdges - (int)S;\n    if (R < 0) R = 0;\n\n    vector<int> ord(N);\n    iota(ord.begin(), ord.end(), 0);\n    sort(ord.begin(), ord.end(), [&](int a, int b) {\n        return frac[a] > frac[b];\n    });\n    for (int k = 0; k < R && k < N; ++k) {\n        destCount[ord[k]]++;\n    }\n\n    vector<int> edgesDest;\n    edgesDest.reserve(totalEdges);\n    for (int i = 0; i < N; ++i) {\n        for (int c = 0; c < destCount[i]; ++c) {\n            edgesDest.push_back(i);\n        }\n    }\n    while ((int)edgesDest.size() > totalEdges) edgesDest.pop_back();\n    while ((int)edgesDest.size() < totalEdges) edgesDest.push_back(0);\n\n    return edgesDest;\n}\n\n// Build a random candidate from a given destination template\nCandidate buildRandomCandidateFromTemplate(const vector<int> &edgesTemplate,\n                                           int N, int L,\n                                           const vector<long long> &T,\n                                           mt19937_64 &rng) {\n    Candidate cand;\n    vector<int> edges = edgesTemplate; // copy\n    shuffle(edges.begin(), edges.end(), rng);\n\n    for (int i = 0; i < N; ++i) {\n        cand.a[i] = edges[2 * i];\n        cand.b[i] = edges[2 * i + 1];\n    }\n    evalCandidate(cand, N, L, T);\n    return cand;\n}\n\n// Greedy static relinking: approximate improvement using current t and used\nvoid greedyRelink(Candidate &cand, int N, const vector<long long> &T) {\n    vector<long long> t(N);\n    for (int i = 0; i < N; ++i) t[i] = cand.t[i];\n\n    struct EdgeInfo {\n        int x;\n        int e; // 0 or 1\n        long long score;\n    };\n    vector<EdgeInfo> edges;\n    edges.reserve(2 * N);\n\n    // Consider edges that send flow into over-visited nodes\n    for (int x = 0; x < N; ++x) {\n        for (int e = 0; e < 2; ++e) {\n            int uses = cand.used[x][e];\n            if (uses <= 0) continue;\n            int y = (e == 0 ? cand.a[x] : cand.b[x]);\n            long long diff = t[y] - T[y]; // over-visit amount\n            if (diff > 0) {\n                long long score = (long long)uses * diff;\n                if (score > 0) edges.push_back({x, e, score});\n            }\n        }\n    }\n\n    if (edges.empty()) return;\n\n    // Process worst edges first\n    sort(edges.begin(), edges.end(), [](const EdgeInfo &a, const EdgeInfo &b) {\n        return a.score > b.score;\n    });\n\n    for (const auto &ed : edges) {\n        int x = ed.x;\n        int e = ed.e;\n        int uses = cand.used[x][e];\n        if (uses <= 0) continue;\n\n        int y = (e == 0 ? cand.a[x] : cand.b[x]);\n        long long ty = t[y];\n        long long Ty = T[y];\n        long long Ey0 = llabs(ty - Ty);\n\n        long long bestDelta = 0;\n        int bestZ = -1;\n\n        for (int z = 0; z < N; ++z) {\n            if (z == y) continue;\n            long long tz = t[z];\n            long long Tz = T[z];\n            long long Ez0 = llabs(tz - Tz);\n\n            long long Ey1 = llabs(ty - uses - Ty);\n            long long Ez1 = llabs(tz + uses - Tz);\n            long long delta = (Ey1 + Ez1) - (Ey0 + Ez0);\n            if (delta < bestDelta) {\n                bestDelta = delta;\n                bestZ = z;\n            }\n        }\n\n        if (bestZ != -1) {\n            if (e == 0) cand.a[x] = bestZ;\n            else        cand.b[x] = bestZ;\n            t[y] -= uses;\n            t[bestZ] += uses;\n        }\n    }\n}\n\n// Random/diversification mutation of one node, guided by deficits\nvoid mutateNode(int idx,\n                Candidate &cand,\n                int N,\n                const vector<int> &deficit,\n                const vector<int> &posIndices,\n                const vector<long long> &posPrefix,\n                long long sumPos,\n                const vector<long long> &Tprefix,\n                long long sumTw,\n                mt19937_64 &rng) {\n    auto samplePos = [&]() -> int {\n        if (sumPos <= 0 || posIndices.empty()) {\n            return (int)(rng() % N);\n        }\n        long long r = (long long)(rng() % sumPos);\n        int pos = int(lower_bound(posPrefix.begin(), posPrefix.end(), r + 1) - posPrefix.begin());\n        if (pos < 0) pos = 0;\n        if (pos >= (int)posIndices.size()) pos = (int)posIndices.size() - 1;\n        return posIndices[pos];\n    };\n\n    auto sampleTdist = [&]() -> int {\n        if (sumTw <= 0) return (int)(rng() % N);\n        long long r = (long long)(rng() % sumTw);\n        int pos = int(upper_bound(Tprefix.begin(), Tprefix.end(), r) - Tprefix.begin());\n        if (pos < 0) pos = 0;\n        if (pos >= N) pos = N - 1;\n        return pos;\n    };\n\n    if (deficit[idx] > 0) {\n        // Node needs more visits: one self-loop and one under-visited target\n        cand.a[idx] = idx;\n        if (sumPos > 0) cand.b[idx] = samplePos();\n        else cand.b[idx] = sampleTdist();\n    } else {\n        // Node has enough or too many visits: redirect outflows to under-visited nodes.\n        if (sumPos > 0) {\n            cand.a[idx] = samplePos();\n            cand.b[idx] = samplePos();\n        } else {\n            cand.a[idx] = sampleTdist();\n            cand.b[idx] = sampleTdist();\n        }\n    }\n\n    if (cand.a[idx] < 0) cand.a[idx] = 0;\n    if (cand.a[idx] >= N) cand.a[idx] = N - 1;\n    if (cand.b[idx] < 0) cand.b[idx] = 0;\n    if (cand.b[idx] >= N) cand.b[idx] = N - 1;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, L;\n    if (!(cin >> N >> L)) {\n        return 0;\n    }\n    vector<long long> T(N);\n    for (int i = 0; i < N; ++i) cin >> T[i];\n\n    mt19937_64 rng(123456789ULL);\n\n    auto startTime = chrono::steady_clock::now();\n    const int TIME_LIMIT_MS = 1900; // safety margin\n\n    // Build multiple destination templates with different weightings\n    vector<double> w_lin(N), w_lin0(N), w_sqrt(N);\n    for (int i = 0; i < N; ++i) {\n        w_lin[i]  = (double)T[i] + 1.0;\n        w_lin0[i] = (double)T[i];            // no \"+1\", so zero targets may get no indegree\n        w_sqrt[i] = sqrt((double)T[i] + 1.0);\n    }\n\n    vector<vector<int>> destTemplates;\n    destTemplates.reserve(3);\n    destTemplates.push_back(buildDestTemplateFromWeights(w_lin));\n    destTemplates.push_back(buildDestTemplateFromWeights(w_lin0));\n    destTemplates.push_back(buildDestTemplateFromWeights(w_sqrt));\n\n    Candidate best;\n    bool bestInitialized = false;\n\n    // A few majority-based candidates\n    const int NUM_MAJ = 2;\n    for (int i = 0; i < NUM_MAJ; ++i) {\n        Candidate c = buildMajorityCandidate(N, L, T, rng);\n        if (!bestInitialized || c.E < best.E) {\n            best = c;\n            bestInitialized = true;\n        }\n    }\n\n    // Random candidates from each destination template\n    const int INIT_RANDOM_PER_TEMPLATE = 10; // total ~30\n    for (auto &templ : destTemplates) {\n        for (int k = 0; k < INIT_RANDOM_PER_TEMPLATE; ++k) {\n            Candidate c = buildRandomCandidateFromTemplate(templ, N, L, T, rng);\n            if (!bestInitialized || c.E < best.E) {\n                best = c;\n                bestInitialized = true;\n            }\n        }\n    }\n\n    // Greedy static relinking on best initial candidate\n    {\n        Candidate cand = best;\n        greedyRelink(cand, N, T);\n        evalCandidate(cand, N, L, T);\n        if (cand.E < best.E) best = cand;\n    }\n\n    // Precompute T-weighted distribution for fallback sampling in local search\n    vector<long long> Tprefix(N);\n    long long sumTw = 0;\n    for (int i = 0; i < N; ++i) {\n        sumTw += (long long)T[i] + 1;\n        Tprefix[i] = sumTw;\n    }\n\n    // Local search: deficits and positive-deficit distribution\n    vector<int> deficit(N);\n    for (int i = 0; i < N; ++i) {\n        deficit[i] = (int)(T[i] - best.t[i]);\n    }\n\n    vector<int> posIndices;\n    vector<long long> posPrefix;\n    long long sumPos = 0;\n\n    auto updatePosDist = [&]() {\n        posIndices.clear();\n        posPrefix.clear();\n        sumPos = 0;\n        for (int i = 0; i < N; ++i) {\n            if (deficit[i] > 0) {\n                posIndices.push_back(i);\n                sumPos += deficit[i];\n                posPrefix.push_back(sumPos);\n            }\n        }\n    };\n    updatePosDist();\n\n    const int LOCAL_ITER_MAX = 1000000000; // effectively infinite; time limit stops us\n\n    for (int iter = 0; iter < LOCAL_ITER_MAX; ++iter) {\n        if ((iter & 7) == 0) {\n            auto now = chrono::steady_clock::now();\n            long long elapsed = chrono::duration_cast<chrono::milliseconds>(now - startTime).count();\n            if (elapsed > TIME_LIMIT_MS) break;\n        }\n\n        Candidate cand = best;  // copy from best\n\n        int numMut = 1;\n        if (iter > 200) numMut = 2;\n        if (iter > 800) numMut = 3;\n\n        auto samplePos = [&]() -> int {\n            if (sumPos <= 0 || posIndices.empty()) {\n                return (int)(rng() % N);\n            }\n            long long r = (long long)(rng() % sumPos);\n            int pos = int(lower_bound(posPrefix.begin(), posPrefix.end(), r + 1) - posPrefix.begin());\n            if (pos < 0) pos = 0;\n            if (pos >= (int)posIndices.size()) pos = (int)posIndices.size() - 1;\n            return posIndices[pos];\n        };\n\n        auto sampleTdist = [&]() -> int {\n            if (sumTw <= 0) return (int)(rng() % N);\n            long long r = (long long)(rng() % sumTw);\n            int pos = int(upper_bound(Tprefix.begin(), Tprefix.end(), r) - Tprefix.begin());\n            if (pos < 0) pos = 0;\n            if (pos >= N) pos = N - 1;\n            return pos;\n        };\n\n        bool usedTargeted = false;\n        bool canTarget = (!posIndices.empty());\n        bool doTargeted = canTarget && (iter % 3 != 2); // ~2/3 of iterations use targeted\n\n        if (doTargeted) {\n            struct EdgeInfo {\n                int x;\n                int e; // 0 or 1\n                long long score;\n            };\n            vector<EdgeInfo> edges;\n            edges.reserve(2 * N);\n\n            // Build list of \"bad\" edges: many uses into over-visited nodes\n            for (int x = 0; x < N; ++x) {\n                for (int e = 0; e < 2; ++e) {\n                    int uses = best.used[x][e];\n                    if (uses <= 0) continue;\n                    int child = (e == 0 ? best.a[x] : best.b[x]);\n                    if (deficit[child] < 0) {\n                        long long score = (long long)uses * (long long)(-deficit[child]);\n                        edges.push_back({x, e, score});\n                    }\n                }\n            }\n\n            if (!edges.empty() && sumPos > 0) {\n                sort(edges.begin(), edges.end(),\n                     [](const EdgeInfo &p, const EdgeInfo &q) {\n                         return p.score > q.score;\n                     });\n\n                int Ktop = (int)edges.size();\n                if (Ktop > 20) Ktop = 20; // focus on top edges\n\n                for (int m = 0; m < numMut && m < Ktop; ++m) {\n                    int x = edges[m].x;\n                    int e = edges[m].e;\n\n                    int oldChild = (e == 0 ? cand.a[x] : cand.b[x]);\n                    int newChild = oldChild;\n\n                    int tries = 0;\n                    while (tries < 5) {\n                        newChild = samplePos();\n                        if (newChild != oldChild) break;\n                        ++tries;\n                    }\n                    if (newChild == oldChild) {\n                        newChild = samplePos();\n                    }\n\n                    if (newChild < 0) newChild = 0;\n                    if (newChild >= N) newChild = N - 1;\n\n                    if (e == 0) cand.a[x] = newChild;\n                    else        cand.b[x] = newChild;\n                }\n                usedTargeted = true;\n            }\n        }\n\n        if (!usedTargeted) {\n            // Fallback / diversification: random node-based mutation\n            for (int k = 0; k < numMut; ++k) {\n                int idx = (int)(rng() % N);\n                mutateNode(idx, cand, N, deficit,\n                           posIndices, posPrefix, sumPos,\n                           Tprefix, sumTw, rng);\n            }\n        }\n\n        evalCandidate(cand, N, L, T);\n\n        if (cand.E < best.E) {\n            best = cand;\n            for (int i = 0; i < N; ++i) {\n                deficit[i] = (int)(T[i] - best.t[i]);\n            }\n            updatePosDist();\n        }\n    }\n\n    // Final greedy relinking on the best candidate (cheap and can only help)\n    {\n        Candidate cand = best;\n        greedyRelink(cand, N, T);\n        evalCandidate(cand, N, L, T);\n        if (cand.E < best.E) best = cand;\n    }\n\n    // Output best found a_i, b_i\n    for (int i = 0; i < N; ++i) {\n        int ai = best.a[i];\n        int bi = best.b[i];\n        if (ai < 0) ai = 0;\n        if (ai >= N) ai = N - 1;\n        if (bi < 0) bi = 0;\n        if (bi >= N) bi = N - 1;\n        cout << ai << ' ' << bi << '\\n';\n    }\n\n    return 0;\n}","ahc045":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int MAXN = 800;\n\nint N, M, Q, L, W;\nint G_in[400];                 // original group sizes\nint lx[MAXN], rx[MAXN], ly[MAXN], ry[MAXN];\nint cx[MAXN], cy[MAXN];        // centers\nint baseDist[MAXN][MAXN];      // squared approx distances\nuint8_t goodCnt[MAXN][MAXN];   // how many times edge appears in query-MST\n\nint B_bias = 0;                // bias in squared-distance units for MST selection\nint CROSS_PEN = 0;             // penalty in sqrt-distance units for cutting a good edge\n\n// List of unique \"good\" edges found from queries\nvector<pair<int,int>> goodEdges;\n\n// Hilbert order of (x, y) with coordinates in [0, 2^pow_bits)\nstatic uint64_t hilbert_order(int x, int y, int pow_bits) {\n    uint64_t res = 0;\n    for (int s = pow_bits - 1; s >= 0; --s) {\n        int rx = (x >> s) & 1;\n        int ry = (y >> s) & 1;\n        res <<= 2;\n        res |= (uint64_t)((rx * 3) ^ ry);\n        if (ry == 0) {\n            if (rx == 1) {\n                x = ((1 << pow_bits) - 1) - x;\n                y = ((1 << pow_bits) - 1) - y;\n            }\n            std::swap(x, y);\n        }\n    }\n    return res;\n}\n\n// Build MST for one group using Prim with adjusted weights for selection only.\n// Edges are recorded in edgesOut; cost is NOT accumulated here.\nvoid buildMSTForGroup(const vector<int> &nodes,\n                      vector<pair<int,int>> &edgesOut) {\n    int m = (int)nodes.size();\n    if (m <= 1) return;\n\n    const int INF = 1000000007;\n    edgesOut.clear();\n    edgesOut.reserve(max(0, m - 1));\n\n    static int best[MAXN];\n    static int parentIdx[MAXN];\n    static bool used[MAXN];\n\n    for (int i = 0; i < m; ++i) {\n        best[i] = INF;\n        parentIdx[i] = -1;\n        used[i] = false;\n    }\n\n    int root = 0;\n    used[root] = true;\n    // Initialize distances from root\n    for (int j = 1; j < m; ++j) {\n        int u = nodes[root];\n        int v = nodes[j];\n        int w = baseDist[u][v];\n        if (B_bias > 0) {\n            uint8_t cnt = goodCnt[u][v];\n            if (cnt) {\n                int cnti = (int)cnt;\n                if (cnti > 3) cnti = 3;\n                int sub = B_bias * cnti;\n                w = max(0, w - sub);\n            }\n        }\n        best[j] = w;\n        parentIdx[j] = root;\n    }\n\n    for (int it = 1; it < m; ++it) {\n        int t = -1;\n        int val = INF;\n        for (int i = 0; i < m; ++i) {\n            if (!used[i] && best[i] < val) {\n                val = best[i];\n                t = i;\n            }\n        }\n        if (t == -1) break; // should not happen\n\n        used[t] = true;\n        int u = nodes[t];\n        int pIdx = parentIdx[t];\n        if (pIdx != -1) {\n            int v = nodes[pIdx];\n            edgesOut.emplace_back(u, v);\n        }\n\n        // Update distances using new node t\n        for (int i = 0; i < m; ++i) {\n            if (!used[i]) {\n                int uu = u;\n                int vv = nodes[i];\n                int w = baseDist[uu][vv];\n                if (B_bias > 0) {\n                    uint8_t cnt = goodCnt[uu][vv];\n                    if (cnt) {\n                        int cnti = (int)cnt;\n                        if (cnti > 3) cnti = 3;\n                        int sub = B_bias * cnti;\n                        w = max(0, w - sub);\n                    }\n                }\n                if (w < best[i]) {\n                    best[i] = w;\n                    parentIdx[i] = t;\n                }\n            }\n        }\n    }\n}\n\nstruct Candidate {\n    vector<vector<int>> groups;\n    vector<vector<pair<int,int>>> edges;\n    long long cost; // approximate cost in sqrt-distance units + penalties\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    if (!(cin >> N >> M >> Q >> L >> W)) {\n        return 0;\n    }\n    for (int i = 0; i < M; ++i) cin >> G_in[i];\n    for (int i = 0; i < N; ++i) {\n        cin >> lx[i] >> rx[i] >> ly[i] >> ry[i];\n    }\n\n    // Approximate coordinates by centers\n    for (int i = 0; i < N; ++i) {\n        cx[i] = (lx[i] + rx[i]) / 2;\n        cy[i] = (ly[i] + ry[i]) / 2;\n    }\n\n    // Precompute squared distances between all pairs\n    for (int i = 0; i < N; ++i) {\n        baseDist[i][i] = 0;\n        for (int j = i + 1; j < N; ++j) {\n            long dx = (long)cx[i] - (long)cx[j];\n            long dy = (long)cy[i] - (long)cy[j];\n            long v = dx * dx + dy * dy;\n            if (v > INT_MAX) v = INT_MAX;\n            int d = (int)v;\n            baseDist[i][j] = baseDist[j][i] = d;\n        }\n    }\n\n    // Initialize goodCnt to zero\n    for (int i = 0; i < N; ++i) {\n        memset(goodCnt[i], 0, N * sizeof(uint8_t));\n    }\n    goodEdges.clear();\n\n    // Build primary Hilbert order (for queries)\n    const int HILBERT_BITS = 15; // 2^15 = 32768 > 10000\n    vector<pair<uint64_t,int>> hv(N);\n    for (int i = 0; i < N; ++i) {\n        uint64_t h = hilbert_order(cx[i], cy[i], HILBERT_BITS);\n        hv[i] = {h, i};\n    }\n    sort(hv.begin(), hv.end());\n    vector<int> hilbOrder(N);\n    for (int i = 0; i < N; ++i) hilbOrder[i] = hv[i].second;\n\n    // --------- Use queries on overlapping Hilbert windows ---------\n    vector<int> good_dists;            // squared distances of unique good edges\n    good_dists.reserve(Q * L);\n    int qUsed = 0;\n\n    if (Q > 0 && L >= 2 && N > 1) {\n        if (N <= L) {\n            // One query on all cities\n            int len = N;\n            cout << \"? \" << len;\n            vector<int> subset(len);\n            for (int k = 0; k < len; ++k) {\n                subset[k] = hilbOrder[k];\n                cout << ' ' << subset[k];\n            }\n            cout << endl;\n\n            for (int t = 0; t < len - 1; ++t) {\n                int a, b;\n                cin >> a >> b;\n                if (goodCnt[a][b] < 255) {\n                    ++goodCnt[a][b];\n                    ++goodCnt[b][a];\n                    if (goodCnt[a][b] == 1) {\n                        good_dists.push_back(baseDist[a][b]);\n                        goodEdges.emplace_back(a, b);\n                    }\n                }\n            }\n            ++qUsed;\n        } else {\n            int maxQueries = Q;\n            int numerator = (N - L) + (maxQueries - 2);\n            int step = numerator / (maxQueries - 1);\n            if (step < 1) step = 1;\n\n            for (int start = 0; start < N && qUsed < Q; start += step) {\n                int len = min(L, N - start);\n                if (len < 2) break;\n                cout << \"? \" << len;\n                vector<int> subset(len);\n                for (int k = 0; k < len; ++k) {\n                    subset[k] = hilbOrder[start + k];\n                    cout << ' ' << subset[k];\n                }\n                cout << endl;\n\n                for (int t = 0; t < len - 1; ++t) {\n                    int a, b;\n                    cin >> a >> b;\n                    if (goodCnt[a][b] < 255) {\n                        ++goodCnt[a][b];\n                        ++goodCnt[b][a];\n                        if (goodCnt[a][b] == 1) {\n                            good_dists.push_back(baseDist[a][b]);\n                            goodEdges.emplace_back(a, b);\n                        }\n                    }\n                }\n                ++qUsed;\n            }\n        }\n    }\n\n    // Determine biases from collected good edge distances\n    if (!good_dists.empty()) {\n        sort(good_dists.begin(), good_dists.end());\n        int medDist = good_dists[good_dists.size() / 2]; // squared\n        int qIdx = (int)good_dists.size() / 4;           // ~25th percentile\n        int qDist = good_dists[qIdx];\n\n        if (medDist > 0) {\n            B_bias = max(1, medDist / 8); // squared units\n        } else {\n            B_bias = 0;\n        }\n\n        if (qDist > 0) {\n            int qSqrt = (int)floor(sqrt((double)qDist));\n            CROSS_PEN = max(1, qSqrt);   // stronger penalty for very short edges\n        } else {\n            CROSS_PEN = 0;\n        }\n    } else {\n        B_bias = 0;\n        CROSS_PEN = 0;\n    }\n\n    // --------- Build multiple city orders ---------\n    vector<vector<int>> cityOrders;\n\n    // 1) Hilbert original (x, y)\n    cityOrders.push_back(hilbOrder);\n\n    // 2) Hilbert with flipped X: (10000 - x, y)\n    {\n        vector<pair<uint64_t,int>> v(N);\n        for (int i = 0; i < N; ++i) {\n            int fx = 10000 - cx[i];\n            int fy = cy[i];\n            uint64_t h = hilbert_order(fx, fy, HILBERT_BITS);\n            v[i] = {h, i};\n        }\n        sort(v.begin(), v.end());\n        vector<int> ord(N);\n        for (int i = 0; i < N; ++i) ord[i] = v[i].second;\n        cityOrders.push_back(std::move(ord));\n    }\n\n    // 3) Hilbert with flipped Y: (x, 10000 - y)\n    {\n        vector<pair<uint64_t,int>> v(N);\n        for (int i = 0; i < N; ++i) {\n            int fx = cx[i];\n            int fy = 10000 - cy[i];\n            uint64_t h = hilbert_order(fx, fy, HILBERT_BITS);\n            v[i] = {h, i};\n        }\n        sort(v.begin(), v.end());\n        vector<int> ord(N);\n        for (int i = 0; i < N; ++i) ord[i] = v[i].second;\n        cityOrders.push_back(std::move(ord));\n    }\n\n    // 4) Hilbert with flipped both: (10000 - x, 10000 - y)\n    {\n        vector<pair<uint64_t,int>> v(N);\n        for (int i = 0; i < N; ++i) {\n            int fx = 10000 - cx[i];\n            int fy = 10000 - cy[i];\n            uint64_t h = hilbert_order(fx, fy, HILBERT_BITS);\n            v[i] = {h, i};\n        }\n        sort(v.begin(), v.end());\n        vector<int> ord(N);\n        for (int i = 0; i < N; ++i) ord[i] = v[i].second;\n        cityOrders.push_back(std::move(ord));\n    }\n\n    // 5) Hilbert on swapped coords: (y, x)\n    {\n        vector<pair<uint64_t,int>> v(N);\n        for (int i = 0; i < N; ++i) {\n            int fx = cy[i];\n            int fy = cx[i];\n            uint64_t h = hilbert_order(fx, fy, HILBERT_BITS);\n            v[i] = {h, i};\n        }\n        sort(v.begin(), v.end());\n        vector<int> ord(N);\n        for (int i = 0; i < N; ++i) ord[i] = v[i].second;\n        cityOrders.push_back(std::move(ord));\n    }\n\n    // 6) Hilbert on (10000 - y, x)\n    {\n        vector<pair<uint64_t,int>> v(N);\n        for (int i = 0; i < N; ++i) {\n            int fx = 10000 - cy[i];\n            int fy = cx[i];\n            uint64_t h = hilbert_order(fx, fy, HILBERT_BITS);\n            v[i] = {h, i};\n        }\n        sort(v.begin(), v.end());\n        vector<int> ord(N);\n        for (int i = 0; i < N; ++i) ord[i] = v[i].second;\n        cityOrders.push_back(std::move(ord));\n    }\n\n    // 7) Lexicographic by (x, y)\n    {\n        vector<pair<pair<int,int>,int>> v(N);\n        for (int i = 0; i < N; ++i) {\n            v[i] = {{cx[i], cy[i]}, i};\n        }\n        sort(v.begin(), v.end());\n        vector<int> ord(N);\n        for (int i = 0; i < N; ++i) ord[i] = v[i].second;\n        cityOrders.push_back(std::move(ord));\n    }\n\n    // 8) Lexicographic by (y, x)\n    {\n        vector<pair<pair<int,int>,int>> v(N);\n        for (int i = 0; i < N; ++i) {\n            v[i] = {{cy[i], cx[i]}, i};\n        }\n        sort(v.begin(), v.end());\n        vector<int> ord(N);\n        for (int i = 0; i < N; ++i) ord[i] = v[i].second;\n        cityOrders.push_back(std::move(ord));\n    }\n\n    // 9) Diagonal order (x + y, x)\n    {\n        vector<pair<pair<int,int>,int>> v(N);\n        for (int i = 0; i < N; ++i) {\n            int diag = cx[i] + cy[i];\n            v[i] = {{diag, cx[i]}, i};\n        }\n        sort(v.begin(), v.end());\n        vector<int> ord(N);\n        for (int i = 0; i < N; ++i) ord[i] = v[i].second;\n        cityOrders.push_back(std::move(ord));\n    }\n\n    // 10) Anti-diagonal order (x - y, x)\n    {\n        vector<pair<pair<int,int>,int>> v(N);\n        for (int i = 0; i < N; ++i) {\n            int diag = cx[i] - cy[i];\n            v[i] = {{diag, cx[i]}, i};\n        }\n        sort(v.begin(), v.end());\n        vector<int> ord(N);\n        for (int i = 0; i < N; ++i) ord[i] = v[i].second;\n        cityOrders.push_back(std::move(ord));\n    }\n\n    // 11) Good-aware nearest neighbor order (start from first Hilbert city)\n    auto build_nn_order = [&](int startCity) {\n        vector<int> order(N);\n        vector<char> used(N, 0);\n        int cur = startCity;\n        order[0] = cur;\n        used[cur] = 1;\n        for (int pos = 1; pos < N; ++pos) {\n            int best = -1;\n            int bestCost = INT_MAX;\n            for (int j = 0; j < N; ++j) {\n                if (used[j]) continue;\n                int w = baseDist[cur][j];\n                if (B_bias > 0) {\n                    uint8_t cnt = goodCnt[cur][j];\n                    if (cnt) {\n                        int cnti = (int)cnt;\n                        if (cnti > 3) cnti = 3;\n                        int sub = B_bias * cnti * 4;\n                        w = max(0, w - sub);\n                    }\n                }\n                if (w < bestCost || (w == bestCost && j < best)) {\n                    bestCost = w;\n                    best = j;\n                }\n            }\n            if (best == -1) {\n                for (int j = 0; j < N; ++j) {\n                    if (!used[j]) { best = j; break; }\n                }\n            }\n            order[pos] = best;\n            used[best] = 1;\n            cur = best;\n        }\n        return order;\n    };\n    cityOrders.push_back(build_nn_order(hilbOrder[0]));\n    cityOrders.push_back(build_nn_order(hilbOrder[N-1]));\n\n    // 13) Global MST DFS order\n    {\n        vector<int> all(N);\n        iota(all.begin(), all.end(), 0);\n        vector<pair<int,int>> mstE;\n        buildMSTForGroup(all, mstE);\n        vector<vector<int>> adj(N);\n        adj.assign(N, {});\n        for (auto &e : mstE) {\n            int u = e.first, v = e.second;\n            adj[u].push_back(v);\n            adj[v].push_back(u);\n        }\n        vector<int> ord;\n        ord.reserve(N);\n        vector<char> vis(N, 0);\n        int root = 0;\n        for (int i = 1; i < N; ++i) {\n            if (cx[i] < cx[root] || (cx[i] == cx[root] && cy[i] < cy[root])) root = i;\n        }\n        stack<int> st;\n        st.push(root);\n        vis[root] = 1;\n        while (!st.empty()) {\n            int u = st.top(); st.pop();\n            ord.push_back(u);\n            auto &nb = adj[u];\n            sort(nb.begin(), nb.end(), [&](int a, int b) {\n                if (cx[a] != cx[b]) return cx[a] < cx[b];\n                if (cy[a] != cy[b]) return cy[a] < cy[b];\n                return a < b;\n            });\n            for (int v : nb) {\n                if (!vis[v]) {\n                    vis[v] = 1;\n                    st.push(v);\n                }\n            }\n        }\n        if ((int)ord.size() < N) {\n            vector<char> inOrd(N, 0);\n            for (int u : ord) inOrd[u] = 1;\n            for (int i = 0; i < N; ++i) if (!inOrd[i]) ord.push_back(i);\n        }\n        cityOrders.push_back(std::move(ord));\n    }\n\n    // Add reversed versions of all city orders to increase diversity\n    {\n        int origCnt = (int)cityOrders.size();\n        for (int i = 0; i < origCnt; ++i) {\n            vector<int> rev = cityOrders[i];\n            reverse(rev.begin(), rev.end());\n            cityOrders.push_back(std::move(rev));\n        }\n    }\n\n    // --------- Precompute size orders ---------\n    vector<pair<int,int>> sizeDesc, sizeAsc, sizeOrig;\n    sizeDesc.reserve(M);\n    sizeAsc.reserve(M);\n    sizeOrig.reserve(M);\n    for (int i = 0; i < M; ++i) {\n        sizeDesc.emplace_back(G_in[i], i);\n        sizeAsc.emplace_back(G_in[i], i);\n        sizeOrig.emplace_back(G_in[i], i);\n    }\n    sort(sizeDesc.begin(), sizeDesc.end(),\n         [](const auto &a, const auto &b) {\n             if (a.first != b.first) return a.first > b.first; // larger first\n             return a.second < b.second;\n         });\n    sort(sizeAsc.begin(), sizeAsc.end(),\n         [](const auto &a, const auto &b) {\n             if (a.first != b.first) return a.first < b.first; // smaller first\n             return a.second < b.second;\n         });\n\n    // Zigzag size order: largest, smallest, 2nd largest, 2nd smallest,...\n    vector<pair<int,int>> sizeZigzag;\n    {\n        vector<pair<int,int>> tmp = sizeAsc; // ascending\n        int l = 0, r = M - 1;\n        bool takeLarge = true;\n        sizeZigzag.reserve(M);\n        while (l <= r) {\n            if (takeLarge) {\n                sizeZigzag.push_back(tmp[r--]);\n            } else {\n                sizeZigzag.push_back(tmp[l++]);\n            }\n            takeLarge = !takeLarge;\n        }\n    }\n\n    // Two deterministic pseudo-random size orders\n    mt19937 rng(1234567u + (unsigned)N * 1009u + (unsigned)M * 917u);\n    vector<pair<int,int>> sizeRand1, sizeRand2;\n    if (M > 1) {\n        vector<int> idx(M);\n        iota(idx.begin(), idx.end(), 0);\n        shuffle(idx.begin(), idx.end(), rng);\n        sizeRand1.reserve(M);\n        for (int id : idx) sizeRand1.emplace_back(G_in[id], id);\n\n        shuffle(idx.begin(), idx.end(), rng);\n        sizeRand2.reserve(M);\n        for (int id : idx) sizeRand2.emplace_back(G_in[id], id);\n    } else {\n        sizeRand1 = sizeOrig;\n        sizeRand2 = sizeOrig;\n    }\n\n    vector<vector<pair<int,int>>> sizeOrders =\n        {sizeDesc, sizeAsc, sizeOrig, sizeZigzag, sizeRand1, sizeRand2};\n\n    // --------- Build candidate solutions ---------\n    vector<Candidate> candidates;\n    candidates.reserve(cityOrders.size() * sizeOrders.size());\n\n    auto build_solution = [&](const vector<int> &cityOrder,\n                              const vector<pair<int,int>> &sizeOrder) {\n        Candidate sol;\n        sol.groups.assign(M, {});\n        int ptr = 0;\n        for (auto &p : sizeOrder) {\n            int sz = p.first;\n            int gid = p.second;\n            sol.groups[gid].reserve(sz);\n            for (int k = 0; k < sz; ++k) {\n                sol.groups[gid].push_back(cityOrder[ptr++]);\n            }\n        }\n        sol.edges.assign(M, {});\n        for (int g = 0; g < M; ++g) {\n            buildMSTForGroup(sol.groups[g], sol.edges[g]);\n        }\n\n        long long cost = 0;\n        for (int g = 0; g < M; ++g) {\n            for (auto &e : sol.edges[g]) {\n                int u = e.first;\n                int v = e.second;\n                int d2 = baseDist[u][v];\n                double d = std::sqrt((double)d2);\n                cost += (long long)std::floor(d);\n            }\n        }\n\n        if (!goodEdges.empty() && CROSS_PEN > 0) {\n            vector<int> cityGroup(N, -1);\n            for (int g = 0; g < M; ++g) {\n                for (int c : sol.groups[g]) {\n                    cityGroup[c] = g;\n                }\n            }\n            long long pen = 0;\n            for (auto &e : goodEdges) {\n                int u = e.first, v = e.second;\n                if (cityGroup[u] != cityGroup[v]) {\n                    uint8_t cnt = goodCnt[u][v];\n                    int cnti = (int)cnt;\n                    if (cnti > 3) cnti = 3;\n                    pen += (long long)CROSS_PEN * cnti;\n                }\n            }\n            cost += pen;\n        }\n\n        sol.cost = cost;\n        candidates.push_back(std::move(sol));\n    };\n\n    for (const auto &ord : cityOrders) {\n        for (const auto &szOrd : sizeOrders) {\n            build_solution(ord, szOrd);\n        }\n    }\n\n    // --------- Choose best candidate ---------\n    int bestIdx = 0;\n    long long bestCost = candidates[0].cost;\n    for (int i = 1; i < (int)candidates.size(); ++i) {\n        if (candidates[i].cost < bestCost) {\n            bestCost = candidates[i].cost;\n            bestIdx = i;\n        }\n    }\n    Candidate &bestSol = candidates[bestIdx];\n\n    // --------- Output final answer ---------\n    cout << \"!\\n\";\n    for (int g = 0; g < M; ++g) {\n        const auto &nodes = bestSol.groups[g];\n        int sz = (int)nodes.size();\n        for (int i = 0; i < sz; ++i) {\n            if (i) cout << ' ';\n            cout << nodes[i];\n        }\n        cout << '\\n';\n        const auto &edges = bestSol.edges[g];\n        for (auto &e : edges) {\n            cout << e.first << ' ' << e.second << '\\n';\n        }\n    }\n\n    return 0;\n}","ahc046":"#include <bits/stdc++.h>\nusing namespace std;\n\n// Directions: Up, Down, Left, Right\nconst int DX[4] = {-1, 1,  0, 0};\nconst int DY[4] = { 0, 0, -1, 1};\nconst char DCH[4] = {'U', 'D', 'L', 'R'};\n\n// N=20, M=40\nint N, M;\n\n// Precomputed slide destinations with NO internal blocks.\n// slideDest0[v][d] = destination cell index when sliding from v in direction d.\nint slideDest0[400][4];\n\ninline int idx(int x, int y) { return x * 20 + y; } // grid is 20x20\n\nconst int INF = 1e9;\n\n// Number of special candidate block cells\nconst int B = 6;\nconst int MASKN = 1 << B;\n\n// Max states for global BFS: (M+1) * N * N * (1<<B) = 41 * 400 * 64 = 1,049,600\nconst int MAX_STATES = 1100000;\n\n// Global BFS arrays\nstatic int  distArr[MAX_STATES];\nstatic int  parentArr[MAX_STATES];\nstatic char parentAct[MAX_STATES];\nstatic char parentDir[MAX_STATES];\nstatic int  qArr[MAX_STATES];\n\n// Candidate block cells and mapping from cell -> candidate index\nint candX[B], candY[B];\nint candId[20][20];\n\n// Precompute slideDest0 on empty grid (no internal blocks)\nvoid init_slide_dest0() {\n    for (int x = 0; x < 20; ++x) {\n        for (int y = 0; y < 20; ++y) {\n            int v = idx(x, y);\n            for (int d = 0; d < 4; ++d) {\n                int nx = x, ny = y;\n                while (true) {\n                    int tx = nx + DX[d];\n                    int ty = ny + DY[d];\n                    if (tx < 0 || tx >= 20 || ty < 0 || ty >= 20) break;\n                    nx = tx;\n                    ny = ty;\n                }\n                slideDest0[v][d] = idx(nx, ny);\n            }\n        }\n    }\n}\n\n// Slide with current mask of active blocks.\n// We simulate step-by-step to guarantee we never stop on a blocked cell.\ninline int slide_with_mask(int x, int y, int d, int mask) {\n    int nx = x, ny = y;\n    while (true) {\n        int tx = nx + DX[d];\n        int ty = ny + DY[d];\n        if (tx < 0 || tx >= 20 || ty < 0 || ty >= 20) break;\n        int cid = candId[tx][ty];\n        if (cid >= 0 && (mask & (1 << cid))) break; // stop before block\n        nx = tx;\n        ny = ty;\n    }\n    return idx(nx, ny);\n}\n\n// Encode/decode state: (ti, x, y, mask) -> integer\n// ti in [0..M], x,y in [0..19], mask in [0..(1<<B)-1]\ninline int encode(int ti, int x, int y, int mask) {\n    // Layout: (((ti * 20 + x) * 20 + y) << B) | mask\n    return ((((ti * 20 + x) * 20 + y) << B) | mask);\n}\n\ninline void decode(int id, int &ti, int &x, int &y, int &mask) {\n    mask = id & (MASKN - 1);\n    int tmp = id >> B;\n    y = tmp % 20;\n    tmp /= 20;\n    x = tmp % 20;\n    tmp /= 20;\n    ti = tmp;\n}\n\n// Baseline no-block solution: per-segment BFS with slides to borders.\n// Returns action sequence, total cost, and the full sequence of visited cells.\nvoid compute_baseline(const vector<pair<int,int>> &points,\n                      vector<char> &baseActs,\n                      vector<char> &baseDirs,\n                      int &baseCost,\n                      vector<int> &pathCells) {\n    static int dist0[400];\n    static int prev0[400];\n    static char act0[400], dir0[400];\n\n    baseActs.clear();\n    baseDirs.clear();\n    baseCost = 0;\n    pathCells.clear();\n\n    int startIdx = idx(points[0].first, points[0].second);\n    pathCells.push_back(startIdx);\n\n    for (int seg = 1; seg < (int)points.size(); ++seg) {\n        int sx = points[seg - 1].first;\n        int sy = points[seg - 1].second;\n        int gx = points[seg].first;\n        int gy = points[seg].second;\n        int sIdx = idx(sx, sy);\n        int gIdx = idx(gx, gy);\n\n        // BFS on empty grid with slideDest0\n        for (int i = 0; i < 400; ++i) {\n            dist0[i] = INF;\n            prev0[i] = -1;\n        }\n        queue<int> q;\n        dist0[sIdx] = 0;\n        q.push(sIdx);\n\n        while (!q.empty()) {\n            int v = q.front(); q.pop();\n            if (v == gIdx) break;\n            int dv = dist0[v];\n            int x = v / 20;\n            int y = v % 20;\n            for (int k = 0; k < 4; ++k) {\n                // Move\n                {\n                    int nx = x + DX[k];\n                    int ny = y + DY[k];\n                    if (0 <= nx && nx < 20 && 0 <= ny && ny < 20) {\n                        int to = idx(nx, ny);\n                        if (dist0[to] > dv + 1) {\n                            dist0[to] = dv + 1;\n                            prev0[to] = v;\n                            act0[to] = 'M';\n                            dir0[to] = DCH[k];\n                            q.push(to);\n                        }\n                    }\n                }\n                // Slide\n                {\n                    int to = slideDest0[v][k];\n                    if (to != v && dist0[to] > dv + 1) {\n                        dist0[to] = dv + 1;\n                        prev0[to] = v;\n                        act0[to] = 'S';\n                        dir0[to] = DCH[k];\n                        q.push(to);\n                    }\n                }\n            }\n        }\n\n        int segCost = dist0[gIdx];\n        if (segCost >= INF) {\n            baseCost = 2 * 20 * M;\n            return;\n        }\n        baseCost += segCost;\n\n        // Reconstruct segment path nodes and actions\n        vector<int> nodes;\n        vector<char> ra, rd;\n        int cur = gIdx;\n        while (cur != sIdx) {\n            int p = prev0[cur];\n            if (p == -1) { nodes.clear(); ra.clear(); rd.clear(); break; }\n            nodes.push_back(cur);\n            ra.push_back(act0[cur]);\n            rd.push_back(dir0[cur]);\n            cur = p;\n        }\n        nodes.push_back(sIdx);\n\n        reverse(nodes.begin(), nodes.end());\n        reverse(ra.begin(), ra.end());\n        reverse(rd.begin(), rd.end());\n\n        // Append path cells (excluding first, which equals previous segment end)\n        for (int i = 1; i < (int)nodes.size(); ++i) {\n            pathCells.push_back(nodes[i]);\n        }\n        // Append actions\n        for (int i = 0; i < (int)ra.size(); ++i) {\n            baseActs.push_back(ra[i]);\n            baseDirs.push_back(rd[i]);\n        }\n    }\n}\n\n// Candidate set 0: path-based + cross fallback\nvoid build_candidates_path_based(const vector<int> &pathCells,\n                                 const bool isTarget[20][20]) {\n    bool usedCell[400];\n    memset(usedCell, 0, sizeof(usedCell));\n    vector<pair<int,int>> candPos;\n    candPos.reserve(B);\n\n    int L = (int)pathCells.size();\n\n    // 1) Central non-target path cells\n    if (L > 0) {\n        for (int posIdx = 0; posIdx < L && (int)candPos.size() < B; ++posIdx) {\n            int cell = pathCells[posIdx];\n            int x = cell / 20;\n            int y = cell % 20;\n            if (isTarget[x][y]) continue;\n            if (x < 4 || x > 15 || y < 4 || y > 15) continue;\n            if (usedCell[cell]) continue;\n            usedCell[cell] = true;\n            candPos.emplace_back(x, y);\n        }\n    }\n\n    // 2) Other non-target path cells\n    if ((int)candPos.size() < B && L > 0) {\n        for (int posIdx = 0; posIdx < L && (int)candPos.size() < B; ++posIdx) {\n            int cell = pathCells[posIdx];\n            int x = cell / 20;\n            int y = cell % 20;\n            if (isTarget[x][y]) continue;\n            if (usedCell[cell]) continue;\n            usedCell[cell] = true;\n            candPos.emplace_back(x, y);\n        }\n    }\n\n    // 3) Cross pattern as backup candidates\n    const pair<int,int> crossCand[B] = {\n        {10, 10},\n        { 6, 10},\n        {14, 10},\n        {10,  6},\n        {10, 14},\n        {10,  2}\n    };\n\n    for (int i = 0; i < B && (int)candPos.size() < B; ++i) {\n        int x = crossCand[i].first;\n        int y = crossCand[i].second;\n        int cell = idx(x, y);\n        if (usedCell[cell]) continue;\n        usedCell[cell] = true;\n        candPos.emplace_back(x, y);\n    }\n\n    // 4) Fill remaining with arbitrary non-target unused cells.\n    if ((int)candPos.size() < B) {\n        for (int x = 0; x < 20 && (int)candPos.size() < B; ++x) {\n            for (int y = 0; y < 20 && (int)candPos.size() < B; ++y) {\n                if (isTarget[x][y]) continue;\n                int cell = idx(x, y);\n                if (!usedCell[cell]) {\n                    usedCell[cell] = true;\n                    candPos.emplace_back(x, y);\n                }\n            }\n        }\n    }\n\n    // Assign candidate arrays and mapping\n    for (int i = 0; i < B; ++i) {\n        candX[i] = candPos[i].first;\n        candY[i] = candPos[i].second;\n    }\n\n    for (int i = 0; i < 20; ++i)\n        for (int j = 0; j < 20; ++j)\n            candId[i][j] = -1;\n    for (int i = 0; i < B; ++i) {\n        candId[candX[i]][candY[i]] = i;\n    }\n}\n\n// Candidate set 1: fixed central cross\nvoid build_candidates_cross1() {\n    const pair<int,int> crossCand[B] = {\n        {10, 10},\n        { 6, 10},\n        {14, 10},\n        {10,  6},\n        {10, 14},\n        {10,  2}\n    };\n    for (int i = 0; i < B; ++i) {\n        candX[i] = crossCand[i].first;\n        candY[i] = crossCand[i].second;\n    }\n    for (int i = 0; i < 20; ++i)\n        for (int j = 0; j < 20; ++j)\n            candId[i][j] = -1;\n    for (int i = 0; i < B; ++i) {\n        candId[candX[i]][candY[i]] = i;\n    }\n}\n\n// Candidate set 2: a slightly different cross\nvoid build_candidates_cross2() {\n    const pair<int,int> crossCand[B] = {\n        {10, 10},\n        { 3, 10},\n        {16, 10},\n        {10,  3},\n        {10, 16},\n        {10,  0}\n    };\n    for (int i = 0; i < B; ++i) {\n        candX[i] = crossCand[i].first;\n        candY[i] = crossCand[i].second;\n    }\n    for (int i = 0; i < 20; ++i)\n        for (int j = 0; j < 20; ++j)\n            candId[i][j] = -1;\n    for (int i = 0; i < B; ++i) {\n        candId[candX[i]][candY[i]] = i;\n    }\n}\n\n// Candidate set 3: cross around the center of gravity of targets\nvoid build_candidates_target_center(const vector<pair<int,int>> &points) {\n    long long sumX = 0, sumY = 0;\n    for (auto &p : points) {\n        sumX += p.first;\n        sumY += p.second;\n    }\n    int cx = (int)((sumX + M / 2) / M);\n    int cy = (int)((sumY + M / 2) / M);\n    cx = max(0, min(19, cx));\n    cy = max(0, min(19, cy));\n\n    pair<int,int> cand[B] = {\n        {cx, cy},\n        {max(cx - 4, 0), cy},\n        {min(cx + 4, 19), cy},\n        {cx, max(cy - 4, 0)},\n        {cx, min(cy + 4, 19)},\n        {max(cx - 4, 0), max(cy - 4, 0)}\n    };\n\n    bool used[20][20];\n    memset(used, 0, sizeof(used));\n\n    int cnt = 0;\n    for (int i = 0; i < B; ++i) {\n        int x = cand[i].first;\n        int y = cand[i].second;\n        if (!used[x][y]) {\n            used[x][y] = true;\n            candX[cnt] = x;\n            candY[cnt] = y;\n            cnt++;\n        }\n    }\n    // If duplicates happened (rare), fill remaining arbitrarily\n    for (int x = 0; x < 20 && cnt < B; ++x) {\n        for (int y = 0; y < 20 && cnt < B; ++y) {\n            if (!used[x][y]) {\n                used[x][y] = true;\n                candX[cnt] = x;\n                candY[cnt] = y;\n                cnt++;\n            }\n        }\n    }\n\n    for (int i = 0; i < 20; ++i)\n        for (int j = 0; j < 20; ++j)\n            candId[i][j] = -1;\n    for (int i = 0; i < B; ++i) {\n        candId[candX[i]][candY[i]] = i;\n    }\n}\n\n// Run global BFS for current candidate set, limited to paths shorter than bestCost.\n// If an improved path is found, update bestCost and bestActs/bestDirs.\nvoid try_with_current_candidates(const vector<pair<int,int>> &points,\n                                 int TOT,\n                                 int &bestCost,\n                                 vector<char> &bestActs,\n                                 vector<char> &bestDirs) {\n    int limit = bestCost;\n\n    // Initialize BFS arrays\n    for (int i = 0; i < TOT; ++i) {\n        distArr[i] = INF;\n        parentArr[i] = -1;\n    }\n\n    int sx = points[0].first;\n    int sy = points[0].second;\n    int startTi = 1;   // next target index to visit is 1\n    int startMask = 0; // no blocks initially\n    int startId = encode(startTi, sx, sy, startMask);\n\n    distArr[startId] = 0;\n    int qh = 0, qt = 0;\n    qArr[qt++] = startId;\n\n    int lastTx = points[M-1].first;\n    int lastTy = points[M-1].second;\n    int goalId = -1;\n\n    while (qh < qt) {\n        int id = qArr[qh++];\n        int dcur = distArr[id];\n        if (dcur >= limit) continue; // cannot improve\n\n        int ti, x, y, mask;\n        decode(id, ti, x, y, mask);\n\n        if (ti == M && x == lastTx && y == lastTy) {\n            goalId = id;\n            break;\n        }\n\n        // Moves and slides\n        for (int k = 0; k < 4; ++k) {\n            // Move\n            {\n                int nx = x + DX[k];\n                int ny = y + DY[k];\n                if (0 <= nx && nx < 20 && 0 <= ny && ny < 20) {\n                    int cid = candId[nx][ny];\n                    bool blocked = (cid >= 0) && (mask & (1 << cid));\n                    if (!blocked) {\n                        int nti = ti;\n                        if (ti < M &&\n                            nx == points[ti].first &&\n                            ny == points[ti].second) {\n                            nti++;\n                        }\n                        int nid = encode(nti, nx, ny, mask);\n                        int nd = dcur + 1;\n                        if (nid < TOT && nd < limit && distArr[nid] > nd) {\n                            distArr[nid] = nd;\n                            parentArr[nid] = id;\n                            parentAct[nid] = 'M';\n                            parentDir[nid] = DCH[k];\n                            qArr[qt++] = nid;\n                        }\n                    }\n                }\n            }\n            // Slide\n            {\n                int dest = slide_with_mask(x, y, k, mask);\n                if (dest != idx(x, y)) {\n                    int nx = dest / 20;\n                    int ny = dest % 20;\n                    int nti = ti;\n                    if (ti < M &&\n                        nx == points[ti].first &&\n                        ny == points[ti].second) {\n                        nti++;\n                    }\n                    int nid = encode(nti, nx, ny, mask);\n                    int nd = dcur + 1;\n                    if (nid < TOT && nd < limit && distArr[nid] > nd) {\n                        distArr[nid] = nd;\n                        parentArr[nid] = id;\n                        parentAct[nid] = 'S';\n                        parentDir[nid] = DCH[k];\n                        qArr[qt++] = nid;\n                    }\n                }\n            }\n        }\n\n        // Alter (toggle block at adjacent candidate cells)\n        for (int k = 0; k < 4; ++k) {\n            int ax = x + DX[k];\n            int ay = y + DY[k];\n            if (0 <= ax && ax < 20 && 0 <= ay && ay < 20) {\n                int cid = candId[ax][ay];\n                if (cid >= 0) {\n                    int nmask = mask ^ (1 << cid);\n                    int nid = encode(ti, x, y, nmask);\n                    int nd = dcur + 1;\n                    if (nid < TOT && nd < limit && distArr[nid] > nd) {\n                        distArr[nid] = nd;\n                        parentArr[nid] = id;\n                        parentAct[nid] = 'A';\n                        parentDir[nid] = DCH[k];\n                        qArr[qt++] = nid;\n                    }\n                }\n            }\n        }\n    }\n\n    if (goalId == -1) return;\n\n    int cost = distArr[goalId];\n    if (cost >= bestCost) return;\n\n    // Reconstruct path from goalId to startId\n    vector<char> ra, rd;\n    int cur = goalId;\n    while (cur != startId) {\n        ra.push_back(parentAct[cur]);\n        rd.push_back(parentDir[cur]);\n        cur = parentArr[cur];\n        if (cur == -1) { ra.clear(); rd.clear(); break; } // safety\n    }\n    if (ra.empty() && cost > 0) return; // failed reconstruction\n\n    bestCost = cost;\n    bestActs.assign(ra.rbegin(), ra.rend());\n    bestDirs.assign(rd.rbegin(), rd.rend());\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> M; // N=20, M=40\n    vector<pair<int,int>> points(M);\n    for (int i = 0; i < M; ++i) {\n        cin >> points[i].first >> points[i].second;\n    }\n\n    init_slide_dest0();\n\n    // Mark target cells\n    bool isTarget[20][20];\n    memset(isTarget, 0, sizeof(isTarget));\n    for (int i = 0; i < M; ++i) {\n        isTarget[points[i].first][points[i].second] = true;\n    }\n\n    // Baseline no-block solution\n    vector<char> baseActs, baseDirs;\n    vector<int> pathCells;\n    int baselineCost;\n    compute_baseline(points, baseActs, baseDirs, baselineCost, pathCells);\n    if (baselineCost > 2 * 20 * M) baselineCost = 2 * 20 * M;\n\n    // Total states (constant for B=6)\n    int TOT = (M + 1) * 20 * 20 * MASKN;\n    if (TOT > MAX_STATES) TOT = MAX_STATES; // safety\n\n    // Global best = baseline\n    int bestCost = baselineCost;\n    vector<char> bestActs = baseActs;\n    vector<char> bestDirs = baseDirs;\n\n    // Candidate set 0: path-based + cross fallback\n    build_candidates_path_based(pathCells, isTarget);\n    try_with_current_candidates(points, TOT, bestCost, bestActs, bestDirs);\n\n    // Candidate set 1: fixed cross near center\n    build_candidates_cross1();\n    try_with_current_candidates(points, TOT, bestCost, bestActs, bestDirs);\n\n    // Candidate set 2: another fixed cross pattern\n    build_candidates_cross2();\n    try_with_current_candidates(points, TOT, bestCost, bestActs, bestDirs);\n\n    // Candidate set 3: cross around target center of gravity\n    build_candidates_target_center(points);\n    try_with_current_candidates(points, TOT, bestCost, bestActs, bestDirs);\n\n    // Output best action sequence\n    for (size_t i = 0; i < bestActs.size(); ++i) {\n        cout << bestActs[i] << ' ' << bestDirs[i] << '\\n';\n    }\n\n    return 0;\n}"}}}